From ea0eac1bf44763ebd94546ffa80ccd951dc77781 Mon Sep 17 00:00:00 2001 From: dpapworth-qc <50959025+dpapworth-qc@users.noreply.github.com> Date: Wed, 28 Jan 2026 18:09:36 +0000 Subject: [PATCH 01/48] Remove quantcastId (#14045) * Remove quantcastIdSystem. * Remove references to quantcastId. --------- Co-authored-by: Demetrio Girardi --- .../gpt/raveltechRtdProvider_example.html | 3 - integrationExamples/gpt/userId_example.html | 3 - metadata/modules.json | 7 - modules/.submodules.json | 3 +- modules/quantcastIdSystem.js | 230 ---------- modules/quantcastIdSystem.md | 46 -- modules/teadsBidAdapter.js | 1 - test/spec/modules/quantcastIdSystem_spec.js | 405 ------------------ test/spec/modules/teadsBidAdapter_spec.js | 2 - 9 files changed, 1 insertion(+), 699 deletions(-) delete mode 100644 modules/quantcastIdSystem.js delete mode 100644 modules/quantcastIdSystem.md delete mode 100644 test/spec/modules/quantcastIdSystem_spec.js diff --git a/integrationExamples/gpt/raveltechRtdProvider_example.html b/integrationExamples/gpt/raveltechRtdProvider_example.html index 8a0be63b6b8..4523ad17ec9 100644 --- a/integrationExamples/gpt/raveltechRtdProvider_example.html +++ b/integrationExamples/gpt/raveltechRtdProvider_example.html @@ -256,9 +256,6 @@ "expires": 28 } }, - { - "name": "quantcastId" - }, { "name": "criteo" }, diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 3861037b401..618874f0bd5 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -234,9 +234,6 @@ "expires": 28 } }, - { - "name": "quantcastId" - }, { "name": "criteo" }, diff --git a/metadata/modules.json b/metadata/modules.json index b078a117e6e..8ff26369262 100644 --- a/metadata/modules.json +++ b/metadata/modules.json @@ -5797,13 +5797,6 @@ "disclosureURL": null, "aliasOf": null }, - { - "componentType": "userId", - "componentName": "quantcastId", - "gvlid": "11", - "disclosureURL": null, - "aliasOf": null - }, { "componentType": "userId", "componentName": "rewardedInterestId", diff --git a/modules/.submodules.json b/modules/.submodules.json index c6274fdcbfd..1ee8e440f1b 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -49,7 +49,6 @@ "pubProvidedIdSystem", "publinkIdSystem", "pubmaticIdSystem", - "quantcastIdSystem", "rewardedInterestIdSystem", "sharedIdSystem", "taboolaIdSystem", @@ -147,4 +146,4 @@ "topLevelPaapi" ] } -} \ No newline at end of file +} diff --git a/modules/quantcastIdSystem.js b/modules/quantcastIdSystem.js deleted file mode 100644 index aeccceb0d10..00000000000 --- a/modules/quantcastIdSystem.js +++ /dev/null @@ -1,230 +0,0 @@ -/** - * This module adds QuantcastID to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/quantcastIdSystem - * @requires module:modules/userId - */ - -import {submodule} from '../src/hook.js' -import {getStorageManager} from '../src/storageManager.js'; -import { triggerPixel, logInfo } from '../src/utils.js'; -import { uspDataHandler, coppaDataHandler, gdprDataHandler } from '../src/adapterManager.js'; -import {MODULE_TYPE_UID} from '../src/activities/modules.js'; - -/** - * @typedef {import('../modules/userId/index.js').Submodule} Submodule - */ - -const QUANTCAST_FPA = '__qca'; -const DEFAULT_COOKIE_EXP_DAYS = 392; // (13 months - 2 days) -const DAY_MS = 86400000; -const PREBID_PCODE = 'p-KceJUEvXN48CE'; -const QSERVE_URL = 'https://pixel.quantserve.com/pixel'; -const QUANTCAST_VENDOR_ID = '11'; -const PURPOSE_DATA_COLLECT = '1'; -const PURPOSE_PRODUCT_IMPROVEMENT = '10'; -const QC_TCF_REQUIRED_PURPOSES = [PURPOSE_DATA_COLLECT, PURPOSE_PRODUCT_IMPROVEMENT]; -const QC_TCF_CONSENT_FIRST_PURPOSES = [PURPOSE_DATA_COLLECT]; -const QC_TCF_CONSENT_ONLY_PUPROSES = [PURPOSE_DATA_COLLECT]; -const GDPR_PRIVACY_STRING = gdprDataHandler.getConsentData(); -const US_PRIVACY_STRING = uspDataHandler.getConsentData(); -const MODULE_NAME = 'quantcastId'; - -export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME}); - -export function firePixel(clientId, cookieExpDays = DEFAULT_COOKIE_EXP_DAYS) { - // check for presence of Quantcast Measure tag _qevent obj and publisher provided clientID - if (!window._qevents && clientId) { - var fpa = storage.getCookie(QUANTCAST_FPA); - var fpan = '0'; - var domain = quantcastIdSubmodule.findRootDomain(); - var now = new Date(); - var usPrivacyParamString = ''; - var firstPartyParamStrings; - var gdprParamStrings; - - if (!fpa) { - var et = now.getTime(); - var expires = new Date(et + (cookieExpDays * DAY_MS)).toGMTString(); - var rand = Math.round(Math.random() * 2147483647); - fpa = `B0-${rand}-${et}`; - fpan = '1'; - storage.setCookie(QUANTCAST_FPA, fpa, expires, '/', domain, null); - } - - firstPartyParamStrings = `&fpan=${fpan}&fpa=${fpa}`; - gdprParamStrings = '&gdpr=0'; - if (GDPR_PRIVACY_STRING && typeof GDPR_PRIVACY_STRING.gdprApplies === 'boolean' && GDPR_PRIVACY_STRING.gdprApplies) { - gdprParamStrings = `gdpr=1&gdpr_consent=${GDPR_PRIVACY_STRING.consentString}`; - } - if (US_PRIVACY_STRING && typeof US_PRIVACY_STRING === 'string') { - usPrivacyParamString = `&us_privacy=${US_PRIVACY_STRING}`; - } - - const url = QSERVE_URL + - '?d=' + domain + - '&client_id=' + clientId + - '&a=' + PREBID_PCODE + - usPrivacyParamString + - gdprParamStrings + - firstPartyParamStrings; - - triggerPixel(url); - } -}; - -export function hasGDPRConsent(gdprConsent) { - // Check for GDPR consent for purpose 1 and 10, and drop request if consent has not been given - // Remaining consent checks are performed server-side. - if (gdprConsent && typeof gdprConsent.gdprApplies === 'boolean' && gdprConsent.gdprApplies) { - if (!gdprConsent.vendorData) { - return false; - } - return checkTCFv2(gdprConsent.vendorData); - } - return true; -} - -export function checkTCFv2(vendorData, requiredPurposes = QC_TCF_REQUIRED_PURPOSES) { - var gdprApplies = vendorData.gdprApplies; - var purposes = vendorData.purpose; - var vendors = vendorData.vendor; - var qcConsent = vendors && vendors.consents && vendors.consents[QUANTCAST_VENDOR_ID]; - var qcInterest = vendors && vendors.legitimateInterests && vendors.legitimateInterests[QUANTCAST_VENDOR_ID]; - var restrictions = vendorData.publisher ? vendorData.publisher.restrictions : {}; - - if (!gdprApplies) { - return true; - } - - return requiredPurposes.map(function(purpose) { - var purposeConsent = purposes.consents ? purposes.consents[purpose] : false; - var purposeInterest = purposes.legitimateInterests ? purposes.legitimateInterests[purpose] : false; - - var qcRestriction = restrictions && restrictions[purpose] - ? restrictions[purpose][QUANTCAST_VENDOR_ID] - : null; - - if (qcRestriction === 0) { - return false; - } - - // Seek consent or legitimate interest based on our default legal - // basis for the purpose, falling back to the other if possible. - if ( - // we have positive vendor consent - qcConsent && - // there is positive purpose consent - purposeConsent && - // publisher does not require legitimate interest - qcRestriction !== 2 && - // purpose is a consent-first purpose or publisher has explicitly restricted to consent - (QC_TCF_CONSENT_FIRST_PURPOSES.indexOf(purpose) !== -1 || qcRestriction === 1) - ) { - return true; - } else if ( - // publisher does not require consent - qcRestriction !== 1 && - // we have legitimate interest for vendor - qcInterest && - // there is legitimate interest for purpose - purposeInterest && - // purpose's legal basis does not require consent - QC_TCF_CONSENT_ONLY_PUPROSES.indexOf(purpose) === -1 && - // purpose is a legitimate-interest-first purpose or publisher has explicitly restricted to legitimate interest - (QC_TCF_CONSENT_FIRST_PURPOSES.indexOf(purpose) === -1 || qcRestriction === 2) - ) { - return true; - } - - return false; - }).reduce(function(a, b) { - return a && b; - }, true); -} - -/** - * tests if us_privacy consent string is present, us_privacy applies, and notice_given / do-not-sell is set to yes - * @returns {boolean} - */ -export function hasCCPAConsent(usPrivacyConsent) { - if ( - usPrivacyConsent && - typeof usPrivacyConsent === 'string' && - usPrivacyConsent.length === 4 && - usPrivacyConsent.charAt(1) === 'Y' && - usPrivacyConsent.charAt(2) === 'Y' - ) { - return false - } - return true; -} - -/** @type {Submodule} */ -export const quantcastIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - - /** - * Vendor id of Quantcast - * @type {Number} - */ - gvlid: QUANTCAST_VENDOR_ID, - - /** - * decode the stored id value for passing to bid requests - * @function - * @returns {{quantcastId: string} | undefined} - */ - decode(value) { - return value; - }, - - /** - * read Quantcast first party cookie and pass it along in quantcastId - * @function - * @returns {{id: {quantcastId: string} | undefined}}} - */ - getId(config) { - // Consent signals are currently checked on the server side. - const fpa = storage.getCookie(QUANTCAST_FPA); - - const coppa = coppaDataHandler.getCoppa(); - - if (coppa || !hasCCPAConsent(US_PRIVACY_STRING) || !hasGDPRConsent(GDPR_PRIVACY_STRING)) { - var expired = new Date(0).toUTCString(); - var domain = quantcastIdSubmodule.findRootDomain(); - logInfo('QuantcastId: Necessary consent not present for Id, exiting QuantcastId'); - storage.setCookie(QUANTCAST_FPA, '', expired, '/', domain, null); - return undefined; - } - - const configParams = (config && config.params) || {}; - const storageParams = (config && config.storage) || {}; - - var clientId = configParams.clientId || ''; - var cookieExpDays = storageParams.expires || DEFAULT_COOKIE_EXP_DAYS; - - // Callbacks on Event Listeners won't trigger if the event is already complete so this check is required - if (document.readyState === 'complete') { - firePixel(clientId, cookieExpDays); - } else { - window.addEventListener('load', function () { - firePixel(clientId, cookieExpDays); - }); - } - - return { id: fpa ? { quantcastId: fpa } : undefined }; - }, - eids: { - 'quantcastId': { - source: 'quantcast.com', - atype: 1 - }, - } -}; - -submodule('userId', quantcastIdSubmodule); diff --git a/modules/quantcastIdSystem.md b/modules/quantcastIdSystem.md deleted file mode 100644 index 7e90764432b..00000000000 --- a/modules/quantcastIdSystem.md +++ /dev/null @@ -1,46 +0,0 @@ -#### Overview - -``` -Module Name: Quantcast Id System -Module Type: Id System -Maintainer: asig@quantcast.com -``` - -#### Description - - The Prebid Quantcast ID module stores a Quantcast ID in a first party cookie. The ID is then made available in the bid request. The ID from the cookie added in the bidstream allows Quantcast to more accurately bid on publisher inventories without third party cookies, which can result in better monetization across publisher sites from Quantcast. And, it’s free to use! For easier integration, you can work with one of our SSP partners, like PubMatic, who can facilitate the legal process as well as the software integration for you. - - Add it to your Prebid.js package with: - - `gulp build --modules=userId,quantcastIdSystem` - - Quantcast’s privacy policies for the services rendered can be found at - https://www.quantcast.com/privacy/ - - Publishers deploying the module are responsible for ensuring legally required notices and choices for users. - - The Quantcast ID module will only perform any action and return an ID in situations where: - 1. the publisher has not set a ‘coppa' flag on the prebid configuration on their site (see [pbjs.setConfig.coppa](https://docs.prebid.org/dev-docs/publisher-api-reference/setConfig.html#setConfig-coppa)) - 2. there is not a IAB us-privacy string indicating the digital property has provided user notice and the user has made a choice to opt out of sale - 3. if GDPR applies, an IAB TCF v2 string exists indicating that Quantcast does not have consent for purpose 1 (cookies, device identifiers, or other information can be stored or accessed on your device for the purposes presented to you), or an established legal basis (by default legitimate interest) for purpose 10 (your data can be used to improve existing systems and software, and to develop new products). - - #### Quantcast ID Configuration - - | Param under userSync.userIds[] | Scope | Type | Description | Example | - | --- | --- | --- | --- | --- | - | name | Required | String | `"quantcastId"` | `"quantcastId"` | - | params | Optional | Object | Details for Quantcast initialization. | | - | params.ClientID | Optional | String | Optional parameter for Quantcast prebid managed service partners. The parameter is not required for websites with Quantcast Measure tag. Reach out to Quantcast for ClientID if you are not an existing Quantcast prebid managed service partner: quantcast-idsupport@quantcast.com. | | - - - #### Quantcast ID Example - -```js - pbjs.setConfig({ - userSync: { - userIds: [{ - name: "quantcastId" - }] - } - }); -``` diff --git a/modules/teadsBidAdapter.js b/modules/teadsBidAdapter.js index dbdda501658..17fec332a02 100644 --- a/modules/teadsBidAdapter.js +++ b/modules/teadsBidAdapter.js @@ -201,7 +201,6 @@ function getSharedViewerIdParameters(validBidRequests) { id5Id: 'id5-sync.com', // id5IdSystem criteoId: 'criteo.com', // criteoIdSystem yahooConnectId: 'yahoo.com', // connectIdSystem - quantcastId: 'quantcast.com', // quantcastIdSystem epsilonPublisherLinkId: 'epsilon.com', // publinkIdSystem publisherFirstPartyViewerId: 'pubcid.org', // sharedIdSystem merkleId: 'merkleinc.com', // merkleIdSystem diff --git a/test/spec/modules/quantcastIdSystem_spec.js b/test/spec/modules/quantcastIdSystem_spec.js deleted file mode 100644 index 157c00e7567..00000000000 --- a/test/spec/modules/quantcastIdSystem_spec.js +++ /dev/null @@ -1,405 +0,0 @@ -import { quantcastIdSubmodule, storage, firePixel, hasCCPAConsent, hasGDPRConsent, checkTCFv2 } from 'modules/quantcastIdSystem.js'; -import * as utils from 'src/utils.js'; -import {coppaDataHandler} from 'src/adapterManager'; -import {attachIdSystem} from '../../../modules/userId/index.js'; -import {createEidsArray} from '../../../modules/userId/eids.js'; -import {expect} from 'chai/index.mjs'; - -describe('QuantcastId module', function () { - beforeEach(function() { - sinon.stub(coppaDataHandler, 'getCoppa'); - sinon.stub(utils, 'triggerPixel'); - sinon.stub(window, 'addEventListener'); - }); - - afterEach(function () { - utils.triggerPixel.restore(); - coppaDataHandler.getCoppa.restore(); - window.addEventListener.restore(); - }); - - it('getId() should return a quantcast id when the Quantcast first party cookie exists', function () { - sinon.stub(storage, 'getCookie').returns('P0-TestFPA'); - const id = quantcastIdSubmodule.getId(); - expect(id).to.be.deep.equal({id: {quantcastId: 'P0-TestFPA'}}); - storage.getCookie.restore(); - }); - - it('getId() should return an empty id when the Quantcast first party cookie is missing', function () { - const id = quantcastIdSubmodule.getId(); - expect(id).to.be.deep.equal({id: undefined}); - }); -}); - -describe('QuantcastId fire pixel', function () { - beforeEach(function () { - storage.setCookie('__qca', '', 'Thu, 01 Jan 1970 00:00:00 GMT'); - sinon.stub(storage, 'setCookie'); - sinon.stub(utils, 'triggerPixel'); - }); - - afterEach(function () { - utils.triggerPixel.restore(); - storage.setCookie.restore(); - }); - - it('fpa should be set when not present on this call', function () { - firePixel('clientId'); - var urlString = utils.triggerPixel.getCall(0).args[0]; - var parsedUrl = utils.parseUrl(urlString); - var urlSearchParams = parsedUrl.search; - assert.equal(urlSearchParams.fpan, '1'); - assert.notEqual(urlSearchParams.fpa, null); - }); - - it('fpa should be extracted from the Quantcast first party cookie when present on this call', function () { - sinon.stub(storage, 'getCookie').returns('P0-TestFPA'); - firePixel('clientId'); - var urlString = utils.triggerPixel.getCall(0).args[0]; - var parsedUrl = utils.parseUrl(urlString); - var urlSearchParams = parsedUrl.search; - assert.equal(urlSearchParams.fpan, '0'); - assert.equal(urlSearchParams.fpa, 'P0-TestFPA'); - storage.getCookie.restore(); - }); - - it('function to trigger pixel is called once', function () { - firePixel('clientId'); - expect(utils.triggerPixel.calledOnce).to.equal(true); - }); - - it('function to trigger pixel is not called when client id is absent', function () { - firePixel(); - expect(utils.triggerPixel.calledOnce).to.equal(false); - }); -}); - -describe('Quantcast CCPA consent check', function() { - it('returns true when CCPA constent string is not present', function() { - expect(hasCCPAConsent()).to.equal(true); - }); - - it("returns true when notice_given or do-not-sell in CCPA constent string is not 'Y' ", function() { - expect(hasCCPAConsent('1NNN')).to.equal(true); - expect(hasCCPAConsent('1YNN')).to.equal(true); - expect(hasCCPAConsent('1NYN')).to.equal(true); - }); - - it("returns false when CCPA consent string is present, and notice_given or do-not-sell in the string is 'Y' ", function() { - expect(hasCCPAConsent('1YYN')).to.equal(false); - }); -}); - -describe('Quantcast GDPR consent check', function() { - it("returns true when GDPR doesn't apply", function() { - expect(hasGDPRConsent({gdprApplies: false})).to.equal(true); - }); - - it('returns false if denied consent, even if special purpose 1 treatment is true in DE', function() { - expect(checkTCFv2({ - gdprApplies: true, - publisherCC: 'DE', - purposeOneTreatment: true, - vendor: { - consents: { '11': false } - }, - purpose: { - consents: { '1': false } - }, - publisher: { - restrictions: { - '1': { - '11': 0 // flatly disallow Quantcast - } - } - } - }, ['1'])).to.equal(false); - }); - - it('returns false if publisher flatly denies required purpose', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': true } - }, - purpose: { - consents: { '1': true } - }, - publisher: { - restrictions: { - '1': { - '11': 0 // flatly disallow Quantcast - } - } - } - }, ['1'])).to.equal(false); - }); - - it('returns true if positive consent for required purpose', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': true } - }, - purpose: { - consents: { '1': true } - } - }, ['1'])).to.equal(true); - }); - - it('returns false if positive consent but publisher requires legitimate interest for required purpose', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': true } - }, - purpose: { - consents: { '1': true } - }, - publisher: { - restrictions: { - '1': { - '11': 2 // require legitimate interest for Quantcast - } - } - } - }, ['1'])).to.equal(false); - }); - - it('returns false if no vendor consent and no legitimate interest', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': false } - }, - purpose: { - consents: { '1': true } - } - }, ['1'])).to.equal(false); - }); - - it('returns false if no purpose consent and no legitimate interest', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': true } - }, - purpose: { - consents: { '1': false } - } - }, ['1'])).to.equal(false); - }); - - it('returns false if no consent, but legitimate interest for consent-first purpose, and no restrictions specified', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': true }, - legitimateInterests: { '11': true } - }, - purpose: { - consents: { '1': false }, - legitimateInterests: { '1': true } - } - }, ['1'])).to.equal(false); - }); - - it('returns false if consent, but no legitimate interest for legitimate-interest-first purpose, and no restrictions specified', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': true }, - legitimateInterests: { '11': true } - }, - purpose: { - consents: { '10': true }, - legitimateInterests: { '10': false } - } - }, ['10'])).to.equal(false); - }); - - it('returns true if consent, but no legitimate interest for legitimate-interest-first purpose, and corresponding consent restriction specified', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': true }, - legitimateInterests: { '11': true } - }, - purpose: { - consents: { '10': true }, - legitimateInterests: { '10': false } - }, - publisher: { - restrictions: { - '10': { - '11': 1 // require consent for Quantcast - } - } - } - }, ['10'])).to.equal(true); - }); - - it('returns false if no consent but legitimate interest for required purpose other than 1, but publisher requires consent', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': false }, - legitimateInterests: { '11': true } - }, - purpose: { - consents: { '10': false }, - legitimateInterests: { '10': true } - }, - publisher: { - restrictions: { - '10': { - '11': 1 // require consent for Quantcast - } - } - } - }, ['10'])).to.equal(false); - }); - - it('returns false if no consent and no legitimate interest for vendor for required purpose other than 1', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': false }, - legitimateInterests: { '11': false } - }, - purpose: { - consents: { '10': false }, - legitimateInterests: { '10': true } - } - }, ['10'])).to.equal(false); - }); - - it('returns false if no consent and no legitimate interest for required purpose other than 1', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': false }, - legitimateInterests: { '11': true } - }, - purpose: { - consents: { '10': false }, - legitimateInterests: { '10': false } - } - }, ['10'])).to.equal(false); - }); - - it('returns false if no consent but legitimate interest for required purpose, but required purpose is purpose 1', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': false }, - legitimateInterests: { '11': true } - }, - purpose: { - consents: { '1': false }, - legitimateInterests: { '1': true } - } - }, ['1'])).to.equal(false); - }); - - it('returns true if different legal bases for multiple required purposes', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': true }, - legitimateInterests: { '11': true } - }, - purpose: { - consents: { - '1': true, - '10': false - }, - legitimateInterests: { - '1': false, - '10': true - } - }, - publisher: { - restrictions: { - '10': { - '11': 2 // require legitimate interest for Quantcast - } - } - } - })).to.equal(true); - }); - - it('returns true if full consent and legitimate interest for all required purposes with no restrictions specified', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': true }, - legitimateInterests: { '11': true } - }, - purpose: { - consents: { - '1': true, - '3': true, - '7': true, - '8': true, - '9': true, - '10': true - }, - legitimateInterests: { - '1': true, - '3': true, - '7': true, - '8': true, - '9': true, - '10': true - } - } - })).to.equal(true); - }); - - it('returns false if one of multiple required purposes has no legal basis', function() { - expect(checkTCFv2({ - gdprApplies: true, - vendor: { - consents: { '11': true }, - legitimateInterests: { '11': true } - }, - purpose: { - consents: { - '1': true, - '10': false - }, - legitimateInterests: { - '11': false, - '10': true - } - }, - publisher: { - restrictions: { - '10': { - '11': 1 // require consent for Quantcast - } - } - } - })).to.equal(false); - }); - describe('eids', () => { - before(() => { - attachIdSystem(quantcastIdSubmodule); - }); - it('quantcastId', function() { - const userId = { - quantcastId: 'some-random-id-value' - }; - const newEids = createEidsArray(userId); - expect(newEids.length).to.equal(1); - expect(newEids[0]).to.deep.equal({ - source: 'quantcast.com', - uids: [{ - id: 'some-random-id-value', - atype: 1 - }] - }); - }); - }) -}); diff --git a/test/spec/modules/teadsBidAdapter_spec.js b/test/spec/modules/teadsBidAdapter_spec.js index c698473260f..6aaf4dd64b5 100644 --- a/test/spec/modules/teadsBidAdapter_spec.js +++ b/test/spec/modules/teadsBidAdapter_spec.js @@ -889,7 +889,6 @@ describe('teadsBidAdapter', () => { id5Id: toEid('id5-sync.com', 'id5Id-id'), criteoId: toEid('criteo.com', 'criteoId-id'), yahooConnectId: toEid('yahoo.com', 'yahooConnectId-id'), - quantcastId: toEid('quantcast.com', 'quantcastId-id'), epsilonPublisherLinkId: toEid('epsilon.com', 'epsilonPublisherLinkId-id'), publisherFirstPartyViewerId: toEid('pubcid.org', 'publisherFirstPartyViewerId-id'), merkleId: toEid('merkleinc.com', 'merkleId-id'), @@ -957,7 +956,6 @@ describe('teadsBidAdapter', () => { expect(payload['id5Id']).to.equal('id5Id-id'); expect(payload['criteoId']).to.equal('criteoId-id'); expect(payload['yahooConnectId']).to.equal('yahooConnectId-id'); - expect(payload['quantcastId']).to.equal('quantcastId-id'); expect(payload['epsilonPublisherLinkId']).to.equal('epsilonPublisherLinkId-id'); expect(payload['publisherFirstPartyViewerId']).to.equal('publisherFirstPartyViewerId-id'); expect(payload['merkleId']).to.equal('merkleId-id'); From 117981a844a414721283eccedca0b9c9283a196e Mon Sep 17 00:00:00 2001 From: dpapworth-qc <50959025+dpapworth-qc@users.noreply.github.com> Date: Wed, 28 Jan 2026 18:15:24 +0000 Subject: [PATCH 02/48] Remove quantcast bid adapter (#14054) * Remove quantcast bid adapter. * Update metadata. * Update modules.json * Add quantcastBidAdapter.json metadata file --------- Co-authored-by: Patrick McCann Co-authored-by: Patrick McCann --- metadata/modules.json | 2 +- metadata/modules/quantcastBidAdapter.json | 2 +- modules/quantcastBidAdapter.js | 297 ------ modules/quantcastBidAdapter.md | 74 -- test/spec/modules/quantcastBidAdapter_spec.js | 859 ------------------ 5 files changed, 2 insertions(+), 1232 deletions(-) delete mode 100644 modules/quantcastBidAdapter.js delete mode 100644 modules/quantcastBidAdapter.md delete mode 100644 test/spec/modules/quantcastBidAdapter_spec.js diff --git a/metadata/modules.json b/metadata/modules.json index 8ff26369262..494102b1459 100644 --- a/metadata/modules.json +++ b/metadata/modules.json @@ -6204,4 +6204,4 @@ "gvlid": null } ] -} \ No newline at end of file +} diff --git a/metadata/modules/quantcastBidAdapter.json b/metadata/modules/quantcastBidAdapter.json index 426abc3ac5c..649cdb0a843 100644 --- a/metadata/modules/quantcastBidAdapter.json +++ b/metadata/modules/quantcastBidAdapter.json @@ -48,4 +48,4 @@ "disclosureURL": "https://www.quantcast.com/.well-known/devicestorage.json" } ] -} \ No newline at end of file +} diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js deleted file mode 100644 index 0ee58a927d1..00000000000 --- a/modules/quantcastBidAdapter.js +++ /dev/null @@ -1,297 +0,0 @@ -import {deepAccess, isArray, isEmpty, logError, logInfo} from '../src/utils.js'; -import {ajax} from '../src/ajax.js'; -import {config} from '../src/config.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {parseDomain} from '../src/refererDetection.js'; - -/** - * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest - * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid - */ - -const BIDDER_CODE = 'quantcast'; -const DEFAULT_BID_FLOOR = 0.0000000001; - -const QUANTCAST_VENDOR_ID = '11'; -// Check other required purposes on server -const PURPOSE_DATA_COLLECT = '1'; - -export const QUANTCAST_DOMAIN = 'qcx.quantserve.com'; -export const QUANTCAST_TEST_DOMAIN = 's2s-canary.quantserve.com'; -export const QUANTCAST_NET_REVENUE = true; -export const QUANTCAST_TEST_PUBLISHER = 'test-publisher'; -export const QUANTCAST_TTL = 4; -export const QUANTCAST_PROTOCOL = 'https'; -export const QUANTCAST_PORT = '8443'; -export const QUANTCAST_FPA = '__qca'; - -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); - -function makeVideoImp(bid) { - const videoInMediaType = deepAccess(bid, 'mediaTypes.video') || {}; - const videoInParams = deepAccess(bid, 'params.video') || {}; - const video = Object.assign({}, videoInParams, videoInMediaType); - - if (video.playerSize) { - video.w = video.playerSize[0]; - video.h = video.playerSize[1]; - } - const videoCopy = { - mimes: video.mimes, - minduration: video.minduration, - maxduration: video.maxduration, - protocols: video.protocols, - startdelay: video.startdelay, - linearity: video.linearity, - battr: video.battr, - maxbitrate: video.maxbitrate, - playbackmethod: video.playbackmethod, - delivery: video.delivery, - api: video.api, - w: video.w, - h: video.h - } - - return { - video: videoCopy, - placementCode: bid.placementCode, - bidFloor: DEFAULT_BID_FLOOR - }; -} - -function makeBannerImp(bid) { - const sizes = bid.sizes || bid.mediaTypes.banner.sizes; - - return { - banner: { - battr: bid.params.battr, - sizes: sizes.map(size => { - return { - width: size[0], - height: size[1] - }; - }) - }, - placementCode: bid.placementCode, - bidFloor: DEFAULT_BID_FLOOR - }; -} - -function checkTCF(tcData) { - const restrictions = tcData.publisher ? tcData.publisher.restrictions : {}; - const qcRestriction = restrictions && restrictions[PURPOSE_DATA_COLLECT] - ? restrictions[PURPOSE_DATA_COLLECT][QUANTCAST_VENDOR_ID] - : null; - - if (qcRestriction === 0 || qcRestriction === 2) { - // Not allowed by publisher, or requires legitimate interest - return false; - } - - const vendorConsent = tcData.vendor && tcData.vendor.consents && tcData.vendor.consents[QUANTCAST_VENDOR_ID]; - const purposeConsent = tcData.purpose && tcData.purpose.consents && tcData.purpose.consents[PURPOSE_DATA_COLLECT]; - - return !!(vendorConsent && purposeConsent); -} - -function getQuantcastFPA() { - const fpa = storage.getCookie(QUANTCAST_FPA) - return fpa || '' -} - -let hasUserSynced = false; - -/** - * The documentation for Prebid.js Adapter 1.0 can be found at link below, - * http://prebid.org/dev-docs/bidder-adapter-1.html - */ -export const spec = { - code: BIDDER_CODE, - gvlid: QUANTCAST_VENDOR_ID, - supportedMediaTypes: ['banner', 'video'], - - /** - * Verify the `AdUnits.bids` response with `true` for valid request and `false` - * for invalid request. - * - * @param {object} bid - * @return boolean `true` is this is a valid bid, and `false` otherwise - */ - isBidRequestValid(bid) { - return !!bid.params.publisherId; - }, - - /** - * Make a server request when the page asks Prebid.js for bids from a list of - * `BidRequests`. - * - * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be send to Quantcast server - * @param bidderRequest - * @return ServerRequest information describing the request to the server. - */ - buildRequests(bidRequests, bidderRequest) { - const bids = bidRequests || []; - const gdprConsent = deepAccess(bidderRequest, 'gdprConsent') || {}; - const uspConsent = deepAccess(bidderRequest, 'uspConsent'); - const referrer = deepAccess(bidderRequest, 'refererInfo.ref'); - const page = deepAccess(bidderRequest, 'refererInfo.page') || deepAccess(window, 'location.href'); - const domain = parseDomain(page, {noLeadingWww: true}); - - // Check for GDPR consent for purpose 1, and drop request if consent has not been given - // Remaining consent checks are performed server-side. - if (gdprConsent.gdprApplies) { - if (gdprConsent.vendorData) { - if (!checkTCF(gdprConsent.vendorData)) { - logInfo(`${BIDDER_CODE}: No purpose 1 consent for TCF v2`); - return; - } - } - } - - const bidRequestsList = []; - - bids.forEach(bid => { - let imp; - if (bid.mediaTypes) { - if (bid.mediaTypes.video && bid.mediaTypes.video.context === 'instream') { - imp = makeVideoImp(bid); - } else if (bid.mediaTypes.banner) { - imp = makeBannerImp(bid); - } else { - // Unsupported mediaType - logInfo(`${BIDDER_CODE}: No supported mediaTypes found in ${JSON.stringify(bid.mediaTypes)}`); - return; - } - } else { - // Parse as banner by default - imp = makeBannerImp(bid); - } - - // Request Data Format can be found at https://wiki.corp.qc/display/adinf/QCX - const requestData = { - publisherId: bid.params.publisherId, - requestId: bid.bidId, - imp: [imp], - site: { - page, - referrer, - domain - }, - bidId: bid.bidId, - gdprSignal: gdprConsent.gdprApplies ? 1 : 0, - gdprConsent: gdprConsent.consentString, - uspSignal: uspConsent ? 1 : 0, - uspConsent, - coppa: config.getConfig('coppa') === true ? 1 : 0, - prebidJsVersion: '$prebid.version$', - fpa: getQuantcastFPA() - }; - - const data = JSON.stringify(requestData); - const qcDomain = bid.params.publisherId === QUANTCAST_TEST_PUBLISHER - ? QUANTCAST_TEST_DOMAIN - : QUANTCAST_DOMAIN; - const url = `${QUANTCAST_PROTOCOL}://${qcDomain}:${QUANTCAST_PORT}/qchb`; - - bidRequestsList.push({ - data, - method: 'POST', - url - }); - }); - - return bidRequestsList; - }, - - /** - * Function get called when the browser has received the response from Quantcast server. - * The function parse the response and create a `bidResponse` object containing one/more bids. - * Returns an empty array if no valid bids - * - * Response Data Format can be found at https://wiki.corp.qc/display/adinf/QCX - * - * @param {*} serverResponse A successful response from Quantcast server. - * @return {Bid[]} An array of bids which were nested inside the server. - * - */ - interpretResponse(serverResponse) { - if (serverResponse === undefined) { - logError('Server Response is undefined'); - return []; - } - - const response = serverResponse['body']; - - if (response === undefined || !response.hasOwnProperty('bids')) { - logError('Sub-optimal JSON received from Quantcast server'); - return []; - } - - if (isEmpty(response.bids)) { - // Shortcut response handling if no bids are present - return []; - } - - const bidResponsesList = response.bids.map(bid => { - const { ad, cpm, width, height, creativeId, currency, videoUrl, dealId, meta } = bid; - - const result = { - requestId: response.requestId, - cpm, - width, - height, - ad, - ttl: QUANTCAST_TTL, - creativeId, - netRevenue: QUANTCAST_NET_REVENUE, - currency - }; - - if (videoUrl !== undefined && videoUrl) { - result['vastUrl'] = videoUrl; - result['mediaType'] = 'video'; - } - - if (dealId !== undefined && dealId) { - result['dealId'] = dealId; - } - - if (meta !== undefined && meta.advertiserDomains && isArray(meta.advertiserDomains)) { - result.meta = {}; - result.meta.advertiserDomains = meta.advertiserDomains; - } - - return result; - }); - - return bidResponsesList; - }, - onTimeout(timeoutData) { - const url = `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb_notify?type=timeout`; - ajax(url, null, null); - }, - getUserSyncs(syncOptions, serverResponses) { - const syncs = [] - if (!hasUserSynced && syncOptions.pixelEnabled) { - const responseWithUrl = ((serverResponses) || []).find(serverResponse => - deepAccess(serverResponse.body, 'userSync.url') - ); - - if (responseWithUrl) { - const url = deepAccess(responseWithUrl.body, 'userSync.url') - syncs.push({ - type: 'image', - url: url - }); - } - hasUserSynced = true; - } - return syncs; - }, - resetUserSync() { - hasUserSynced = false; - } -}; - -registerBidder(spec); diff --git a/modules/quantcastBidAdapter.md b/modules/quantcastBidAdapter.md deleted file mode 100644 index edbbc538b65..00000000000 --- a/modules/quantcastBidAdapter.md +++ /dev/null @@ -1,74 +0,0 @@ -# Overview - -``` -Module Name: Quantcast Bidder Adapter -Module Type: Bidder Adapter -Maintainer: inventoryteam@quantcast.com -``` - -# Description - -Module that connects to Quantcast demand sources to fetch bids. - -# Test Parameters - -## Sample Banner Ad Unit -```js -const adUnits = [{ - code: 'banner', - sizes: [ - [300, 250] - ], - bids: [ - { - bidder: 'quantcast', - params: { - publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast - battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 - } - } - ], - userSync: { - url: 'https://quantcast.com/pixelUrl' - } -}]; -``` - -## Sample Video Ad Unit -```js -var adUnits = [{ - code: 'video', - mediaTypes: { - video: { - context: 'instream', // required - playerSize: [600, 300] // required - } - }, - bids: [ - { - bidder: 'quantcast', - params: { - publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast - // Video object as specified in OpenRTB 2.5 - video: { - mimes: ['video/mp4'], // required - minduration: 3, // optional - maxduration: 5, // optional - protocols: [3], // optional - startdelay: 1, // optional - linearity: 1, // optinal - battr: [1, 2], // optional - maxbitrate: 10, // optional - playbackmethod: [1], // optional - delivery: [1], // optional - placement: 1, // optional - api: [2, 3] // optional - } - } - } - ], - userSync: { - url: 'https://quantcast.com/pixelUrl' - } -}]; -``` diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js deleted file mode 100644 index dbf6b2c9ef4..00000000000 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ /dev/null @@ -1,859 +0,0 @@ -import { expect } from 'chai'; -import { - QUANTCAST_DOMAIN, - QUANTCAST_TEST_DOMAIN, - QUANTCAST_NET_REVENUE, - QUANTCAST_TTL, - QUANTCAST_TEST_PUBLISHER, - QUANTCAST_PROTOCOL, - QUANTCAST_PORT, - spec as qcSpec, - storage -} from '../../../modules/quantcastBidAdapter.js'; -import { newBidder } from '../../../src/adapters/bidderFactory.js'; -import { parseUrl } from 'src/utils.js'; -import { config } from 'src/config.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; - -describe('Quantcast adapter', function () { - const quantcastAdapter = newBidder(qcSpec); - let bidRequest; - let bidderRequest; - - afterEach(function () { - getGlobal().bidderSettings = {}; - }); - beforeEach(function () { - getGlobal().bidderSettings = { - quantcast: { - storageAllowed: true - } - }; - bidRequest = { - bidder: 'quantcast', - bidId: '2f7b179d443f14', - auctionId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', - bidderRequestId: '1cc026909c24c8', - placementCode: 'div-gpt-ad-1438287399331-0', - params: { - publisherId: QUANTCAST_TEST_PUBLISHER, // REQUIRED - Publisher ID provided by Quantcast - battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 - }, - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - } - }; - - bidderRequest = { - refererInfo: { - page: 'http://example.com/hello.html', - ref: 'http://example.com/hello.html', - domain: 'example.com' - } - }; - - storage.setCookie('__qca', '', 'Thu, 01 Jan 1970 00:00:00 GMT'); - }); - - function setupVideoBidRequest(videoParams, mediaTypesParams) { - bidRequest.params = { - publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast - // Video object as specified in OpenRTB 2.5 - video: videoParams - }; - if (mediaTypesParams) { - bidRequest['mediaTypes'] = { - video: mediaTypesParams - } - } - }; - - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(quantcastAdapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('`isBidRequestValid`', function () { - it('should return `true` when bid has publisherId', function () { - const bidRequest = { - bidder: 'quantcast', - params: { - publisherId: 'my_publisher_id' - } - }; - - expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); - }); - - it('should return `false` when bid has no publisherId', function () { - const bidRequest = { - bidder: 'quantcast', - params: { - } - }; - - expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); - }); - }); - - describe('`buildRequests`', function () { - it('sends secure bid requests', function () { - const requests = qcSpec.buildRequests([bidRequest]); - const url = parseUrl(requests[0]['url']); - expect(url.protocol).to.equal('https'); - }); - - it('sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`', function () { - const requests = qcSpec.buildRequests([bidRequest]); - const url = parseUrl(requests[0]['url']); - expect(url.hostname).to.equal(QUANTCAST_TEST_DOMAIN); - }); - - it('sends bid requests to default endpoint for non standard publisher IDs', function () { - const modifiedBidRequest = Object.assign({}, bidRequest, { - params: Object.assign({}, bidRequest.params, { - publisherId: 'foo-bar', - }), - }); - const requests = qcSpec.buildRequests([modifiedBidRequest]); - expect(requests[0]['url']).to.equal( - `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb` - ); - }); - - it('sends bid requests to Quantcast Header Bidding Endpoints via POST', function () { - const requests = qcSpec.buildRequests([bidRequest]); - - expect(requests[0].method).to.equal('POST'); - }); - - const expectedBannerBidRequest = { - publisherId: QUANTCAST_TEST_PUBLISHER, - requestId: '2f7b179d443f14', - imp: [ - { - banner: { - battr: [1, 2], - sizes: [{ width: 300, height: 250 }] - }, - placementCode: 'div-gpt-ad-1438287399331-0', - bidFloor: 1e-10 - } - ], - site: { - page: 'http://example.com/hello.html', - referrer: 'http://example.com/hello.html', - domain: 'example.com' - }, - bidId: '2f7b179d443f14', - gdprSignal: 0, - uspSignal: 0, - coppa: 0, - prebidJsVersion: '$prebid.version$', - fpa: '' - }; - - it('sends banner bid requests contains all the required parameters', function () { - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - - expect(requests[0].data).to.equal(JSON.stringify(expectedBannerBidRequest)); - }); - - it('supports deprecated banner format', function () { - bidRequest.sizes = bidRequest.mediaTypes.banner.sizes; - delete bidRequest.mediaTypes; - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - - expect(requests[0].data).to.equal(JSON.stringify(expectedBannerBidRequest)); - }); - - it('sends video bid requests containing all the required parameters', function () { - setupVideoBidRequest({ - mimes: ['video/mp4'], // required - minduration: 3, // optional - maxduration: 5, // optional - protocols: [3], // optional - startdelay: 1, // optional - linearity: 1, // optinal - battr: [1, 2], // optional - maxbitrate: 10, // optional - playbackmethod: [1], // optional - delivery: [1], // optional - api: [2, 3] // optional - }, { - context: 'instream', - playerSize: [600, 300] - }); - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - const expectedVideoBidRequest = { - publisherId: QUANTCAST_TEST_PUBLISHER, - requestId: '2f7b179d443f14', - imp: [ - { - video: { - mimes: ['video/mp4'], - minduration: 3, - maxduration: 5, - protocols: [3], - startdelay: 1, - linearity: 1, - battr: [1, 2], - maxbitrate: 10, - playbackmethod: [1], - delivery: [1], - api: [2, 3], - w: 600, - h: 300 - }, - placementCode: 'div-gpt-ad-1438287399331-0', - bidFloor: 1e-10 - } - ], - site: { - page: 'http://example.com/hello.html', - referrer: 'http://example.com/hello.html', - domain: 'example.com' - }, - bidId: '2f7b179d443f14', - gdprSignal: 0, - uspSignal: 0, - coppa: 0, - prebidJsVersion: '$prebid.version$', - fpa: '' - }; - - expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); - }); - - it('sends video bid requests containing all the required parameters from mediaTypes', function() { - setupVideoBidRequest(null, { - mimes: ['video/mp4'], // required - minduration: 3, // optional - maxduration: 5, // optional - protocols: [3], // optional - startdelay: 1, // optional - linearity: 1, // optinal - battr: [1, 2], // optional - maxbitrate: 10, // optional - playbackmethod: [1], // optional - delivery: [1], // optional - api: [2, 3], // optional - context: 'instream', - playerSize: [600, 300] - }); - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - const expectedVideoBidRequest = { - publisherId: QUANTCAST_TEST_PUBLISHER, - requestId: '2f7b179d443f14', - imp: [ - { - video: { - mimes: ['video/mp4'], - minduration: 3, - maxduration: 5, - protocols: [3], - startdelay: 1, - linearity: 1, - battr: [1, 2], - maxbitrate: 10, - playbackmethod: [1], - delivery: [1], - api: [2, 3], - w: 600, - h: 300 - }, - placementCode: 'div-gpt-ad-1438287399331-0', - bidFloor: 1e-10 - } - ], - site: { - page: 'http://example.com/hello.html', - referrer: 'http://example.com/hello.html', - domain: 'example.com' - }, - bidId: '2f7b179d443f14', - gdprSignal: 0, - uspSignal: 0, - coppa: 0, - prebidJsVersion: '$prebid.version$', - fpa: '' - }; - - expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); - }); - - it('overrides video parameters with parameters from adunit', function() { - setupVideoBidRequest({ - mimes: ['video/mp4'] - }, { - context: 'instream', - playerSize: [600, 300] - }); - bidRequest.mediaTypes.video.mimes = ['video/webm']; - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - const expectedVideoBidRequest = { - publisherId: QUANTCAST_TEST_PUBLISHER, - requestId: '2f7b179d443f14', - imp: [ - { - video: { - mimes: ['video/webm'], - w: 600, - h: 300 - }, - placementCode: 'div-gpt-ad-1438287399331-0', - bidFloor: 1e-10 - } - ], - site: { - page: 'http://example.com/hello.html', - referrer: 'http://example.com/hello.html', - domain: 'example.com' - }, - bidId: '2f7b179d443f14', - gdprSignal: 0, - uspSignal: 0, - coppa: 0, - prebidJsVersion: '$prebid.version$', - fpa: '' - }; - - expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); - }); - - it('sends video bid request when no video parameters are given', function () { - setupVideoBidRequest(null, { - context: 'instream', - playerSize: [600, 300] - }); - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - const expectedVideoBidRequest = { - publisherId: QUANTCAST_TEST_PUBLISHER, - requestId: '2f7b179d443f14', - imp: [ - { - video: { - w: 600, - h: 300 - }, - placementCode: 'div-gpt-ad-1438287399331-0', - bidFloor: 1e-10 - } - ], - site: { - page: 'http://example.com/hello.html', - referrer: 'http://example.com/hello.html', - domain: 'example.com' - }, - bidId: '2f7b179d443f14', - gdprSignal: 0, - uspSignal: 0, - coppa: 0, - prebidJsVersion: '$prebid.version$', - fpa: '' - }; - - expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); - }); - - it('ignores unsupported video bid requests', function () { - bidRequest.mediaTypes = { - video: { - context: 'outstream', - playerSize: [[550, 310]] - } - }; - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - - expect(requests).to.be.empty; - }); - - it('parses multi-format bid request', function () { - bidRequest.mediaTypes = { - banner: {sizes: [[300, 250], [728, 90], [250, 250], [468, 60], [320, 50]]}, - native: { - image: {required: true, sizes: [150, 50]}, - title: {required: true, len: 80}, - sponsoredBy: {required: true}, - clickUrl: {required: true}, - privacyLink: {required: false}, - body: {required: true}, - icon: {required: true, sizes: [50, 50]} - }, - video: { - context: 'outstream', - playerSize: [[550, 310]] - } - }; - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - const expectedBidRequest = { - publisherId: QUANTCAST_TEST_PUBLISHER, - requestId: '2f7b179d443f14', - imp: [{ - banner: { - battr: [1, 2], - sizes: [ - {width: 300, height: 250}, - {width: 728, height: 90}, - {width: 250, height: 250}, - {width: 468, height: 60}, - {width: 320, height: 50} - ] - }, - placementCode: 'div-gpt-ad-1438287399331-0', - bidFloor: 1e-10 - }], - site: { - page: 'http://example.com/hello.html', - referrer: 'http://example.com/hello.html', - domain: 'example.com' - }, - bidId: '2f7b179d443f14', - gdprSignal: 0, - uspSignal: 0, - coppa: 0, - prebidJsVersion: '$prebid.version$', - fpa: '' - }; - - expect(requests[0].data).to.equal(JSON.stringify(expectedBidRequest)); - }); - }); - - it('propagates GDPR consent string and signal', function () { - const bidderRequest = { - gdprConsent: { - gdprApplies: true, - consentString: 'consentString' - } - }; - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - const parsed = JSON.parse(requests[0].data); - - expect(parsed.gdprSignal).to.equal(1); - expect(parsed.gdprConsent).to.equal('consentString'); - }); - - it('allows TCF v2 request when Quantcast has consent for purpose 1', function() { - const bidderRequest = { - gdprConsent: { - gdprApplies: true, - consentString: 'consentString', - vendorData: { - vendor: { - consents: { - '11': true - } - }, - purpose: { - consents: { - '1': true - } - } - }, - apiVersion: 2 - } - }; - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - const parsed = JSON.parse(requests[0].data); - - expect(parsed.gdprSignal).to.equal(1); - expect(parsed.gdprConsent).to.equal('consentString'); - }); - - it('blocks TCF v2 request when no consent for Quantcast', function() { - const bidderRequest = { - gdprConsent: { - gdprApplies: true, - consentString: 'consentString', - vendorData: { - vendor: { - consents: { - '11': false - } - }, - purpose: { - consents: { - '1': true - } - } - }, - apiVersion: 2 - } - }; - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - - expect(requests).to.equal(undefined); - }); - - it('blocks TCF v2 request when no consent for purpose 1', function() { - const bidderRequest = { - gdprConsent: { - gdprApplies: true, - consentString: 'consentString', - vendorData: { - vendor: { - consents: { - '11': true - } - }, - purpose: { - consents: { - '1': false - } - } - }, - apiVersion: 2 - } - }; - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - - expect(requests).to.equal(undefined); - }); - - it('blocks TCF v2 request when Quantcast not allowed by publisher', function () { - const bidderRequest = { - gdprConsent: { - gdprApplies: true, - consentString: 'consentString', - vendorData: { - vendor: { - consents: { - '11': true - } - }, - purpose: { - consents: { - '1': true - } - }, - publisher: { - restrictions: { - '1': { - '11': 0 - } - } - } - }, - apiVersion: 2 - } - }; - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - - expect(requests).to.equal(undefined); - }); - - it('blocks TCF v2 request when legitimate interest required', function () { - const bidderRequest = { - gdprConsent: { - gdprApplies: true, - consentString: 'consentString', - vendorData: { - vendor: { - consents: { - '11': true - } - }, - purpose: { - consents: { - '1': true - } - }, - publisher: { - restrictions: { - '1': { - '11': 2 - } - } - } - }, - apiVersion: 2 - } - }; - - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - - expect(requests).to.equal(undefined); - }); - - it('propagates US Privacy/CCPA consent information', function () { - const bidderRequest = { uspConsent: 'consentString' } - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - const parsed = JSON.parse(requests[0].data); - expect(parsed.uspSignal).to.equal(1); - expect(parsed.uspConsent).to.equal('consentString'); - }); - - it('propagates Quantcast first-party cookie (fpa)', function() { - storage.setCookie('__qca', 'P0-TestFPA'); - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - const parsed = JSON.parse(requests[0].data); - expect(parsed.fpa).to.equal('P0-TestFPA'); - }); - - describe('propagates coppa', function() { - let sandbox; - beforeEach(() => { - sandbox = sinon.createSandbox(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('propagates coppa as 1 if coppa param is set to true in the bid request', function () { - bidRequest.params = { - publisherId: 'test_publisher_id', - coppa: true - }; - sandbox.stub(config, 'getConfig').callsFake((key) => { - const config = { - 'coppa': true - }; - return config[key]; - }); - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); - expect(JSON.parse(requests[0].data).coppa).to.equal(1); - }); - - it('propagates coppa as 0 if there is no coppa param or coppa is set to false in the bid request', function () { - const requestsWithoutCoppa = qcSpec.buildRequests([bidRequest], bidderRequest); - expect(JSON.parse(requestsWithoutCoppa[0].data).coppa).to.equal(0); - - bidRequest.params = { - publisherId: 'test_publisher_id', - coppa: false - }; - sandbox.stub(config, 'getConfig').callsFake((key) => { - const config = { - 'coppa': false - }; - return config[key]; - }); - const requestsWithFalseCoppa = qcSpec.buildRequests([bidRequest], bidderRequest); - expect(JSON.parse(requestsWithFalseCoppa[0].data).coppa).to.equal(0); - }); - }); - - describe('`interpretResponse`', function () { - // The sample response is from https://wiki.corp.qc/display/adinf/QCX - const body = { - bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name - requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames - bids: [ - { - statusCode: 1, - placementCode: 'imp1', // Changing this to placementCode to be reflective - cpm: 4.5, - currency: 'USD', - ad: - '
Quantcast
', - creativeId: 1001, - width: 300, - height: 250, - meta: { - advertiserDomains: ['dailymail.com'] - } - } - ] - }; - - const response = { - body, - headers: {} - }; - - const videoBody = { - bidderCode: 'qcx', - requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', - bids: [ - { - statusCode: 1, - placementCode: 'video1', - cpm: 4.5, - currency: 'USD', - videoUrl: 'https://vast.quantserve.com/vast?p=&r=&gdpr=&gdpr_consent=&rand=1337&d=H4sIAAAAAAAAAONi4mIQcrzFqGLi5OzibOzmpGtm4eyia-LoaqDraGRupOtobGJhYuni6GRiYLmLiYWrp5f_BBPDDybGScxcPs7-aRYmpmVVoVJgCSXBkozMYl0gKslI1S1Izk9JBQALkFy_YAAAAA&h=uRnsTjyXbOrXJtBQiaMn239i9GI', - width: 600, - height: 300 - } - ] - }; - - const videoResponse = { - body: videoBody, - headers: {} - }; - - it('should return an empty array if `serverResponse` is `undefined`', function () { - const interpretedResponse = qcSpec.interpretResponse(); - - expect(interpretedResponse.length).to.equal(0); - }); - - it('should return an empty array if the parsed response does NOT include `bids`', function () { - const interpretedResponse = qcSpec.interpretResponse({}); - - expect(interpretedResponse.length).to.equal(0); - }); - - it('should return an empty array if the parsed response has an empty `bids`', function () { - const interpretedResponse = qcSpec.interpretResponse({ bids: [] }); - - expect(interpretedResponse.length).to.equal(0); - }); - - it('should get correct bid response', function () { - const expectedResponse = { - requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', - cpm: 4.5, - width: 300, - height: 250, - ad: - '
Quantcast
', - ttl: QUANTCAST_TTL, - creativeId: 1001, - netRevenue: QUANTCAST_NET_REVENUE, - currency: 'USD', - meta: { - advertiserDomains: ['dailymail.com'] - } - }; - const interpretedResponse = qcSpec.interpretResponse(response); - - expect(interpretedResponse[0]).to.deep.equal(expectedResponse); - }); - - it('should include dealId in bid response', function () { - response.body.bids[0].dealId = 'test-dealid'; - const expectedResponse = { - requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', - cpm: 4.5, - width: 300, - height: 250, - ad: - '
Quantcast
', - ttl: QUANTCAST_TTL, - creativeId: 1001, - netRevenue: QUANTCAST_NET_REVENUE, - currency: 'USD', - dealId: 'test-dealid', - meta: { - advertiserDomains: ['dailymail.com'] - } - }; - const interpretedResponse = qcSpec.interpretResponse(response); - - expect(interpretedResponse[0]).to.deep.equal(expectedResponse); - }); - - it('should get correct bid response for instream video', function() { - const expectedResponse = { - requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', - cpm: 4.5, - width: 600, - height: 300, - vastUrl: 'https://vast.quantserve.com/vast?p=&r=&gdpr=&gdpr_consent=&rand=1337&d=H4sIAAAAAAAAAONi4mIQcrzFqGLi5OzibOzmpGtm4eyia-LoaqDraGRupOtobGJhYuni6GRiYLmLiYWrp5f_BBPDDybGScxcPs7-aRYmpmVVoVJgCSXBkozMYl0gKslI1S1Izk9JBQALkFy_YAAAAA&h=uRnsTjyXbOrXJtBQiaMn239i9GI', - mediaType: 'video', - ttl: QUANTCAST_TTL, - creativeId: undefined, - ad: undefined, - netRevenue: QUANTCAST_NET_REVENUE, - currency: 'USD' - }; - const interpretedResponse = qcSpec.interpretResponse(videoResponse); - - expect(interpretedResponse[0]).to.deep.equal(expectedResponse); - }); - - it('handles no bid response', function () { - const body = { - bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name - requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames - bids: [] - }; - const response = { - body, - headers: {} - }; - const interpretedResponse = qcSpec.interpretResponse(response); - - expect(interpretedResponse.length).to.equal(0); - }); - - it('should return pixel url when available userSync available', function () { - const syncOptions = { - pixelEnabled: true - }; - const serverResponses = [ - { - body: { - userSync: { - url: 'http://quantcast.com/pixelUrl' - } - } - }, - { - body: { - - } - } - ]; - - const actualSyncs = qcSpec.getUserSyncs(syncOptions, serverResponses); - const expectedSync = { - type: 'image', - url: 'http://quantcast.com/pixelUrl' - }; - expect(actualSyncs.length).to.equal(1); - expect(actualSyncs[0]).to.deep.equal(expectedSync); - qcSpec.resetUserSync(); - }); - - it('should not return user syncs if done already', function () { - const syncOptions = { - pixelEnabled: true - }; - const serverResponses = [ - { - body: { - userSync: { - url: 'http://quantcast.com/pixelUrl' - } - } - }, - { - body: { - - } - } - ]; - - let actualSyncs = qcSpec.getUserSyncs(syncOptions, serverResponses); - const expectedSync = { - type: 'image', - url: 'http://quantcast.com/pixelUrl' - }; - expect(actualSyncs.length).to.equal(1); - expect(actualSyncs[0]).to.deep.equal(expectedSync); - - actualSyncs = qcSpec.getUserSyncs(syncOptions, serverResponses); - expect(actualSyncs.length).to.equal(0); - - qcSpec.resetUserSync(); - }); - }); -}); From 37a37c8b9727147e5fd216fc8a9328fed0c544d4 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 28 Jan 2026 13:17:29 -0500 Subject: [PATCH 03/48] Delete modules/ringieraxelspringerBidAdapter.md --- modules/ringieraxelspringerBidAdapter.md | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 modules/ringieraxelspringerBidAdapter.md diff --git a/modules/ringieraxelspringerBidAdapter.md b/modules/ringieraxelspringerBidAdapter.md deleted file mode 100644 index 4527d9f8c6d..00000000000 --- a/modules/ringieraxelspringerBidAdapter.md +++ /dev/null @@ -1,8 +0,0 @@ -# Overview - -The `ringieraxelspringer` bidder has been renamed to `das`. -Please use the `das` bidder code instead. - -See [dasBidAdapter.md](./dasBidAdapter.md) for documentation. - -This adapter will be removed in Prebid 11. From 282f3c95298f151c0f9fb5551aee730db8fef7d1 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 28 Jan 2026 13:17:54 -0500 Subject: [PATCH 04/48] Delete test/spec/modules/ringieraxelspringerBidAdapter_spec.js --- .../spec/modules/ringieraxelspringerBidAdapter_spec.js | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 test/spec/modules/ringieraxelspringerBidAdapter_spec.js diff --git a/test/spec/modules/ringieraxelspringerBidAdapter_spec.js b/test/spec/modules/ringieraxelspringerBidAdapter_spec.js deleted file mode 100644 index 0318a6987c6..00000000000 --- a/test/spec/modules/ringieraxelspringerBidAdapter_spec.js +++ /dev/null @@ -1,10 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/ringieraxelspringerBidAdapter.js'; - -describe('ringieraxelspringer backward-compatibility shim', function () { - it('should re-export spec from dasBidAdapter', function () { - expect(spec).to.exist; - expect(spec.code).to.equal('das'); - expect(spec.aliases).to.include('ringieraxelspringer'); - }); -}); From 869f4703d4c1d6e08f02365796502f894ee1da3d Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 28 Jan 2026 13:18:12 -0500 Subject: [PATCH 05/48] Delete modules/ringieraxelspringerBidAdapter.js --- modules/ringieraxelspringerBidAdapter.js | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 modules/ringieraxelspringerBidAdapter.js diff --git a/modules/ringieraxelspringerBidAdapter.js b/modules/ringieraxelspringerBidAdapter.js deleted file mode 100644 index c5b7e000f87..00000000000 --- a/modules/ringieraxelspringerBidAdapter.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Backward-compatibility shim for ringieraxelspringer bidder. - * This bidder has been renamed to 'das'. - * - * This file will be removed in Prebid 11. - * See dasBidAdapter.js for implementation. - */ -export { spec } from './dasBidAdapter.js'; // eslint-disable-line prebid/validate-imports From 076b9a7fae49310f731d0413e50dc5b338f9a719 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 28 Jan 2026 13:18:28 -0500 Subject: [PATCH 06/48] Delete metadata/modules/ringieraxelspringerBidAdapter.json --- .../ringieraxelspringerBidAdapter.json | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 metadata/modules/ringieraxelspringerBidAdapter.json diff --git a/metadata/modules/ringieraxelspringerBidAdapter.json b/metadata/modules/ringieraxelspringerBidAdapter.json deleted file mode 100644 index 1ca1c72523f..00000000000 --- a/metadata/modules/ringieraxelspringerBidAdapter.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "NOTICE": "do not edit - this file is autogenerated by `gulp update-metadata`", - "disclosures": {}, - "components": [ - { - "componentType": "bidder", - "componentName": "das", - "aliasOf": null, - "gvlid": null, - "disclosureURL": null - }, - { - "componentType": "bidder", - "componentName": "ringieraxelspringer", - "aliasOf": "das", - "gvlid": null, - "disclosureURL": null - } - ] -} \ No newline at end of file From f5999aed9a0590d350c5d0afb66a488d8dba2991 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 28 Jan 2026 13:18:56 -0500 Subject: [PATCH 07/48] Remove ringieraxelspringerBidAdapter from overrides --- metadata/overrides.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/metadata/overrides.mjs b/metadata/overrides.mjs index 214f778485c..869069f94d3 100644 --- a/metadata/overrides.mjs +++ b/metadata/overrides.mjs @@ -16,6 +16,5 @@ export default { operaadsIdSystem: 'operaId', relevadRtdProvider: 'RelevadRTDModule', sirdataRtdProvider: 'SirdataRTDModule', - fanBidAdapter: 'freedomadnetwork', - ringieraxelspringerBidAdapter: 'das' + fanBidAdapter: 'freedomadnetwork' } From e102bac63320c61e8868a19035a51a521be0630b Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 28 Jan 2026 13:21:28 -0500 Subject: [PATCH 08/48] Delete modules/dfpAdServerVideo.js --- modules/dfpAdServerVideo.js | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 modules/dfpAdServerVideo.js diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js deleted file mode 100644 index a7053622102..00000000000 --- a/modules/dfpAdServerVideo.js +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint prebid/validate-imports: "off" */ -import {registerVideoSupport} from '../src/adServerManager.js'; -import {buildGamVideoUrl, getVastXml, notifyTranslationModule, dep, VAST_TAG_URI_TAGNAME, getBase64BlobContent} from './gamAdServerVideo.js'; - -export const buildDfpVideoUrl = buildGamVideoUrl; -export { getVastXml, notifyTranslationModule, dep, VAST_TAG_URI_TAGNAME, getBase64BlobContent }; - -registerVideoSupport('dfp', { - buildVideoUrl: buildDfpVideoUrl, - getVastXml -}); From 2af37d6e073795e1206d1356c809e8b182131b4a Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 28 Jan 2026 13:22:09 -0500 Subject: [PATCH 09/48] Delete modules/dfpAdpod.js --- modules/dfpAdpod.js | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 modules/dfpAdpod.js diff --git a/modules/dfpAdpod.js b/modules/dfpAdpod.js deleted file mode 100644 index 831507dcc5c..00000000000 --- a/modules/dfpAdpod.js +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint prebid/validate-imports: "off" */ -import {registerVideoSupport} from '../src/adServerManager.js'; -import {buildAdpodVideoUrl, adpodUtils} from './gamAdpod.js'; - -export { buildAdpodVideoUrl, adpodUtils }; - -registerVideoSupport('dfp', { - buildAdpodVideoUrl, - getAdpodTargeting: (args) => adpodUtils.getTargeting(args) -}); From 043fec21f534c0eb9ad65af8aa8fcae09168e5f5 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Thu, 29 Jan 2026 11:21:15 -0500 Subject: [PATCH 10/48] Delete modules/express.js --- modules/express.js | 210 --------------------------------------------- 1 file changed, 210 deletions(-) delete mode 100644 modules/express.js diff --git a/modules/express.js b/modules/express.js deleted file mode 100644 index a2998baed07..00000000000 --- a/modules/express.js +++ /dev/null @@ -1,210 +0,0 @@ -import { logMessage, logWarn, logError, logInfo } from '../src/utils.js'; -import {getGlobal} from '../src/prebidGlobal.js'; - -const MODULE_NAME = 'express'; -const pbjsInstance = getGlobal(); - -/** - * Express Module - * - * The express module allows the initiation of Prebid.js auctions automatically based on calls such as gpt.defineSlot. - * It works by monkey-patching the gpt methods and overloading their functionality. In order for this module to be - * used gpt must be included in the page, this module must be included in the Prebid.js bundle, and a call to - * pbjs.express() must be made. - * - * @param {Object[]} [adUnits = pbjs.adUnits] - an array of adUnits for express to operate on. - */ -pbjsInstance.express = function(adUnits = pbjsInstance.adUnits) { - logMessage('loading ' + MODULE_NAME); - - if (adUnits.length === 0) { - logWarn('no valid adUnits found, not loading ' + MODULE_NAME); - } - - // store gpt slots in a more performant hash lookup by elementId (adUnit code) - var gptSlotCache = {}; - // put adUnits in a more performant hash lookup by code. - var adUnitsCache = adUnits.reduce(function (cache, adUnit) { - if (adUnit.code && adUnit.bids) { - cache[adUnit.code] = adUnit; - } else { - logError('misconfigured adUnit', null, adUnit); - } - return cache; - }, {}); - - window.googletag = window.googletag || {}; - window.googletag.cmd = window.googletag.cmd || []; - window.googletag.cmd.push(function () { - // verify all necessary gpt functions exist - var gpt = window.googletag; - var pads = gpt.pubads; - if (!gpt.display || !gpt.enableServices || typeof pads !== 'function' || !pads().refresh || !pads().disableInitialLoad || !pads().getSlots || !pads().enableSingleRequest) { - logError('could not bind to gpt googletag api'); - return; - } - logMessage('running'); - - // function to convert google tag slot sizes to [[w,h],...] - function mapGptSlotSizes(aGPTSlotSizes) { - var aSlotSizes = []; - for (var i = 0; i < aGPTSlotSizes.length; i++) { - try { - aSlotSizes.push([aGPTSlotSizes[i].getWidth(), aGPTSlotSizes[i].getHeight()]); - } catch (e) { - logWarn('slot size ' + aGPTSlotSizes[i].toString() + ' not supported by' + MODULE_NAME); - } - } - return aSlotSizes; - } - - // a helper function to verify slots or get slots if not present - function defaultSlots(slots) { - return Array.isArray(slots) - ? slots.slice() - // eslint-disable-next-line no-undef - : googletag.pubads().getSlots().slice(); - } - - // maps gpt slots to adUnits, matches are copied to new array and removed from passed array. - function pickAdUnits(gptSlots) { - var adUnits = []; - // traverse backwards (since gptSlots is mutated) to find adUnits in cache and remove non-mapped slots - for (var i = gptSlots.length - 1; i > -1; i--) { - const gptSlot = gptSlots[i]; - const elemId = gptSlot.getSlotElementId(); - const adUnit = adUnitsCache[elemId]; - - if (adUnit) { - gptSlotCache[elemId] = gptSlot; // store by elementId - adUnit.sizes = adUnit.sizes || mapGptSlotSizes(gptSlot.getSizes()); - adUnits.push(adUnit); - gptSlots.splice(i, 1); - } - } - - return adUnits; - } - - // store original gpt functions that will be overridden - var fGptDisplay = gpt.display; - var fGptEnableServices = gpt.enableServices; - var fGptRefresh = pads().refresh; - var fGptDisableInitialLoad = pads().disableInitialLoad; - var fGptEnableSingleRequest = pads().enableSingleRequest; - - // override googletag.enableServices() - // - make sure fGptDisableInitialLoad() has been called so we can - // better control when slots are displayed, then call original - // fGptEnableServices() - gpt.enableServices = function () { - if (!bInitialLoadDisabled) { - fGptDisableInitialLoad.apply(pads()); - } - return fGptEnableServices.apply(gpt, arguments); - }; - - // override googletag.display() - // - call the real fGptDisplay(). this won't initiate auctions because we've disabled initial load - // - define all corresponding rubicon slots - // - if disableInitialLoad() has been called by the pub, done - // - else run an auction and call the real fGptRefresh() to - // initiate the DFP request - gpt.display = function (sElementId) { - logInfo('display:', sElementId); - // call original gpt display() function - fGptDisplay.apply(gpt, arguments); - - // if not SRA mode, get only the gpt slot corresponding to sEementId - var aGptSlots; - if (!bEnabledSRA) { - // eslint-disable-next-line no-undef - aGptSlots = googletag.pubads().getSlots().filter(function (oGptSlot) { - return oGptSlot.getSlotElementId() === sElementId; - }); - } - - aGptSlots = defaultSlots(aGptSlots).filter(function (gptSlot) { - return !gptSlot._displayed; - }); - - aGptSlots.forEach(function (gptSlot) { - gptSlot._displayed = true; - }); - - var adUnits = pickAdUnits(/* mutated: */ aGptSlots); - - if (!bInitialLoadDisabled) { - if (aGptSlots.length) { - fGptRefresh.apply(pads(), [aGptSlots]); - } - - if (adUnits.length) { - pbjsInstance.requestBids({ - adUnits: adUnits, - bidsBackHandler: function () { - pbjsInstance.setTargetingForGPTAsync(); - fGptRefresh.apply(pads(), [ - adUnits.map(function (adUnit) { - return gptSlotCache[adUnit.code]; - }) - ]); - } - }); - } - } - }; - - // override gpt refresh() function - // - run auctions for provided gpt slots, then initiate ad-server call - pads().refresh = function (aGptSlots, options) { - logInfo('refresh:', aGptSlots); - // get already displayed adUnits from aGptSlots if provided, else all defined gptSlots - aGptSlots = defaultSlots(aGptSlots); - var adUnits = pickAdUnits(/* mutated: */ aGptSlots).filter(function (adUnit) { - return gptSlotCache[adUnit.code]._displayed; - }); - - if (aGptSlots.length) { - fGptRefresh.apply(pads(), [aGptSlots, options]); - } - - if (adUnits.length) { - pbjsInstance.requestBids({ - adUnits: adUnits, - bidsBackHandler: function () { - pbjsInstance.setTargetingForGPTAsync(); - fGptRefresh.apply(pads(), [ - adUnits.map(function (adUnit) { - return gptSlotCache[adUnit.code]; - }), - options - ]); - } - }); - } - }; - - // override gpt disableInitialLoad function - // Register that initial load was called, meaning calls to display() - // should not initiate an ad-server request. Instead a call to - // refresh() will be needed to iniate the request. - // We will assume the pub is using this the correct way, calling it - // before enableServices() - var bInitialLoadDisabled = false; - pads().disableInitialLoad = function () { - bInitialLoadDisabled = true; - return fGptDisableInitialLoad.apply(window.googletag.pubads(), arguments); - }; - - // override gpt useSingleRequest function - // Register that SRA has been turned on - // We will assume the pub is using this the correct way, calling it - // before enableServices() - var bEnabledSRA = false; - pads().enableSingleRequest = function () { - bEnabledSRA = true; - return fGptEnableSingleRequest.apply(window.googletag.pubads(), arguments); - }; - }); -}; From 0fdb2a2685db6234756c1ee852ae05d5ff937d38 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Mon, 9 Feb 2026 12:33:09 -0800 Subject: [PATCH 11/48] Prebid 11: remove PAAPI (#14432) * core: remove paapi support * PAAPI: remove paapi modules * Core: remove getBidToRender * Debugging: remove paapi support * Core: remove paapi events * PBS bid adapter: remove paapi support * VidazooUtils: remove paapi support * paapiTools: remove paapiTools * remove stray references to paapi methods * criteo bid adapter: remove paapi support * ix bid adapter: remove paapi support * logicAd bid adapter: remove paapi support * gumgum bid adapter: remove paapi support * ccx bid adapter: remove paapi support * Remove stray paapi tests * kargo bid adapter: remove paapi support * rtb house bid adapter: remove references to fledge in docs * onetag bid adapter: remove paapi support * medianet bid adapter: remove paapi support * lucead bid adapter: remove paapi support * openxBidAdapter: remove paapi support * optable bid adapter: remove paapi support * sharethrough bid adapter: remove paapi support * silverpush bid adapter: remove paapi support * sspBC bid adapter: remove paapi support * taboola bid adapter: remove paapi support * triplelift bid adapter: remove paapi support * ozone bid adapter: remove paapi support * lint * Delete modules/optableBidAdapter.js * Delete modules/optableBidAdapter.md * Delete test/spec/modules/optableBidAdapter_spec.js --------- Co-authored-by: Patrick McCann --- libraries/paapiTools/buyerOrigins.js | 35 - libraries/vidazooUtils/bidderUtils.js | 7 - modules/.submodules.json | 4 - modules/ccxBidAdapter.js | 4 - modules/criteoBidAdapter.js | 22 +- modules/debugging/bidInterceptor.js | 26 +- modules/debugging/debugging.js | 1 - modules/debugging/pbsInterceptor.js | 9 - modules/gumgumBidAdapter.js | 4 - modules/ixBidAdapter.js | 70 +- modules/ixBidAdapter.md | 5 - modules/kargoBidAdapter.js | 17 +- modules/logicadBidAdapter.js | 16 - modules/luceadBidAdapter.js | 29 +- modules/medianetBidAdapter.js | 18 +- modules/medianetBidAdapter.md | 20 - modules/onetagBidAdapter.js | 14 +- modules/openxBidAdapter.js | 22 +- modules/optableBidAdapter.js | 67 - modules/optableBidAdapter.md | 41 - modules/ozoneBidAdapter.js | 42 +- modules/paapi.js | 808 ------- modules/paapiForGpt.js | 166 -- modules/paapiForGpt.md | 123 - modules/prebidServerBidAdapter/index.ts | 14 +- .../prebidServerBidAdapter/ortbConverter.js | 20 - modules/rtbhouseBidAdapter.md | 43 - modules/sharethroughBidAdapter.js | 16 +- modules/silverpushBidAdapter.js | 17 +- modules/sspBCBidAdapter.js | 19 +- modules/taboolaBidAdapter.js | 51 +- modules/topLevelPaapi.js | 207 -- modules/tripleliftBidAdapter.js | 24 +- src/adRendering.ts | 15 +- src/adapters/bidderFactory.ts | 30 +- src/ajax.ts | 8 +- src/constants.ts | 4 - src/secureCreatives.js | 8 +- test/spec/modules/ccxBidAdapter_spec.js | 74 - test/spec/modules/criteoBidAdapter_spec.js | 212 -- test/spec/modules/debugging_mod_spec.js | 77 +- test/spec/modules/gumgumBidAdapter_spec.js | 18 - test/spec/modules/ixBidAdapter_spec.js | 221 -- test/spec/modules/kargoBidAdapter_spec.js | 49 - test/spec/modules/logicadBidAdapter_spec.js | 61 - test/spec/modules/luceadBidAdapter_spec.js | 8 - test/spec/modules/medianetBidAdapter_spec.js | 39 - test/spec/modules/onetagBidAdapter_spec.js | 38 - test/spec/modules/openxBidAdapter_spec.js | 111 - test/spec/modules/optableBidAdapter_spec.js | 116 - test/spec/modules/ozoneBidAdapter_spec.js | 23 - test/spec/modules/paapiForGpt_spec.js | 216 -- test/spec/modules/paapi_spec.js | 2014 ----------------- .../modules/prebidServerBidAdapter_spec.js | 106 +- .../modules/sharethroughBidAdapter_spec.js | 63 - test/spec/modules/sspBCBidAdapter_spec.js | 7 - test/spec/modules/taboolaBidAdapter_spec.js | 175 -- test/spec/modules/topLevelPaapi_spec.js | 515 ----- .../modules/trafficgateBidAdapter_spec.js | 1 - .../spec/modules/tripleliftBidAdapter_spec.js | 57 - .../modules/twistDigitalBidAdapter_spec.js | 9 - test/spec/modules/vidazooBidAdapter_spec.js | 9 - test/spec/unit/adRendering_spec.js | 21 - test/spec/unit/core/ajax_spec.js | 2 +- test/spec/unit/core/bidderFactory_spec.js | 55 +- test/spec/unit/pbjs_api_spec.js | 1 - test/spec/unit/secureCreatives_spec.js | 12 - 67 files changed, 68 insertions(+), 6288 deletions(-) delete mode 100644 libraries/paapiTools/buyerOrigins.js delete mode 100644 modules/optableBidAdapter.js delete mode 100644 modules/optableBidAdapter.md delete mode 100644 modules/paapi.js delete mode 100644 modules/paapiForGpt.js delete mode 100644 modules/paapiForGpt.md delete mode 100644 modules/topLevelPaapi.js delete mode 100644 test/spec/modules/optableBidAdapter_spec.js delete mode 100644 test/spec/modules/paapiForGpt_spec.js delete mode 100644 test/spec/modules/paapi_spec.js delete mode 100644 test/spec/modules/topLevelPaapi_spec.js diff --git a/libraries/paapiTools/buyerOrigins.js b/libraries/paapiTools/buyerOrigins.js deleted file mode 100644 index ace9b7da073..00000000000 --- a/libraries/paapiTools/buyerOrigins.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - This list is several known buyer origins for PAAPI auctions. - Bidders should add anyone they like to it. - It is not intended to be comphensive nor maintained by the Core team. - Rather, Bid adapters should simply append additional constants whenever - the need arises in their adapter. - - The goal is to reduce expression of common constants over many - bid adapters attempting to define interestGroupBuyers - in advance of network traffic. - - Bidders should consider updating their interstGroupBuyer list - with server communication for auctions initiated after the first bid response. - - Known buyers without current importers are commented out. If you need one, uncomment it. -*/ - -export const BO_CSR_ONET = 'https://csr.onet.pl'; -// export const BO_DOUBLECLICK_GOOGLEADS = 'https://googleads.g.doubleclick.net'; -// export const BO_DOUBLECLICK_TD = 'https://td.doubleclick.net'; -// export const BO_RTBHOUSE = 'https://f.creativecdn.com'; -// export const BO_CRITEO_US = 'https://fledge.us.criteo.com'; -// export const BO_CRITEO_EU = 'https://fledge.eu.criteo.com'; -// export const BO_CRITEO_AS = 'https://fledge.as.criteo.com'; -// export const BO_CRITEO_GRID_MERCURY = 'https://grid-mercury.criteo.com'; -// export const BO_CRITEO_BIDSWITCH_TRADR = 'https://tradr.bsw-sb.criteo.com'; -// export const BO_CRITEO_BIDSWITCH_SANDBOX = 'https://dsp-paapi-sandbox.bsw-ig.criteo.com'; -// export const BO_APPSPOT = 'https://fledge-buyer-testing-1.uc.r.appspot.com'; -// export const BO_OPTABLE = 'https://ads.optable.co'; -// export const BO_ADROLL = 'https://x.adroll.com'; -// export const BO_ADFORM = 'https://a2.adform.net'; -// export const BO_RETARGETLY = 'https://cookieless-campaign.prd-00.retargetly.com'; -// export const BO_AUDIGENT = 'https://proton.ad.gt'; -// export const BO_YAHOO = 'https://pa.ybp.yahoo.com'; -// export const BO_DOTOMI = 'https://usadmm.dotomi.com'; diff --git a/libraries/vidazooUtils/bidderUtils.js b/libraries/vidazooUtils/bidderUtils.js index fa2cea1b6fa..98da155ed10 100644 --- a/libraries/vidazooUtils/bidderUtils.js +++ b/libraries/vidazooUtils/bidderUtils.js @@ -339,13 +339,6 @@ export function buildRequestData(bid, topWindowUrl, sizes, bidderRequest, bidder data.gppSid = bidderRequest.ortb2.regs.gpp_sid; } - if (bidderRequest.paapi?.enabled) { - const fledge = bidderRequest?.ortb2Imp?.ext?.ae; - if (fledge) { - data.fledge = fledge; - } - } - const api = mediaTypes?.video?.api || []; if (api.includes(7)) { const sourceExt = bidderRequest?.ortb2?.source?.ext; diff --git a/modules/.submodules.json b/modules/.submodules.json index 1ee8e440f1b..366327948be 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -140,10 +140,6 @@ "jwplayerVideoProvider", "videojsVideoProvider", "adplayerproVideoProvider" - ], - "paapi": [ - "paapiForGpt", - "topLevelPaapi" ] } } diff --git a/modules/ccxBidAdapter.js b/modules/ccxBidAdapter.js index 14268185027..c1faefb36ec 100644 --- a/modules/ccxBidAdapter.js +++ b/modules/ccxBidAdapter.js @@ -104,10 +104,6 @@ function _buildBid (bid, bidderRequest) { placement.ext = {'pid': bid.params.placementId} - if (bidderRequest.paapi?.enabled) { - placement.ext.ae = bid?.ortb2Imp?.ext?.ae - } - return placement } diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 9965cd1cb2b..46b1e5d75a0 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -1,4 +1,4 @@ -import {deepSetValue, isArray, logError, logWarn, parseUrl, triggerPixel, deepAccess, logInfo} from '../src/utils.js'; +import {deepAccess, deepSetValue, logError, logInfo, logWarn, parseUrl, triggerPixel} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {getStorageManager} from '../src/storageManager.js'; @@ -76,10 +76,6 @@ function imp(buildImp, bidRequest, context) { delete imp.rwdd // oRTB 2.6 field moved to ext - if (!context.fledgeEnabled && imp.ext.igs?.ae) { - delete imp.ext.igs.ae; - } - if (hasVideoMediaType(bidRequest)) { const paramsVideo = bidRequest.params.video; if (paramsVideo !== undefined) { @@ -392,7 +388,7 @@ export const spec = { /** * @param {*} response * @param {ServerRequest} request - * @return {Bid[] | {bids: Bid[], fledgeAuctionConfigs: object[]}} + * @return {Bid[] | {bids: Bid[]}} */ interpretResponse: (response, request) => { if (typeof response?.body === 'undefined') { @@ -400,18 +396,7 @@ export const spec = { } const interpretedResponse = CONVERTER.fromORTB({response: response.body, request: request.data}); - const bids = interpretedResponse.bids || []; - - const fledgeAuctionConfigs = response.body?.ext?.igi?.filter(igi => isArray(igi?.igs)) - .flatMap(igi => igi.igs); - if (fledgeAuctionConfigs?.length) { - return { - bids, - paapi: fledgeAuctionConfigs, - }; - } - - return bids; + return interpretedResponse.bids || []; }, /** @@ -503,7 +488,6 @@ function buildContext(bidRequests, bidderRequest) { url: bidderRequest?.refererInfo?.page || '', debug: queryString['pbt_debug'] === '1', noLog: queryString['pbt_nolog'] === '1', - fledgeEnabled: bidderRequest.paapi?.enabled, amp: bidRequests.some(bidRequest => bidRequest.params.integrationMode === 'amp'), networkId: bidRequests.find(bidRequest => bidRequest.params?.networkId)?.params.networkId, publisherId: bidRequests.find(bidRequest => bidRequest.params?.pubid)?.params.pubid, diff --git a/modules/debugging/bidInterceptor.js b/modules/debugging/bidInterceptor.js index 928fba3f10b..4acf543764c 100644 --- a/modules/debugging/bidInterceptor.js +++ b/modules/debugging/bidInterceptor.js @@ -53,7 +53,6 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { match: this.matcher(ruleDef.when, ruleNo), replace: this.replacer(ruleDef.then, ruleNo), options: Object.assign({}, this.DEFAULT_RULE_OPTIONS, ruleDef.options), - paapi: this.paapiReplacer(ruleDef.paapi || [], ruleNo) } }, /** @@ -144,24 +143,6 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { return response; } }, - - paapiReplacer(paapiDef, ruleNo) { - function wrap(configs = []) { - return configs.map(config => { - return Object.keys(config).some(k => !['config', 'igb'].includes(k)) - ? {config} - : config - }); - } - if (Array.isArray(paapiDef)) { - return () => wrap(paapiDef); - } else if (typeof paapiDef === 'function') { - return (...args) => wrap(paapiDef(...args)) - } else { - this.logger.logError(`Invalid 'paapi' definition for debug bid interceptor (in rule #${ruleNo})`); - } - }, - responseDefaults(bid) { const response = { requestId: bid.bidId, @@ -224,12 +205,11 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { * {{}[]} bids? * {*} bidRequest * {function(*)} addBid called once for each mock response - * addPaapiConfig called once for each mock PAAPI config * {function()} done called once after all mock responses have been run through `addBid` * returns {{bids: {}[], bidRequest: {}} remaining bids that did not match any rule (this applies also to * bidRequest.bids) */ - intercept({bids, bidRequest, addBid, addPaapiConfig, done}) { + intercept({bids, bidRequest, addBid, done}) { if (bids == null) { bids = bidRequest.bids; } @@ -238,12 +218,10 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { const callDone = delayExecution(done, matches.length); matches.forEach((match) => { const mockResponse = match.rule.replace(match.bid, bidRequest); - const mockPaapi = match.rule.paapi(match.bid, bidRequest); const delay = match.rule.options.delay; - this.logger.logMessage(`Intercepted bid request (matching rule #${match.rule.no}), mocking response in ${delay}ms. Request, response, PAAPI configs:`, match.bid, mockResponse, mockPaapi) + this.logger.logMessage(`Intercepted bid request (matching rule #${match.rule.no}), mocking response in ${delay}ms. Request, response:`, match.bid, mockResponse) this.setTimeout(() => { mockResponse && addBid(mockResponse, match.bid); - mockPaapi.forEach(cfg => addPaapiConfig(cfg, match.bid, bidRequest)); callDone(); }, delay) }); diff --git a/modules/debugging/debugging.js b/modules/debugging/debugging.js index d5bbc895ae1..1db564ceb95 100644 --- a/modules/debugging/debugging.js +++ b/modules/debugging/debugging.js @@ -108,7 +108,6 @@ export function makeBidderBidInterceptor({utils}) { bids, bidRequest, addBid: wrapCallback(cbs.onBid), - addPaapiConfig: wrapCallback((config, bidRequest) => cbs.onPaapi({bidId: bidRequest.bidId, ...config})), done })); if (bids.length === 0) { diff --git a/modules/debugging/pbsInterceptor.js b/modules/debugging/pbsInterceptor.js index 753f502002d..8e7435337bf 100644 --- a/modules/debugging/pbsInterceptor.js +++ b/modules/debugging/pbsInterceptor.js @@ -4,7 +4,6 @@ export function makePbsInterceptor({createBid, utils}) { onResponse, onError, onBid, - onFledge, }) { let responseArgs; const done = delayExecution(() => onResponse(...responseArgs), bidRequests.length + 1) @@ -22,14 +21,6 @@ export function makePbsInterceptor({createBid, utils}) { .map((req) => interceptBids({ bidRequest: req, addBid, - addPaapiConfig(config, bidRequest, bidderRequest) { - onFledge({ - adUnitCode: bidRequest.adUnitCode, - ortb2: bidderRequest.ortb2, - ortb2Imp: bidRequest.ortb2Imp, - ...config - }) - }, done }).bidRequest) .filter((req) => req.bids.length > 0) diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 3f7339a4f08..46249591937 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -376,7 +376,6 @@ function buildRequests(validBidRequests, bidderRequest) { const { currency, floor } = _getFloor(mediaTypes, params.bidfloor, bidRequest); const eids = getEids(userId); const gpid = deepAccess(ortb2Imp, 'ext.gpid'); - const paapiEligible = deepAccess(ortb2Imp, 'ext.ae') === 1 let sizes = [1, 1]; let data = {}; data.displaymanager = 'Prebid.js - gumgum'; @@ -465,9 +464,6 @@ function buildRequests(validBidRequests, bidderRequest) { } else { // legacy params data = { ...data, ...handleLegacyParams(params, sizes) }; } - if (paapiEligible) { - data.ae = paapiEligible - } if (gdprConsent) { data.gdprApplies = gdprConsent.gdprApplies ? 1 : 0; } diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index 1df9570aab8..da01c3daa07 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -686,8 +686,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) { r = addRequestedFeatureToggles(r, FEATURE_TOGGLES.REQUESTED_FEATURE_TOGGLES) // getting ixdiags for adunits of the video, outstream & multi format (MF) style - const fledgeEnabled = deepAccess(bidderRequest, 'paapi.enabled') - const ixdiag = buildIXDiag(validBidRequests, fledgeEnabled); + const ixdiag = buildIXDiag(validBidRequests); for (const key in ixdiag) { r.ext.ixdiag[key] = ixdiag[key]; } @@ -954,8 +953,6 @@ function addImpressions(impressions, impKeys, r, adUnitIndex) { const dfpAdUnitCode = impressions[impKeys[adUnitIndex]].dfp_ad_unit_code; const tid = impressions[impKeys[adUnitIndex]].tid; const sid = impressions[impKeys[adUnitIndex]].sid; - const auctionEnvironment = impressions[impKeys[adUnitIndex]].ae; - const paapi = impressions[impKeys[adUnitIndex]].paapi; const bannerImpressions = impressionObjects.filter(impression => BANNER in impression); const otherImpressions = impressionObjects.filter(impression => !(BANNER in impression)); @@ -1005,7 +1002,7 @@ function addImpressions(impressions, impKeys, r, adUnitIndex) { _bannerImpression.banner.pos = position; } - if (dfpAdUnitCode || gpid || tid || sid || auctionEnvironment || externalID || paapi) { + if (dfpAdUnitCode || gpid || tid || sid || externalID) { _bannerImpression.ext = {}; _bannerImpression.ext.dfp_ad_unit_code = dfpAdUnitCode; @@ -1013,12 +1010,6 @@ function addImpressions(impressions, impKeys, r, adUnitIndex) { _bannerImpression.ext.tid = tid; _bannerImpression.ext.sid = sid; _bannerImpression.ext.externalID = externalID; - - // enable fledge auction - if (Number(auctionEnvironment) === 1) { - _bannerImpression.ext.ae = 1; - _bannerImpression.ext.paapi = paapi; - } } if ('bidfloor' in bannerImps[0]) { @@ -1272,10 +1263,9 @@ function addIdentifiersInfo(impressions, r, impKeys, adUnitIndex, payload, baseU * Calculates IX diagnostics values and packages them into an object * * @param {Array} validBidRequests - The valid bid requests from prebid - * @param {boolean} fledgeEnabled - Flag indicating if protected audience (fledge) is enabled * @return {Object} IX diag values for ad units */ -function buildIXDiag(validBidRequests, fledgeEnabled) { +function buildIXDiag(validBidRequests) { var adUnitMap = validBidRequests .map(bidRequest => bidRequest.adUnitCode) .filter((value, index, arr) => arr.indexOf(value) === index); @@ -1292,7 +1282,6 @@ function buildIXDiag(validBidRequests, fledgeEnabled) { version: '$prebid.version$', url: window.location.href.split('?')[0], vpd: defaultVideoPlacement, - ae: fledgeEnabled, eidLength: allEids.length }; @@ -1417,23 +1406,6 @@ function createBannerImps(validBidRequest, missingBannerSizes, bannerImps, bidde bannerImps[validBidRequest.adUnitCode].tagId = deepAccess(validBidRequest, 'params.tagId'); bannerImps[validBidRequest.adUnitCode].pos = deepAccess(validBidRequest, 'mediaTypes.banner.pos'); - // Add Fledge flag if enabled - const fledgeEnabled = deepAccess(bidderRequest, 'paapi.enabled') - if (fledgeEnabled) { - const auctionEnvironment = deepAccess(validBidRequest, 'ortb2Imp.ext.ae') - const paapi = deepAccess(validBidRequest, 'ortb2Imp.ext.paapi') - if (paapi) { - bannerImps[validBidRequest.adUnitCode].paapi = paapi - } - if (auctionEnvironment) { - if (isInteger(auctionEnvironment)) { - bannerImps[validBidRequest.adUnitCode].ae = auctionEnvironment; - } else { - logWarn('error setting auction environment flag - must be an integer') - } - } - } - // AdUnit-Specific First Party Data const adUnitFPD = deepAccess(validBidRequest, 'ortb2Imp.ext.data'); if (adUnitFPD) { @@ -1766,9 +1738,6 @@ export const spec = { const bids = []; let bid = null; - // Extract the FLEDGE auction configuration list from the response - let fledgeAuctionConfigs = deepAccess(serverResponse, 'body.ext.protectedAudienceAuctionConfigs') || []; - FEATURE_TOGGLES.setFeatureToggles(serverResponse); if (!serverResponse.hasOwnProperty('body')) { @@ -1812,29 +1781,7 @@ export const spec = { } } } - - if (Array.isArray(fledgeAuctionConfigs) && fledgeAuctionConfigs.length > 0) { - // Validate and filter fledgeAuctionConfigs - fledgeAuctionConfigs = fledgeAuctionConfigs.filter(config => { - if (!isValidAuctionConfig(config)) { - logWarn('Malformed auction config detected:', config); - return false; - } - return true; - }); - - try { - return { - bids, - paapi: fledgeAuctionConfigs, - }; - } catch (error) { - logWarn('Error attaching AuctionConfigs', error); - return bids; - } - } else { - return bids; - } + return bids; }, /** @@ -2044,15 +1991,6 @@ function getFormatCount(imp) { return formatCount; } -/** - * Checks if auction config is valid - * @param {object} config - * @returns bool - */ -function isValidAuctionConfig(config) { - return typeof config === 'object' && config !== null; -} - /** * Adds device.w / device.h info * @param {object} r diff --git a/modules/ixBidAdapter.md b/modules/ixBidAdapter.md index e6f6f8dc320..14a013fd6be 100644 --- a/modules/ixBidAdapter.md +++ b/modules/ixBidAdapter.md @@ -468,11 +468,6 @@ pbjs.setConfig({ The timeout value must be a positive whole number in milliseconds. -Protected Audience API (FLEDGE) -=========================== - -In order to enable receiving [Protected Audience API](https://developer.chrome.com/en/docs/privacy-sandbox/fledge/) traffic, follow Prebid's documentation on [paapiForGpt](https://docs.prebid.org/dev-docs/modules/paapiForGpt.html) module to build and enable Fledge. - Additional Information ====================== diff --git a/modules/kargoBidAdapter.js b/modules/kargoBidAdapter.js index 1909112d36d..ad70cf2e953 100644 --- a/modules/kargoBidAdapter.js +++ b/modules/kargoBidAdapter.js @@ -199,7 +199,6 @@ function buildRequests(validBidRequests, bidderRequest) { function interpretResponse(response, bidRequest) { const bids = response.body; - const fledgeAuctionConfigs = []; const bidResponses = []; if (isEmpty(bids) || typeof bids !== 'object') { @@ -241,23 +240,9 @@ function interpretResponse(response, bidRequest) { } bidResponses.push(bidResponse); - - if (adUnit.auctionConfig) { - fledgeAuctionConfigs.push({ - bidId: bidID, - config: adUnit.auctionConfig - }) - } } - if (fledgeAuctionConfigs.length > 0) { - return { - bids: bidResponses, - paapi: fledgeAuctionConfigs - } - } else { - return bidResponses; - } + return bidResponses; } function getUserSyncs(syncOptions, _, gdprConsent, usPrivacy, gppConsent) { diff --git a/modules/logicadBidAdapter.js b/modules/logicadBidAdapter.js index 64a848c157e..310513ab392 100644 --- a/modules/logicadBidAdapter.js +++ b/modules/logicadBidAdapter.js @@ -42,14 +42,6 @@ export const spec = { bids.push(seatbid.bid); }) - const fledgeAuctionConfigs = deepAccess(serverResponse, 'ext.fledgeAuctionConfigs') || []; - if (fledgeAuctionConfigs.length) { - return { - bids, - paapi: fledgeAuctionConfigs, - }; - } - return bids; }, getUserSyncs: function (syncOptions, serverResponses) { @@ -74,14 +66,6 @@ function newBidRequest(bidRequest, bidderRequest) { mediaTypes: bidRequest.mediaTypes, } - const fledgeEnabled = deepAccess(bidderRequest, 'paapi.enabled') - if (fledgeEnabled) { - const ae = deepAccess(bidRequest, 'ortb2Imp.ext.ae'); - if (ae) { - bid.ae = ae; - } - } - const data = { // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auctionId: bidRequest.auctionId, diff --git a/modules/luceadBidAdapter.js b/modules/luceadBidAdapter.js index 134b6e505eb..186002b77ba 100755 --- a/modules/luceadBidAdapter.js +++ b/modules/luceadBidAdapter.js @@ -106,34 +106,7 @@ function interpretResponse(serverResponse, bidRequest) { })); logInfo('interpretResponse', {serverResponse, bidRequest, bidRequestData, bids}); - - if (response?.enable_pa === false) { return bids; } - - const fledgeAuctionConfigs = (response.bids || []).map(bid => ({ - bidId: bid?.bid_id, - config: { - seller: baseUrl, - decisionLogicUrl: `${baseUrl}/js/ssp.js`, - interestGroupBuyers: [baseUrl], - requestedSize: bid?.size, - auctionSignals: { - size: bid?.size, - }, - perBuyerSignals: { - [baseUrl]: { - prebid_paapi: true, - prebid_bid_id: bid?.bid_id, - prebid_request_id: bidRequestData.request_id, - placement_id: bid.placement_id, - // floor, - is_sra: true, - endpoint_url: endpointUrl, - }, - } - } - })); - - return {bids, paapi: fledgeAuctionConfigs}; + return {bids}; } function report(type, data) { diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index cec3880a6d7..18a557c8617 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -256,9 +256,6 @@ function slotParams(bidRequest, bidderRequests) { if (floorInfo && floorInfo.length > 0) { params.bidfloors = floorInfo; } - if (bidderRequests.paapi?.enabled) { - params.ext.ae = bidRequest?.ortb2Imp?.ext?.ae; - } return params; } @@ -487,7 +484,7 @@ export const spec = { * Unpack the response from the server into a list of bids. * * @param {*} serverResponse A successful response from the server. - * @returns {{bids: *[], fledgeAuctionConfigs: *[]} | *[]} An object containing bids and fledgeAuctionConfigs if present, otherwise an array of bids. + * @returns {*[]} An array of bids. */ interpretResponse: function(serverResponse, request) { let validBids = []; @@ -502,18 +499,7 @@ export const spec = { validBids = bids.filter(bid => isValidBid(bid)); validBids.forEach(addRenderer); } - const fledgeAuctionConfigs = deepAccess(serverResponse, 'body.ext.paApiAuctionConfigs') || []; - const ortbAuctionConfigs = deepAccess(serverResponse, 'body.ext.igi') || []; - if (fledgeAuctionConfigs.length === 0 && ortbAuctionConfigs.length === 0) { - return validBids; - } - if (ortbAuctionConfigs.length > 0) { - fledgeAuctionConfigs.push(...ortbAuctionConfigs.map(({igs}) => igs || []).flat()); - } - return { - bids: validBids, - paapi: fledgeAuctionConfigs, - } + return validBids; }, getUserSyncs: function(syncOptions, serverResponses) { const cookieSyncUrls = fetchCookieSyncUrls(serverResponses); diff --git a/modules/medianetBidAdapter.md b/modules/medianetBidAdapter.md index 500c9f3f12b..1af49e5b6dc 100644 --- a/modules/medianetBidAdapter.md +++ b/modules/medianetBidAdapter.md @@ -181,23 +181,3 @@ var adUnits = [{ ``` - -# Protected Audience API (FLEDGE) - -In order to enable PAAPI auctions follow the instructions below: - -1. Add the paapiForGpt and paapi modules to your prebid bundle. -2. Add the following configuration for the module -``` -pbjs.que.push(function() { - pbjs.setConfig({ - paapi: { - enabled: true, - bidders: ['medianet'], - defaultForSlots: 1 - } - }); -}); -``` - -For a detailed guide to enabling PAAPI auctions follow Prebid's documentation on [paapiForGpt](https://docs.prebid.org/dev-docs/modules/paapiForGpt.html) diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js index d919d1398b7..827291f5407 100644 --- a/modules/onetagBidAdapter.js +++ b/modules/onetagBidAdapter.js @@ -145,7 +145,7 @@ function buildRequests(validBidRequests, bidderRequest) { const connection = getConnectionInfo(); payload.networkConnectionType = connection?.type || null; payload.networkEffectiveConnectionType = connection?.effectiveType || null; - payload.fledgeEnabled = Boolean(bidderRequest?.paapi?.enabled) + payload.fledgeEnabled = false; return { method: 'POST', url: ENDPOINT, @@ -160,7 +160,7 @@ function interpretResponse(serverResponse, bidderRequest) { if (!body || (body.nobid && body.nobid === true)) { return bids; } - if (!body.fledgeAuctionConfigs && (!body.bids || !Array.isArray(body.bids) || body.bids.length === 0)) { + if (!body.bids || !Array.isArray(body.bids) || body.bids.length === 0) { return bids; } Array.isArray(body.bids) && body.bids.forEach(bid => { @@ -206,15 +206,7 @@ function interpretResponse(serverResponse, bidderRequest) { bids.push(responseBid); }); - if (body.fledgeAuctionConfigs && Array.isArray(body.fledgeAuctionConfigs)) { - const fledgeAuctionConfigs = body.fledgeAuctionConfigs - return { - bids, - paapi: fledgeAuctionConfigs - } - } else { - return bids; - } + return bids; } function createRenderer(bid, rendererOptions = {}) { diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 2da04ad3e38..2db74ecde60 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -98,27 +98,7 @@ const converter = ortbConverter({ utils.deepSetValue(ortbResponse, 'ext.platform', ortbRequest.ext.platform); } } - const response = buildResponse(bidResponses, ortbResponse, context); - // TODO: we may want to standardize this and move fledge logic to ortbConverter - let fledgeAuctionConfigs = utils.deepAccess(ortbResponse, 'ext.fledge_auction_configs'); - if (fledgeAuctionConfigs) { - fledgeAuctionConfigs = Object.entries(fledgeAuctionConfigs).map(([bidId, cfg]) => { - return { - bidId, - config: mergeDeep(Object.assign({}, cfg), { - auctionSignals: { - ortb2Imp: context.impContext[bidId]?.imp, - }, - }), - } - }); - return { - bids: response.bids, - paapi: fledgeAuctionConfigs, - } - } else { - return response - } + return buildResponse(bidResponses, ortbResponse, context); }, overrides: { imp: { diff --git a/modules/optableBidAdapter.js b/modules/optableBidAdapter.js deleted file mode 100644 index d2dae252e6c..00000000000 --- a/modules/optableBidAdapter.js +++ /dev/null @@ -1,67 +0,0 @@ -import * as utils from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { config } from '../src/config.js'; -import { BANNER } from '../src/mediaTypes.js'; -import { ortbConverter } from '../libraries/ortbConverter/converter.js' -const converter = ortbConverter({ - context: { netRevenue: true, ttl: 300 }, - imp(buildImp, bidRequest, context) { - const imp = buildImp(bidRequest, context); - utils.mergeDeep(imp, { - tagid: bidRequest.params.site, - }); - return imp; - } -}); -const BIDDER_CODE = 'optable'; -const DEFAULT_REGION = 'ca' -const DEFAULT_ORIGIN = 'https://ads.optable.co' - -function getOrigin() { - return config.getConfig('optable.origin') ?? DEFAULT_ORIGIN; -} - -function getBaseUrl() { - const region = config.getConfig('optable.region') ?? DEFAULT_REGION; - return `${getOrigin()}/${region}` -} - -export const spec = { - code: BIDDER_CODE, - isBidRequestValid: function(bid) { return !!bid.params?.site }, - buildRequests: function(bidRequests, bidderRequest) { - const requestURL = `${getBaseUrl()}/ortb2/v1/ssp/bid` - const data = converter.toORTB({ bidRequests, bidderRequest, context: { mediaType: BANNER } }); - return { method: 'POST', url: requestURL, data } - }, - buildPAAPIConfigs: function(bidRequests) { - const origin = getOrigin(); - return bidRequests - .filter(req => req.ortb2Imp?.ext?.ae) - .map(bid => ({ - bidId: bid.bidId, - config: { - seller: origin, - decisionLogicURL: `${getBaseUrl()}/paapi/v1/ssp/decision-logic.js?origin=${bid.params.site}`, - interestGroupBuyers: [origin], - perBuyerMultiBidLimits: { - [origin]: 100 - }, - perBuyerCurrencies: { - [origin]: 'USD' - } - } - })) - }, - interpretResponse: function(response, request) { - const bids = converter.fromORTB({ response: response.body, request: request.data }).bids - const auctionConfigs = (response.body.ext?.optable?.fledge?.auctionconfigs ?? []).map((cfg) => { - const { impid, ...config } = cfg; - return { bidId: impid, config } - }) - - return { bids, paapi: auctionConfigs } - }, - supportedMediaTypes: [BANNER] -} -registerBidder(spec); diff --git a/modules/optableBidAdapter.md b/modules/optableBidAdapter.md deleted file mode 100644 index a7c4829fe63..00000000000 --- a/modules/optableBidAdapter.md +++ /dev/null @@ -1,41 +0,0 @@ -# Overview - -``` -Module Name: Optable Bidder Adapter -Module Type: Bidder Adapter -Maintainer: prebid@optable.co -``` - -# Description - -Module that connects to Optable's demand sources. - -# Bid Parameters -## Banner - -| Name | Scope | Type | Description | Example -| ---- | ----- | ---- | ----------- | ------- -| `site` | required | String | Optable site ID provided by your Optable representative. | "aaaaaaaa" - -## Video - -Not supported at the moment. - -# Example -```javascript -var adUnits = [ - { - code: 'test-div', - sizes: [[728, 90]], // a display size - mediaTypes: {'banner': {}}, - bids: [ - { - bidder: 'optable', - params: { - site: 'aaaaaaaa', - }, - }, - ], - }, -]; -``` diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index e804eef164e..027d623ba12 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -1,21 +1,24 @@ import { - logInfo, - logError, deepAccess, - logWarn, + deepClone, deepSetValue, + generateUUID, + getBidIdParameter, isArray, + logError, + logInfo, + logWarn, mergeDeep, - parseUrl, - generateUUID, isInteger, deepClone, getBidIdParameter + parseUrl } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; import {getPriceBucketString} from '../src/cpmBucketManager.js'; -import { Renderer } from '../src/Renderer.js'; +import {Renderer} from '../src/Renderer.js'; import {getRefererInfo} from '../src/refererDetection.js'; import {toOrtb25} from '../libraries/ortb2.5Translator/translator.js'; + const BIDDER_CODE = 'ozone'; const ORIGIN = 'https://elb.the-ozone-project.com'; const AUCTIONURI = '/openrtb2/auction'; @@ -137,7 +140,6 @@ export const spec = { if (this.blockTheRequest()) { return []; } - const fledgeEnabled = !!bidderRequest.fledgeEnabled; let htmlParams = {'publisherId': '', 'siteId': ''}; if (validBidRequests.length > 0) { Object.assign(this.cookieSyncBag.userIdObject, this.findAllUserIdsFromEids(validBidRequests[0])); @@ -274,14 +276,6 @@ export const spec = { if (auctionId) { obj.ext.auctionId = auctionId; } - if (fledgeEnabled) { - const auctionEnvironment = deepAccess(ozoneBidRequest, 'ortb2Imp.ext.ae'); - if (isInteger(auctionEnvironment)) { - deepSetValue(obj, 'ext.ae', auctionEnvironment); - } else { - logError(`ignoring ortb2Imp.ext.ae - not an integer for obj.id=${obj.id}`); - } - } return obj; }); const extObj = {}; @@ -572,20 +566,6 @@ export const spec = { } } let ret = arrAllBids; - let fledgeAuctionConfigs = deepAccess(serverResponse, 'ext.igi') || []; - if (isArray(fledgeAuctionConfigs) && fledgeAuctionConfigs.length > 0) { - fledgeAuctionConfigs = fledgeAuctionConfigs.filter(cfg => { - if (typeof cfg !== 'object' || cfg === null) { - logWarn('Removing malformed fledge auction config:', cfg); - return false; - } - return true; - }); - ret = { - bids: arrAllBids, - fledgeAuctionConfigs, - }; - } const endTime = new Date().getTime(); logInfo(`interpretResponse going to return at time ${endTime} (took ${endTime - startTime}ms) Time from buildRequests Start -> interpretRequests End = ${endTime - this.propertyBag.buildRequestsStart}ms`); logInfo('will return: ', deepClone(ret)); diff --git a/modules/paapi.js b/modules/paapi.js deleted file mode 100644 index e67b24bdcfc..00000000000 --- a/modules/paapi.js +++ /dev/null @@ -1,808 +0,0 @@ -/** - * Collect PAAPI component auction configs from bid adapters and make them available through `pbjs.getPAAPIConfig()` - */ -import {config} from '../src/config.js'; -import {getHook, hook, module} from '../src/hook.js'; -import { - deepAccess, - deepEqual, - deepSetValue, - logError, - logInfo, - logWarn, - mergeDeep, - sizesToSizeTuples -} from '../src/utils.js'; -import {IMP, PBS, registerOrtbProcessor, RESPONSE} from '../src/pbjsORTB.js'; -import * as events from '../src/events.js'; -import {EVENTS} from '../src/constants.js'; -import {currencyCompare} from '../libraries/currencyUtils/currency.js'; -import {keyCompare, maximum, minimum} from '../src/utils/reducers.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import {auctionStore} from '../libraries/weakStore/weakStore.js'; -import {adapterMetrics, guardTids} from '../src/adapters/bidderFactory.js'; -import {defer, PbPromise} from '../src/utils/promise.js'; -import {auctionManager} from '../src/auctionManager.js'; - -const MODULE = 'PAAPI'; - -const submodules = []; -const USED = new WeakSet(); - -export function registerSubmodule(submod) { - submodules.push(submod); - submod.init && submod.init({ - getPAAPIConfig, - expandFilters - }); -} - -module('paapi', registerSubmodule); - -/* auction configs as returned by getPAAPIConfigs */ -const configsForAuction = auctionStore(); - -/* auction configs returned by adapters, but waiting for end-of-auction signals before they're added to configsForAuction */ -const pendingConfigsForAuction = auctionStore(); - -/* igb returned by adapters, waiting for end-of-auction signals before they're merged into configForAuctions */ -const pendingBuyersForAuction = auctionStore(); - -/* for auction configs that were generated in parallel with auctions (and contain promises), their resolve/reject methods */ -const deferredConfigsForAuction = auctionStore(); - -let latestAuctionForAdUnit = {}; -let moduleConfig = {}; - -config.getConfig('paapi', config => { - init(config.paapi); -}); - -export function reset() { - submodules.splice(0, submodules.length); - latestAuctionForAdUnit = {}; -} - -export function init(cfg) { - if (cfg && cfg.enabled === true) { - if (!moduleConfig.enabled) { - attachHandlers(); - } - moduleConfig = cfg; - logInfo(`${MODULE} enabled (browser ${isFledgeSupported() ? 'supports' : 'does NOT support'} runAdAuction)`, cfg); - } else { - if (moduleConfig.enabled) { - detachHandlers(); - } - moduleConfig = {}; - logInfo(`${MODULE} disabled`, cfg); - } -} - -function attachHandlers() { - getHook('addPaapiConfig').before(addPaapiConfigHook); - getHook('makeBidRequests').before(addPaapiData); - getHook('makeBidRequests').after(markForFledge); - getHook('processBidderRequests').before(parallelPaapiProcessing, 9); - // resolve params before parallel processing - getHook('processBidderRequests').before(buildPAAPIParams, 10); - getHook('processBidderRequests').before(adAuctionHeadersHook); - events.on(EVENTS.AUCTION_INIT, onAuctionInit); - events.on(EVENTS.AUCTION_END, onAuctionEnd); -} - -function detachHandlers() { - getHook('addPaapiConfig').getHooks({hook: addPaapiConfigHook}).remove(); - getHook('makeBidRequests').getHooks({hook: addPaapiData}).remove(); - getHook('makeBidRequests').getHooks({hook: markForFledge}).remove(); - getHook('processBidderRequests').getHooks({hook: parallelPaapiProcessing}).remove(); - getHook('processBidderRequests').getHooks({hook: buildPAAPIParams}).remove(); - getHook('processBidderRequests').getHooks({hook: adAuctionHeadersHook}).remove(); - events.off(EVENTS.AUCTION_INIT, onAuctionInit); - events.off(EVENTS.AUCTION_END, onAuctionEnd); -} - -export function adAuctionHeadersHook(next, spec, bids, bidderRequest, ajax, ...args) { - if (bidderRequest.paapi?.enabled) { - ajax = ((orig) => { - return function (url, callback, data, options) { - options = options ?? {}; - options.adAuctionHeaders = options.adAuctionHeaders ?? true; - return orig.call(this, url, callback, data, options); - } - })(ajax); - } - return next.call(this, spec, bids, bidderRequest, ajax, ...args); -} - -function getStaticSignals(adUnit = {}) { - const cfg = {}; - const requestedSize = getRequestedSize(adUnit); - if (requestedSize) { - cfg.requestedSize = requestedSize; - } - return cfg; -} - -function getSlotSignals(bidsReceived = [], bidRequests = []) { - let bidfloor, bidfloorcur; - if (bidsReceived.length > 0) { - const bestBid = bidsReceived.reduce(maximum(currencyCompare(bid => [bid.cpm, bid.currency]))); - bidfloor = bestBid.cpm; - bidfloorcur = bestBid.currency; - } else { - const floors = bidRequests.map(bid => typeof bid.getFloor === 'function' && bid.getFloor()).filter(f => f); - const minFloor = floors.length && floors.reduce(minimum(currencyCompare(floor => [floor.floor, floor.currency]))); - bidfloor = minFloor?.floor; - bidfloorcur = minFloor?.currency; - } - const cfg = {}; - if (bidfloor) { - deepSetValue(cfg, 'auctionSignals.prebid.bidfloor', bidfloor); - bidfloorcur && deepSetValue(cfg, 'auctionSignals.prebid.bidfloorcur', bidfloorcur); - } - return cfg; -} - -export function buyersToAuctionConfigs(igbRequests, merge = mergeBuyers, config = moduleConfig?.componentSeller ?? {}, partitioners = { - compact: (igbRequests) => partitionBuyers(igbRequests.map(req => req[1])).map(part => [{}, part]), - expand: partitionBuyersByBidder -}) { - if (!config.auctionConfig) { - logWarn(MODULE, 'Cannot use IG buyers: paapi.componentSeller.auctionConfig not set', igbRequests.map(req => req[1])); - return []; - } - const partition = partitioners[config.separateAuctions ? 'expand' : 'compact']; - return partition(igbRequests) - .map(([request, igbs]) => { - const auctionConfig = mergeDeep(merge(igbs), config.auctionConfig); - auctionConfig.auctionSignals = setFPD(auctionConfig.auctionSignals || {}, request); - return [request, auctionConfig]; - }); -} - -function onAuctionEnd({auctionId, bidsReceived, bidderRequests, adUnitCodes, adUnits}) { - const adUnitsByCode = Object.fromEntries(adUnits?.map(au => [au.code, au]) || []); - const allReqs = bidderRequests?.flatMap(br => br.bids); - const paapiConfigs = configsForAuction(auctionId); - (adUnitCodes || []).forEach(au => { - if (!paapiConfigs.hasOwnProperty(au)) { - paapiConfigs[au] = null; - } - !latestAuctionForAdUnit.hasOwnProperty(au) && (latestAuctionForAdUnit[au] = null); - }); - - const pendingConfigs = pendingConfigsForAuction(auctionId); - const pendingBuyers = pendingBuyersForAuction(auctionId); - - if (pendingConfigs && pendingBuyers) { - Object.entries(pendingBuyers).forEach(([adUnitCode, igbRequests]) => { - buyersToAuctionConfigs(igbRequests).forEach(([{bidder}, auctionConfig]) => append(pendingConfigs, adUnitCode, {id: getComponentSellerConfigId(bidder), config: auctionConfig})) - }) - } - - const deferredConfigs = deferredConfigsForAuction(auctionId); - - const adUnitsWithConfigs = Array.from(new Set(Object.keys(pendingConfigs).concat(Object.keys(deferredConfigs)))); - const signals = Object.fromEntries( - adUnitsWithConfigs.map(adUnitCode => { - latestAuctionForAdUnit[adUnitCode] = auctionId; - const forThisAdUnit = (bid) => bid.adUnitCode === adUnitCode; - return [adUnitCode, { - ...getStaticSignals(adUnitsByCode[adUnitCode]), - ...getSlotSignals(bidsReceived?.filter(forThisAdUnit), allReqs?.filter(forThisAdUnit)) - }] - }) - ) - - const configsById = {}; - Object.entries(pendingConfigs || {}).forEach(([adUnitCode, auctionConfigs]) => { - auctionConfigs.forEach(({id, config}) => append(configsById, id, { - adUnitCode, - config: mergeDeep({}, signals[adUnitCode], config) - })); - }); - - function resolveSignals(signals, deferrals) { - Object.entries(deferrals).forEach(([signal, {resolve, default: defaultValue}]) => { - let value = signals.hasOwnProperty(signal) ? signals[signal] : null; - if (value == null && defaultValue == null) { - value = undefined; - } else if (typeof defaultValue === 'object' && typeof value === 'object') { - value = mergeDeep({}, defaultValue, value); - } else { - value = value ?? defaultValue - } - resolve(value); - }) - } - - Object.entries(deferredConfigs).forEach(([adUnitCode, {top, components}]) => { - resolveSignals(signals[adUnitCode], top); - Object.entries(components).forEach(([configId, {deferrals}]) => { - const matchingConfigs = configsById.hasOwnProperty(configId) ? configsById[configId] : []; - if (matchingConfigs.length > 1) { - logWarn(`Received multiple PAAPI configs for the same bidder and seller (${configId}), active PAAPI auctions will only see the first`); - } - const {config} = matchingConfigs.shift() ?? {config: {...signals[adUnitCode]}} - resolveSignals(config, deferrals); - }) - }); - - const newConfigs = Object.values(configsById).flatMap(configs => configs); - const hasDeferredConfigs = Object.keys(deferredConfigs).length > 0; - - if (moduleConfig.parallel && hasDeferredConfigs && newConfigs.length > 0) { - logError(`Received PAAPI configs after PAAPI auctions were already started in parallel with their contextual auction`, newConfigs) - } - - newConfigs.forEach(({adUnitCode, config}) => { - if (paapiConfigs[adUnitCode] == null) { - paapiConfigs[adUnitCode] = { - ...signals[adUnitCode], - componentAuctions: [] - } - } - paapiConfigs[adUnitCode].componentAuctions.push(mergeDeep({}, signals[adUnitCode], config)); - }); - - if (!moduleConfig.parallel || !hasDeferredConfigs) { - submodules.forEach(submod => submod.onAuctionConfig?.(auctionId, paapiConfigs)); - } -} - -function append(target, key, value) { - !target.hasOwnProperty(key) && (target[key] = []); - target[key].push(value); -} - -function setFPD(target, {ortb2, ortb2Imp}) { - ortb2 != null && deepSetValue(target, 'prebid.ortb2', mergeDeep({}, ortb2, target.prebid?.ortb2)); - ortb2Imp != null && deepSetValue(target, 'prebid.ortb2Imp', mergeDeep({}, ortb2Imp, target.prebid?.ortb2Imp)); - return target; -} - -function getConfigId(bidderCode, seller) { - return `${bidderCode}::${seller}`; -} - -function getComponentSellerConfigId(bidderCode) { - return moduleConfig.componentSeller.separateAuctions ? `igb::${bidderCode}` : 'igb'; -} - -export function addPaapiConfigHook(next, request, paapiConfig) { - if (getFledgeConfig(config.getCurrentBidder()).enabled) { - const {adUnitCode, auctionId, bidder} = request; - - function storePendingData(store, data) { - const target = store(auctionId); - if (target != null) { - append(target, adUnitCode, data) - } else { - logWarn(MODULE, `Received PAAPI config for auction that has closed (auction '${auctionId}', adUnit '${adUnitCode}')`, data); - } - } - - const {config, igb} = paapiConfig; - if (config) { - config.auctionSignals = setFPD(config.auctionSignals || {}, request); - const pbs = config.perBuyerSignals = config.perBuyerSignals ?? {}; - (config.interestGroupBuyers || []).forEach(buyer => { - pbs[buyer] = setFPD(pbs[buyer] ?? {}, request); - }) - storePendingData(pendingConfigsForAuction, {id: getConfigId(bidder, config.seller), config}); - } - if (igb && checkOrigin(igb)) { - igb.pbs = setFPD(igb.pbs || {}, request); - storePendingData(pendingBuyersForAuction, [request, igb]) - } - } - next(request, paapiConfig); -} - -export const IGB_TO_CONFIG = { - cur: 'perBuyerCurrencies', - pbs: 'perBuyerSignals', - ps: 'perBuyerPrioritySignals', - maxbid: 'auctionSignals.prebid.perBuyerMaxbid', -} - -function checkOrigin(igb) { - if (igb.origin) return true; - logWarn('PAAPI buyer does not specify origin and will be ignored', igb); -} - -/** - * Convert a list of InterestGroupBuyer (igb) objects into a partial auction config. - * https://github.com/InteractiveAdvertisingBureau/openrtb/blob/main/extensions/community_extensions/Protected%20Audience%20Support.md - */ -export function mergeBuyers(igbs) { - const buyers = new Set(); - return Object.assign( - igbs.reduce((config, igb) => { - if (checkOrigin(igb)) { - if (!buyers.has(igb.origin)) { - buyers.add(igb.origin); - Object.entries(IGB_TO_CONFIG).forEach(([igbField, configField]) => { - if (igb[igbField] != null) { - const entry = deepAccess(config, configField) || {} - entry[igb.origin] = igb[igbField]; - deepSetValue(config, configField, entry); - } - }); - } else { - logWarn(MODULE, `Duplicate buyer: ${igb.origin}. All but the first will be ignored`, igbs); - } - } - return config; - }, {}), - { - interestGroupBuyers: Array.from(buyers.keys()) - } - ); -} - -/** - * Partition a list of InterestGroupBuyer (igb) object into sets that can each be merged into a single auction. - * If the same buyer (origin) appears more than once, it will be split across different partition unless the igb objects - * are identical. - */ -export function partitionBuyers(igbs) { - return igbs.reduce((partitions, igb) => { - if (checkOrigin(igb)) { - let partition = partitions.find(part => !part.hasOwnProperty(igb.origin) || deepEqual(part[igb.origin], igb)); - if (!partition) { - partition = {}; - partitions.push(partition); - } - partition[igb.origin] = igb; - } - return partitions; - }, []).map(part => Object.values(part)); -} - -export function partitionBuyersByBidder(igbRequests) { - const requests = {}; - const igbs = {}; - igbRequests.forEach(([request, igb]) => { - !requests.hasOwnProperty(request.bidder) && (requests[request.bidder] = request); - append(igbs, request.bidder, igb); - }) - return Object.entries(igbs).map(([bidder, igbs]) => [requests[bidder], igbs]) -} - -/** - * Expand PAAPI api filters into a map from ad unit code to auctionId. - * - * auctionId when specified, the result will have this as the value for each entry. - * when not specified, each ad unit will map to the latest auction that involved that ad unit. - * adUnitCode when specified, the result will contain only one entry (for this ad unit) or be empty (if this ad - * unit was never involved in an auction). - * when not specified, the result will contain an entry for every ad unit that was involved in any auction. - * @return {{[adUnitCode: string]: string}} - */ -function expandFilters({auctionId, adUnitCode} = {}) { - let adUnitCodes = []; - if (adUnitCode == null) { - adUnitCodes = Object.keys(latestAuctionForAdUnit); - } else if (latestAuctionForAdUnit.hasOwnProperty(adUnitCode)) { - adUnitCodes = [adUnitCode]; - } - return Object.fromEntries( - adUnitCodes.map(au => [au, auctionId ?? latestAuctionForAdUnit[au]]) - ); -} - -/** - * Get PAAPI auction configuration. - * - * @param {Object} [filters] - Filters object - * @param {string} [filters.auctionId] optional auction filter; if omitted, the latest auction for each ad unit is used - * @param {string} [filters.adUnitCode] optional ad unit filter - * @param {boolean} [includeBlanks=false] if true, include null entries for ad units that match the given filters but do not have any available auction configs. - * @returns {Object} a map from ad unit code to auction config for the ad unit. - */ -export function getPAAPIConfig(filters = {}, includeBlanks = false) { - const output = {}; - Object.entries(expandFilters(filters)).forEach(([au, auctionId]) => { - const auctionConfigs = configsForAuction(auctionId); - if (auctionConfigs?.hasOwnProperty(au)) { - // ad unit was involved in a PAAPI auction - const candidate = auctionConfigs[au]; - if (candidate && !USED.has(candidate)) { - output[au] = candidate; - USED.add(candidate); - } else if (includeBlanks) { - output[au] = null; - } - } else if (auctionId == null && includeBlanks) { - // ad unit was involved in a non-PAAPI auction - output[au] = null; - } - }); - return output; -} - -getGlobal().getPAAPIConfig = (filters) => getPAAPIConfig(filters); - -function isFledgeSupported() { - return 'runAdAuction' in navigator && 'joinAdInterestGroup' in navigator; -} - -function getFledgeConfig(bidder) { - const enabled = moduleConfig.enabled && (bidder == null || !moduleConfig.bidders?.length || moduleConfig.bidders?.includes(bidder)); - return { - enabled, - ae: enabled ? moduleConfig.defaultForSlots : undefined - }; -} - -/** - * Given an array of size tuples, return the one that should be used for PAAPI. - */ -export const getPAAPISize = hook('sync', function (sizes) { - sizes = sizes - ?.filter(([w, h]) => !(w === h && w <= 5)); - - if (sizes?.length) { - return sizes - .reduce(maximum(keyCompare(([w, h]) => w * h))); - } -}, 'getPAAPISize'); - -function getRequestedSize(adUnit) { - return adUnit.ortb2Imp?.ext?.paapi?.requestedSize || (() => { - const size = getPAAPISize(sizesToSizeTuples(adUnit.mediaTypes?.banner?.sizes)); - if (size) { - return { - width: size[0], - height: size[1] - }; - } - })(); -} - -export function addPaapiData(next, adUnits, ...args) { - if (isFledgeSupported() && moduleConfig.enabled) { - adUnits.forEach(adUnit => { - // https://github.com/InteractiveAdvertisingBureau/openrtb/blob/main/extensions/community_extensions/Protected%20Audience%20Support.md - const igsAe = adUnit.ortb2Imp?.ext?.igs != null - ? adUnit.ortb2Imp.ext.igs.ae || 1 - : null; - const extAe = adUnit.ortb2Imp?.ext?.ae; - if (igsAe !== extAe && igsAe != null && extAe != null) { - logWarn(MODULE, `Ad unit defines conflicting ortb2Imp.ext.ae and ortb2Imp.ext.igs, using the latter`, adUnit); - } - const ae = igsAe ?? extAe ?? moduleConfig.defaultForSlots; - if (ae) { - deepSetValue(adUnit, 'ortb2Imp.ext.ae', ae); - adUnit.ortb2Imp.ext.igs = Object.assign({ - ae: ae, - biddable: 1 - }, adUnit.ortb2Imp.ext.igs); - const requestedSize = getRequestedSize(adUnit); - if (requestedSize) { - deepSetValue(adUnit, 'ortb2Imp.ext.paapi.requestedSize', requestedSize); - } - adUnit.bids.forEach(bidReq => { - if (!getFledgeConfig(bidReq.bidder).enabled) { - deepSetValue(bidReq, 'ortb2Imp.ext.ae', 0); - bidReq.ortb2Imp.ext.igs = {ae: 0, biddable: 0}; - } - }) - } - }) - } - next(adUnits, ...args); -} - -export const NAVIGATOR_APIS = ['createAuctionNonce', 'getInterestGroupAdAuctionData']; - -export function markForFledge(next, bidderRequests) { - if (isFledgeSupported()) { - bidderRequests.forEach((bidderReq) => { - const {enabled} = getFledgeConfig(bidderReq.bidderCode); - Object.assign(bidderReq, { - paapi: { - enabled, - componentSeller: !!moduleConfig.componentSeller?.auctionConfig - } - }); - if (enabled) { - NAVIGATOR_APIS.forEach(method => { - bidderReq.paapi[method] = (...args) => new AsyncPAAPIParam(() => navigator[method](...args)) - }) - } - }); - } - next(bidderRequests); -} - -export const ASYNC_SIGNALS = [ - 'auctionSignals', - 'sellerSignals', - 'perBuyerSignals', - 'perBuyerTimeouts', - 'directFromSellerSignals', - 'perBuyerCurrencies', - 'perBuyerCumulativeTimeouts', - 'serverResponse' -]; - -const validatePartialConfig = (() => { - const REQUIRED_SYNC_SIGNALS = [ - { - props: ['seller'], - validate: (val) => typeof val === 'string' - }, - { - props: ['interestGroupBuyers'], - validate: (val) => Array.isArray(val) && val.length > 0 - }, - { - props: ['decisionLogicURL', 'decisionLogicUrl'], - validate: (val) => typeof val === 'string' - } - ]; - - return function (config) { - const invalid = REQUIRED_SYNC_SIGNALS.find(({props, validate}) => props.every(prop => !config.hasOwnProperty(prop) || !config[prop] || !validate(config[prop]))); - if (invalid) { - logError(`Partial PAAPI config has missing or invalid property "${invalid.props[0]}"`, config) - return false; - } - return true; - } -})() - -function callAdapterApi(spec, method, bids, bidderRequest) { - const metrics = adapterMetrics(bidderRequest); - const tidGuard = guardTids(bidderRequest); - let result; - metrics.measureTime(method, () => { - try { - result = spec[method](bids.map(tidGuard.bidRequest), tidGuard.bidderRequest(bidderRequest)) - } catch (e) { - logError(`Error invoking "${method}":`, e); - } - }); - return result; -} - -/** - * Adapters can provide a `spec.buildPAAPIConfigs(validBidRequests, bidderRequest)` to be included in PAAPI auctions - * that can be started in parallel with contextual auctions. - * - * If PAAPI is enabled, and an adapter provides `buildPAAPIConfigs`, it is invoked just before `buildRequests`, - * and takes the same arguments. It should return an array of PAAPI configuration objects with the same format - * as in `interpretResponse` (`{bidId, config?, igb?}`). - * - * Everything returned by `buildPAAPIConfigs` is treated in the same way as if it was returned by `interpretResponse` - - * except for signals that can be provided asynchronously (cfr. `ASYNC_SIGNALS`), which are replaced by promises. - * When the (contextual) auction ends, the promises are resolved. - * - * If during the auction the adapter's `interpretResponse` returned matching configurations (same `bidId`, - * and a `config` with the same `seller`, or an `igb` with the same `origin`), the promises resolve to their contents. - * Otherwise, they resolve to the values provided by `buildPAAPIConfigs`, or an empty object if no value was provided. - * - * Promisified auction configs are available from `getPAAPIConfig` immediately after `requestBids`. - * If the `paapi.parallel` config flag is set, PAAPI submodules are also triggered at the same time - * (instead of when the auction ends). - */ -export function parallelPaapiProcessing(next, spec, bids, bidderRequest, ...args) { - function makeDeferrals(defaults = {}) { - const promises = {}; - const deferrals = Object.fromEntries(ASYNC_SIGNALS.map(signal => { - const def = defer({promiseFactory: (resolver) => new Promise(resolver)}); - def.default = defaults.hasOwnProperty(signal) ? defaults[signal] : null; - promises[signal] = def.promise; - return [signal, def] - })) - return [deferrals, promises]; - } - - const {auctionId, paapi: {enabled, componentSeller} = {}} = bidderRequest; - const auctionConfigs = configsForAuction(auctionId); - bids.map(bid => bid.adUnitCode).forEach(adUnitCode => { - latestAuctionForAdUnit[adUnitCode] = auctionId; - if (!auctionConfigs.hasOwnProperty(adUnitCode)) { - auctionConfigs[adUnitCode] = null; - } - }); - - if (enabled && spec.buildPAAPIConfigs) { - const partialConfigs = callAdapterApi(spec, 'buildPAAPIConfigs', bids, bidderRequest) - const requestsById = Object.fromEntries(bids.map(bid => [bid.bidId, bid])); - (partialConfigs ?? []).forEach(({bidId, config, igb}) => { - const bidRequest = requestsById.hasOwnProperty(bidId) && requestsById[bidId]; - if (!bidRequest) { - logError(`Received partial PAAPI config for unknown bidId`, {bidId, config}); - } else { - const adUnitCode = bidRequest.adUnitCode; - latestAuctionForAdUnit[adUnitCode] = auctionId; - const deferredConfigs = deferredConfigsForAuction(auctionId); - - const getDeferredConfig = () => { - if (!deferredConfigs.hasOwnProperty(adUnitCode)) { - const [deferrals, promises] = makeDeferrals(); - auctionConfigs[adUnitCode] = { - ...getStaticSignals(auctionManager.index.getAdUnit(bidRequest)), - ...promises, - componentAuctions: [] - } - deferredConfigs[adUnitCode] = { - top: deferrals, - components: {}, - auctionConfig: auctionConfigs[adUnitCode] - } - } - return deferredConfigs[adUnitCode]; - } - - if (config && validatePartialConfig(config)) { - const configId = getConfigId(bidRequest.bidder, config.seller); - const deferredConfig = getDeferredConfig(); - if (deferredConfig.components.hasOwnProperty(configId)) { - logWarn(`Received multiple PAAPI configs for the same bidder and seller; config will be ignored`, { - config, - bidder: bidRequest.bidder - }) - } else { - const [deferrals, promises] = makeDeferrals(config); - const auctionConfig = { - ...getStaticSignals(bidRequest), - ...config, - ...promises - } - deferredConfig.auctionConfig.componentAuctions.push(auctionConfig) - deferredConfig.components[configId] = {auctionConfig, deferrals}; - } - } - if (componentSeller && igb && checkOrigin(igb)) { - const configId = getComponentSellerConfigId(spec.code); - const deferredConfig = getDeferredConfig(); - const partialConfig = buyersToAuctionConfigs([[bidRequest, igb]])[0][1]; - if (deferredConfig.components.hasOwnProperty(configId)) { - const {auctionConfig, deferrals} = deferredConfig.components[configId]; - if (!auctionConfig.interestGroupBuyers.includes(igb.origin)) { - const immediate = {}; - Object.entries(partialConfig).forEach(([key, value]) => { - if (deferrals.hasOwnProperty(key)) { - mergeDeep(deferrals[key], {default: value}); - } else { - immediate[key] = value; - } - }) - mergeDeep(auctionConfig, immediate); - } else { - logWarn(`Received the same PAAPI buyer multiple times for the same PAAPI auction. Consider setting paapi.componentSeller.separateAuctions: true`, igb) - } - } else { - const [deferrals, promises] = makeDeferrals(partialConfig); - const auctionConfig = { - ...partialConfig, - ...getStaticSignals(bidRequest), - ...promises, - } - deferredConfig.components[configId] = {auctionConfig, deferrals}; - deferredConfig.auctionConfig.componentAuctions.push(auctionConfig); - } - } - } - }) - } - return next.call(this, spec, bids, bidderRequest, ...args); -} - -export class AsyncPAAPIParam { - constructor(resolve) { - this.resolve = resolve; - } -} - -export function buildPAAPIParams(next, spec, bids, bidderRequest, ...args) { - if (bidderRequest.paapi?.enabled && spec.paapiParameters) { - const params = callAdapterApi(spec, 'paapiParameters', bids, bidderRequest); - return PbPromise.all( - Object.entries(params ?? {}).map(([key, value]) => - value instanceof AsyncPAAPIParam - ? value.resolve().then(result => [key, result]) - : Promise.resolve([key, value])) - ).then(resolved => { - bidderRequest.paapi.params = Object.fromEntries(resolved); - }).catch(err => { - logError(`Could not resolve PAAPI parameters`, err); - }).then(() => { - next.call(this, spec, bids, bidderRequest, ...args); - }) - } else { - next.call(this, spec, bids, bidderRequest, ...args); - } -} - -export function onAuctionInit({auctionId}) { - if (moduleConfig.parallel) { - auctionManager.index.getAuction({auctionId}).requestsDone.then(() => { - if (Object.keys(deferredConfigsForAuction(auctionId)).length > 0) { - submodules.forEach(submod => submod.onAuctionConfig?.(auctionId, configsForAuction(auctionId))); - } - }) - } -} - -export function setImpExtAe(imp, bidRequest, context) { - if (!context.bidderRequest.paapi?.enabled) { - delete imp.ext?.ae; - delete imp.ext?.igs; - } -} - -registerOrtbProcessor({type: IMP, name: 'impExtAe', fn: setImpExtAe}); - -export function parseExtIgi(response, ortbResponse, context) { - paapiResponseParser( - (ortbResponse.ext?.igi || []).flatMap(igi => { - return (igi?.igs || []).map(igs => { - if (igs.impid !== igi.impid && igs.impid != null && igi.impid != null) { - logWarn(MODULE, 'ORTB response ext.igi.igs.impid conflicts with parent\'s impid', igi); - } - return { - config: igs.config, - impid: igs.impid ?? igi.impid - } - }).concat((igi?.igb || []).map(igb => ({ - igb, - impid: igi.impid - }))) - }), - response, - context - ) -} - -function paapiResponseParser(configs, response, context) { - configs.forEach((config) => { - const impCtx = context.impContext[config.impid]; - if (!impCtx?.imp?.ext?.ae) { - logWarn(MODULE, 'Received auction configuration for an impression that was not in the request or did not ask for it', config, impCtx?.imp); - } else { - impCtx.paapiConfigs = impCtx.paapiConfigs || []; - impCtx.paapiConfigs.push(config); - } - }); -} - -// to make it easier to share code between the PBS adapter and adapters whose backend is PBS, break up -// fledge response processing in two steps: first aggregate all the auction configs by their imp... - -export function parseExtPrebidFledge(response, ortbResponse, context) { - paapiResponseParser( - (ortbResponse.ext?.prebid?.fledge?.auctionconfigs || []), - response, - context - ) -} - -registerOrtbProcessor({type: RESPONSE, name: 'extPrebidFledge', fn: parseExtPrebidFledge, dialects: [PBS]}); -registerOrtbProcessor({type: RESPONSE, name: 'extIgiIgs', fn: parseExtIgi}); - -// ...then, make them available in the adapter's response. This is the client side version, for which the -// interpretResponse api is {fledgeAuctionConfigs: [{bidId, config}]} - -export function setResponsePaapiConfigs(response, ortbResponse, context) { - const configs = Object.values(context.impContext) - .flatMap((impCtx) => (impCtx.paapiConfigs || []).map(cfg => ({ - bidId: impCtx.bidRequest.bidId, - ...cfg - }))); - if (configs.length > 0) { - response.paapi = configs; - } -} - -registerOrtbProcessor({ - type: RESPONSE, - name: 'paapiConfigs', - priority: -1, - fn: setResponsePaapiConfigs, -}); diff --git a/modules/paapiForGpt.js b/modules/paapiForGpt.js deleted file mode 100644 index 363c83ada03..00000000000 --- a/modules/paapiForGpt.js +++ /dev/null @@ -1,166 +0,0 @@ -/** - * GPT-specific slot configuration logic for PAAPI. - */ -import {getHook, submodule} from '../src/hook.js'; -import {deepAccess, logInfo, logWarn, sizeTupleToSizeString} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {getGlobal} from '../src/prebidGlobal.js'; - -import {keyCompare} from '../src/utils/reducers.js'; -import {getGPTSlotsForAdUnits, targeting} from '../src/targeting.js'; - -const MODULE = 'paapiForGpt'; - -let getPAAPIConfig; - -config.getConfig('paapi', (cfg) => { - if (deepAccess(cfg, 'paapi.gpt.configWithTargeting', true)) { - logInfo(MODULE, 'enabling PAAPI configuration with setTargetingForGPTAsync') - targeting.setTargetingForGPT.before(setTargetingHook); - } else { - targeting.setTargetingForGPT.getHooks({hook: setTargetingHook}).remove(); - } -}); - -export function setTargetingHookFactory(setPaapiConfig = getGlobal().setPAAPIConfigForGPT) { - return function(next, adUnit, customSlotMatching) { - const adUnitCodes = Array.isArray(adUnit) ? adUnit : [adUnit] - adUnitCodes - .map(adUnitCode => adUnitCode == null ? undefined : {adUnitCode}) - .forEach(filters => setPaapiConfig(filters, customSlotMatching)) - next(adUnit, customSlotMatching); - } -} - -export function slotConfigurator() { - const PREVIOUSLY_SET = {}; - return function setComponentAuction(adUnitCode, gptSlots, auctionConfigs, reset = true) { - if (gptSlots.length > 0) { - let previous = PREVIOUSLY_SET[adUnitCode] ?? {}; - let configsBySeller = Object.fromEntries(auctionConfigs.map(cfg => [cfg.seller, cfg])); - const sellers = Object.keys(configsBySeller); - if (reset) { - configsBySeller = Object.assign(previous, configsBySeller); - previous = Object.fromEntries(sellers.map(seller => [seller, null])); - } else { - sellers.forEach(seller => { - previous[seller] = null; - }); - } - Object.keys(previous).length ? PREVIOUSLY_SET[adUnitCode] = previous : delete PREVIOUSLY_SET[adUnitCode]; - const componentAuction = Object.entries(configsBySeller) - .map(([configKey, auctionConfig]) => ({configKey, auctionConfig})); - if (componentAuction.length > 0) { - gptSlots.forEach(gptSlot => { - gptSlot.setConfig({componentAuction}); - logInfo(MODULE, `register component auction configs for: ${adUnitCode}: ${gptSlot.getAdUnitPath()}`, auctionConfigs); - // reference https://developers.google.com/publisher-tag/reference#googletag.config.ComponentAuctionConfig - }); - } - } else if (auctionConfigs.length > 0) { - logWarn(MODULE, `unable to register component auction config for ${adUnitCode}`, auctionConfigs); - } - }; -} - -const setComponentAuction = slotConfigurator(); - -export const getPAAPISizeHook = (() => { - /* - https://github.com/google/ads-privacy/tree/master/proposals/fledge-multiple-seller-testing#faq - https://support.google.com/admanager/answer/1100453?hl=en - - Ignore any placeholder sizes, where placeholder is defined as a square creative with a side of <= 5 pixels - Look if there are any sizes that are part of the set of supported ad sizes defined here. If there are, choose the largest supported size by area (width * height) - For clarity, the set of supported ad sizes includes all of the ad sizes listed under “Top-performing ad sizes”, “Other supported ad sizes”, and “Regional ad sizes”. - If not, choose the largest remaining size (i.e. that isn’t in the list of supported ad sizes) by area (width * height) - */ - const SUPPORTED_SIZES = [ - [728, 90], - [336, 280], - [300, 250], - [300, 50], - [160, 600], - [1024, 768], - [970, 250], - [970, 90], - [768, 1024], - [480, 320], - [468, 60], - [320, 480], - [320, 100], - [320, 50], - [300, 600], - [300, 100], - [250, 250], - [234, 60], - [200, 200], - [180, 150], - [125, 125], - [120, 600], - [120, 240], - [120, 60], - [88, 31], - [980, 120], - [980, 90], - [950, 90], - [930, 180], - [750, 300], - [750, 200], - [750, 100], - [580, 400], - [250, 360], - [240, 400], - ].sort(keyCompare(([w, h]) => -(w * h))) - .map(size => [size, sizeTupleToSizeString(size)]); - - return function(next, sizes) { - if (sizes?.length) { - const sizeStrings = new Set(sizes.map(sizeTupleToSizeString)); - const preferredSize = SUPPORTED_SIZES.find(([_, sizeStr]) => sizeStrings.has(sizeStr)); - if (preferredSize) { - next.bail(preferredSize[0]); - return; - } - } - next(sizes); - } -})(); - -export function setPAAPIConfigFactory( - getConfig = (filters) => getPAAPIConfig(filters, true), - setGptConfig = setComponentAuction, - getSlots = getGPTSlotsForAdUnits) { - /** - * Configure GPT slots with PAAPI auction configs. - * `filters` are the same filters accepted by `pbjs.getPAAPIConfig`; - */ - return function(filters = {}, customSlotMatching) { - let some = false; - const cfg = getConfig(filters) || {}; - const auToSlots = getSlots(Object.keys(cfg), customSlotMatching); - - Object.entries(cfg).forEach(([au, config]) => { - if (config != null) { - some = true; - } - setGptConfig(au, auToSlots[au], config?.componentAuctions || [], true); - }) - if (!some) { - logInfo(`${MODULE}: No component auctions available to set`); - } - } -} -/** - * Configure GPT slots with PAAPI component auctions. Accepts the same filter arguments as `pbjs.getPAAPIConfig`. - */ -getGlobal().setPAAPIConfigForGPT = setPAAPIConfigFactory(); -const setTargetingHook = setTargetingHookFactory(); - -submodule('paapi', { - name: 'gpt', - init(params) { - getPAAPIConfig = params.getPAAPIConfig; - getHook('getPAAPISize').before(getPAAPISizeHook); - } -}); diff --git a/modules/paapiForGpt.md b/modules/paapiForGpt.md deleted file mode 100644 index 8565987eb5b..00000000000 --- a/modules/paapiForGpt.md +++ /dev/null @@ -1,123 +0,0 @@ -# Overview -This module allows Prebid.js to support PAAPI by integrating it with GPT's [experimental PAAPI -support](https://github.com/google/ads-privacy/tree/master/proposals/fledge-multiple-seller-testing). - -To learn more about PAAPI in general, go [here](https://github.com/WICG/turtledove/blob/main/PAAPI.md). - -This document covers the steps necessary for publishers to enable PAAPI on their inventory. It also describes -the changes Bid Adapters need to implement in order to support PAAPI. - -## Publisher Integration -Publishers wishing to enable PAAPI support must do two things. First, they must compile Prebid.js with support for this module. -This is accomplished by adding the `paapiForGpt` module to the list of modules they are already using: - -``` -gulp build --modules=paapiForGpt,... -``` - -Second, they must enable PAAPI in their Prebid.js configuration. -This is done through module level configuration, but to provide a high degree of flexiblity for testing, PAAPI settings also exist the slot level. - -### Module Configuration -This module exposes the following settings: - -|Name |Type |Description |Notes | -| :------------ | :------------ | :------------ |:------------ | -|enabled | Boolean |Enable/disable the module |Defaults to `false` | -|bidders | Array[String] |Optional list of bidders |Defaults to all bidders | -|defaultForSlots | Number |Default value for `imp.ext.ae` in requests for specified bidders |Should be 1 | - -As noted above, PAAPI support is disabled by default. To enable it, set the `enabled` value to `true` for this module and configure `defaultForSlots` to be `1` (meaning _Client-side auction_). -using the `setConfig` method of Prebid.js. Optionally, a list of bidders to apply these settings to may be provided: - -```js -pbjs.que.push(function() { - pbjs.setConfig({ - paapi: { - enabled: true, - bidders: ['openx', 'rtbhouse'], - defaultForSlots: 1 - } - }); -}); -``` - -### AdUnit Configuration -All adunits can be opted-in to PAAPI in the global config via the `defaultForSlots` parameter. -If needed, adunits can be configured individually by setting an attribute of the `ortb2Imp` object for that -adunit. This attribute will take precedence over `defaultForSlots` setting. - -|Name |Type |Description |Notes | -| :------------ | :------------ | :------------ |:------------ | -| ortb2Imp.ext.ae | Integer | Auction Environment: 1 indicates PAAPI eligible, 0 indicates it is not | Absence indicates this is not PAAPI eligible | - -The `ae` field stands for Auction Environment and was chosen to be consistent with the field that GAM passes to bidders -in their Open Bidding and Exchange Bidding APIs. More details on that can be found -[here](https://github.com/google/ads-privacy/tree/master/proposals/fledge-rtb#bid-request-changes-indicating-interest-group-auction-support) -In practice, this looks as follows: - -```js -pbjs.addAdUnits({ - code: "my-adunit-div", - // other config here - ortb2Imp: { - ext: { - ae: 1 - } - } -}); -``` - -## Bid Adapter Integration -Chrome has enabled a two-tier auction in PAAPI. This allows multiple sellers (frequently SSPs) to act on behalf of the publisher with -a single entity serving as the final decision maker. In their [current approach](https://github.com/google/ads-privacy/tree/master/proposals/fledge-multiple-seller-testing), -GPT has opted to run the final auction layer while allowing other SSPs/sellers to participate as -[Component Auctions](https://github.com/WICG/turtledove/blob/main/PAAPI.md#21-initiating-an-on-device-auction) which feed their -bids to the final layer. To learn more about Component Auctions, go [here](https://github.com/WICG/turtledove/blob/main/PAAPI.md#24-scoring-bids-in-component-auctions). - -The PAAPI auction, including Component Auctions, are configured via an `AuctionConfig` object that defines the parameters of the auction for a given -seller. This module enables PAAPI support by allowing bid adaptors to return `AuctionConfig` objects in addition to bids. If a bid adaptor returns an -`AuctionConfig` object, Prebid.js will register it with the appropriate GPT ad slot so the bidder can participate as a Component Auction in the overall -PAAPI auction for that slot. More details on the GPT API can be found [here](https://developers.google.com/publisher-tag/reference#googletag.config.componentauctionconfig). - -Modifying a bid adapter to support PAAPI is a straightforward process and consists of the following steps: -1. Detecting when a bid request is PAAPI eligible -2. Responding with AuctionConfig - -PAAPI eligibility is made available to bid adapters through the `bidderRequest.paapi.enabled` field. -The [`bidderRequest`](https://docs.prebid.org/dev-docs/bidder-adaptor.html#bidderrequest-parameters) object is passed to -the [`buildRequests`](https://docs.prebid.org/dev-docs/bidder-adaptor.html#building-the-request) method of an adapter. Bid adapters -who wish to participate should read this flag and pass it to their server. PAAPI eligibility depends on a number of parameters: - -1. Chrome enablement -2. Publisher participatipon in the [Origin Trial](https://developer.chrome.com/docs/privacy-sandbox/unified-origin-trial/#configure) -3. Publisher Prebid.js configuration (detailed above) - -When a bid request is PAAPI enabled, a bid adapter can return a tuple consisting of bids and AuctionConfig objects rather than just a list of bids: - -```js -function interpretResponse(resp, req) { - // Load the bids from the response - this is adapter specific - const bids = parseBids(resp); - - // Load the auctionConfigs from the response - also adapter specific - const auctionConfigs = parseAuctionConfigs(resp); - - if (auctionConfigs) { - // Return a tuple of bids and auctionConfigs. It is possible that bids could be null. - return {bids, auctionConfigs}; - } else { - return bids; - } -} -``` - -An AuctionConfig must be associated with an adunit and auction, and this is accomplished using the value in the `bidId` field from the objects in the -`validBidRequests` array passed to the `buildRequests` function - see [here](https://docs.prebid.org/dev-docs/bidder-adaptor.html#ad-unit-params-in-the-validbidrequests-array) -for more details. This means that the AuctionConfig objects returned from `interpretResponse` must contain a `bidId` field whose value corresponds to -the request it should be associated with. This may raise the question: why isn't the AuctionConfig object returned as part of the bid? The -answer is that it's possible to participate in the PAAPI auction without returning a contextual bid. - -An example of this can be seen in the OpenX OpenRTB bid adapter [here](https://github.com/prebid/Prebid.js/blob/master/modules/openxOrtbBidAdapter.js#L327). - -Other than the addition of the `bidId` field, the AuctionConfig object should adhere to the requirements set forth in PAAPI. The details of creating an AuctionConfig object are beyond the scope of this document. diff --git a/modules/prebidServerBidAdapter/index.ts b/modules/prebidServerBidAdapter/index.ts index 71abec10cee..e518a16e258 100644 --- a/modules/prebidServerBidAdapter/index.ts +++ b/modules/prebidServerBidAdapter/index.ts @@ -21,7 +21,7 @@ import { import {DEBUG_MODE, EVENTS, REJECTION_REASON, S2S} from '../../src/constants.js'; import adapterManager, {s2sActivityParams} from '../../src/adapterManager.js'; import {config} from '../../src/config.js'; -import {addPaapiConfig, isValid} from '../../src/adapters/bidderFactory.js'; +import {isValid} from '../../src/adapters/bidderFactory.js'; import * as events from '../../src/events.js'; import {ajax} from '../../src/ajax.js'; import {hook} from '../../src/hook.js'; @@ -544,11 +544,6 @@ export function PrebidServer() { addBidResponse.reject(adUnit, bid, REJECTION_REASON.INVALID); } } - }, - onFledge: (params) => { - config.runWithBidder(params.bidder, () => { - addPaapiConfig({auctionId: bidRequests[0].auctionId, ...params}, {config: params.config}); - }) } }) } @@ -577,7 +572,7 @@ type PbsRequestData = { * @param onError {function(String, {})} invoked on HTTP failure - with status message and XHR error * @param onBid {function({})} invoked once for each bid in the response - with the bid as returned by interpretResponse */ -export const processPBSRequest = hook('async', function (s2sBidRequest, bidRequests, ajax, {onResponse, onError, onBid, onFledge}) { +export const processPBSRequest = hook('async', function (s2sBidRequest, bidRequests, ajax, {onResponse, onError, onBid}) { const { gdprConsent } = getConsentData(bidRequests); const adUnits = deepClone(s2sBidRequest.ad_units); @@ -606,11 +601,8 @@ export const processPBSRequest = hook('async', function (s2sBidRequest, bidReque let result; try { result = JSON.parse(response); - const {bids, paapi} = s2sBidRequest.metrics.measureTime('interpretResponse', () => interpretPBSResponse(result, request)); + const {bids} = s2sBidRequest.metrics.measureTime('interpretResponse', () => interpretPBSResponse(result, request)); bids.forEach(onBid); - if (paapi) { - paapi.forEach(onFledge); - } } catch (error) { logError(error); } diff --git a/modules/prebidServerBidAdapter/ortbConverter.js b/modules/prebidServerBidAdapter/ortbConverter.js index ab9e18e6837..4a053849eb6 100644 --- a/modules/prebidServerBidAdapter/ortbConverter.js +++ b/modules/prebidServerBidAdapter/ortbConverter.js @@ -248,23 +248,6 @@ const PBS_CONVERTER = ortbConverter({ // override to process each request context.actualBidderRequests.forEach(req => orig(response, ortbResponse, {...context, bidderRequest: req, bidRequests: req.bids})); }, - paapiConfigs(orig, response, ortbResponse, context) { - const configs = Object.values(context.impContext) - .flatMap((impCtx) => (impCtx.paapiConfigs || []).map(cfg => { - const bidderReq = impCtx.actualBidderRequests.find(br => br.bidderCode === cfg.bidder); - const bidReq = impCtx.actualBidRequests.get(cfg.bidder); - return { - adUnitCode: impCtx.adUnit.code, - ortb2: bidderReq?.ortb2, - ortb2Imp: bidReq?.ortb2Imp, - bidder: cfg.bidder, - config: cfg.config - }; - })); - if (configs.length > 0) { - response.paapi = configs; - } - } } }, }); @@ -317,9 +300,6 @@ export function buildPBSRequest(s2sBidRequest, bidderRequests, adUnits, requeste const proxyBidderRequest = { ...Object.fromEntries(Object.entries(bidderRequests[0]).filter(([k]) => !BIDDER_SPECIFIC_REQUEST_PROPS.has(k))), - paapi: { - enabled: bidderRequests.some(br => br.paapi?.enabled) - } } return PBS_CONVERTER.toORTB({ diff --git a/modules/rtbhouseBidAdapter.md b/modules/rtbhouseBidAdapter.md index 7fcae1299b2..b8b59aa9edc 100644 --- a/modules/rtbhouseBidAdapter.md +++ b/modules/rtbhouseBidAdapter.md @@ -65,46 +65,3 @@ Please reach out to pmp@rtbhouse.com to receive your own } ]; ``` - -# Protected Audience API (FLEDGE) support -There’s an option to receive demand for Protected Audience API (FLEDGE/PAAPI) -ads using RTB House bid adapter. -Prebid’s [paapiForGpt](https://docs.prebid.org/dev-docs/modules/paapiForGpt.html) -module and Google Ad Manager is currently required. - -The following steps should be taken to setup Protected Audience for RTB House: - -1. Reach out to your RTB House representative for setup coordination. - -2. Build and enable FLEDGE module as described in -[paapiForGpt](https://docs.prebid.org/dev-docs/modules/paapiForGpt.html) -module documentation. - - a. Make sure to enable RTB House bidder to participate in FLEDGE. If there are any other bidders to be allowed for that, add them to the **bidders** array: - ```javascript - pbjs.setConfig({ - paapi: { - bidders: ["rtbhouse"], - enabled: true - } - }); - ``` - - b. If you as a publisher have your own [decisionLogicUrl](https://github.com/WICG/turtledove/blob/main/FLEDGE.md#21-initiating-an-on-device-auction) - you may utilize it by setting up a dedicated `fledgeConfig` object: - ```javascript - pbjs.setConfig({ - paapi: { - bidders: ["rtbhouse"], - enabled: true - }, - fledgeConfig: { - seller: 'https://seller.domain', - decisionLogicUrl: 'https://seller.domain/decisionLogicFile.js', - sellerTimeout: 100 - } - }); - ``` - The `decisionLogicUrl` must be in the same domain as `seller` and has to respond with `X-Allow-FLEDGE: true` http header. - - `sellerTimeout` is optional, defaults to 50 as per spec, will be clamped to 500 if greater. diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index a11820b5897..c0bcd4e03c4 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -159,10 +159,6 @@ export const sharethroughAdapterSpec = { const nativeRequest = deepAccess(bidReq, 'mediaTypes.native'); const videoRequest = deepAccess(bidReq, 'mediaTypes.video'); - if (bidderRequest.paapi?.enabled && bidReq.mediaTypes.banner) { - mergeDeep(impression, { ext: { ae: 1 } }); // ae = auction environment; if this is 1, ad server knows we have a fledge auction - } - if (videoRequest) { // default playerSize, only change this if we know width and height are properly defined in the request let [w, h] = [640, 360]; @@ -292,8 +288,6 @@ export const sharethroughAdapterSpec = { return []; } - const fledgeAuctionEnabled = body.ext?.auctionConfigs; - const imp = req.data.imp[0]; const bidsFromExchange = body.seatbid[0].bid.map((bid) => { @@ -340,15 +334,7 @@ export const sharethroughAdapterSpec = { return response; }); - - if (fledgeAuctionEnabled && !isEqtvTest) { - return { - bids: bidsFromExchange, - paapi: body.ext?.auctionConfigs || {}, - }; - } else { - return bidsFromExchange; - } + return bidsFromExchange; }, getUserSyncs: (syncOptions, serverResponses, gdprConsent) => { diff --git a/modules/silverpushBidAdapter.js b/modules/silverpushBidAdapter.js index 46aed11c4ac..9903fd033bb 100644 --- a/modules/silverpushBidAdapter.js +++ b/modules/silverpushBidAdapter.js @@ -117,22 +117,7 @@ export const CONVERTER = ortbConverter({ }, response(buildResponse, bidResponses, ortbResponse, context) { const response = buildResponse(bidResponses, ortbResponse, context); - - let fledgeAuctionConfigs = utils.deepAccess(ortbResponse, 'ext.fledge_auction_configs'); - if (fledgeAuctionConfigs) { - fledgeAuctionConfigs = Object.entries(fledgeAuctionConfigs).map(([bidId, cfg]) => { - return Object.assign({ - bidId, - auctionSignals: {} - }, cfg); - }); - return { - bids: response.bids, - paapi: fledgeAuctionConfigs, - } - } else { - return response.bids - } + return response.bids } }); diff --git a/modules/sspBCBidAdapter.js b/modules/sspBCBidAdapter.js index 5ce8fb34492..3efc17138e2 100644 --- a/modules/sspBCBidAdapter.js +++ b/modules/sspBCBidAdapter.js @@ -1,11 +1,11 @@ -import { deepAccess, getWinDimensions, getWindowTop, isArray, logInfo, logWarn } from '../src/utils.js'; -import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRatio.js'; -import { ajax } from '../src/ajax.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import {deepAccess, getWinDimensions, getWindowTop, isArray, logInfo, logWarn} from '../src/utils.js'; +import {getDevicePixelRatio} from '../libraries/devicePixelRatio/devicePixelRatio.js'; +import {ajax} from '../src/ajax.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; -import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js'; +import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; +import {getCurrencyFromBidderRequest} from '../libraries/ortb2Utils/currency.js'; const BIDDER_CODE = 'sspBC'; const BIDDER_URL = 'https://ssp.wp.pl/bidder/'; @@ -671,8 +671,7 @@ const spec = { interpretResponse(serverResponse, request) { const { bidderRequest } = request; const { body: response = {} } = serverResponse; - const { seatbid: responseSeat, ext: responseExt = {} } = response; - const { paapi: fledgeAuctionConfigs = [] } = responseExt; + const { seatbid: responseSeat } = response; const bids = []; let site = JSON.parse(request.data).site; // get page and referer data from request site.sn = response.sn || 'mc_adapter'; // WPM site name (wp_sn) @@ -788,7 +787,7 @@ const spec = { }); } - return fledgeAuctionConfigs.length ? { bids, fledgeAuctionConfigs } : bids; + return bids; }, getUserSyncs(syncOptions, _, gdprConsent = {}) { diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 421ddbd256b..3b39dd3db03 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -3,7 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; -import {deepSetValue, getWindowSelf, replaceAuctionPrice, isArray, safeJSONParse, isPlainObject, getWinDimensions} from '../src/utils.js'; +import {deepSetValue, getWinDimensions, getWindowSelf, isPlainObject, replaceAuctionPrice} from '../src/utils.js'; import {getStorageManager} from '../src/storageManager.js'; import {ajax} from '../src/ajax.js'; import {ortbConverter} from '../libraries/ortbConverter/converter.js'; @@ -236,58 +236,11 @@ export const spec = { return []; } const bids = []; - const fledgeAuctionConfigs = []; if (!serverResponse.body.seatbid || !serverResponse.body.seatbid.length || !serverResponse.body.seatbid[0].bid || !serverResponse.body.seatbid[0].bid.length) { - if (!serverResponse.body.ext || !serverResponse.body.ext.igbid || !serverResponse.body.ext.igbid.length) { - return []; - } + return []; } else { bids.push(...converter.fromORTB({response: serverResponse.body, request: request.data}).bids); } - if (isArray(serverResponse.body.ext?.igbid)) { - serverResponse.body.ext.igbid.forEach((igbid) => { - if (!igbid || !igbid.igbuyer || !igbid.igbuyer.length || !igbid.igbuyer[0].buyerdata) { - return; - } - const buyerdata = safeJSONParse(igbid.igbuyer[0]?.buyerdata) - if (!buyerdata) { - return; - } - const perBuyerSignals = {}; - igbid.igbuyer.forEach(buyerItem => { - if (!buyerItem || !buyerItem.buyerdata || !buyerItem.origin) { - return; - } - const parsedData = safeJSONParse(buyerItem.buyerdata) - if (!parsedData || !parsedData.perBuyerSignals || !(buyerItem.origin in parsedData.perBuyerSignals)) { - return; - } - perBuyerSignals[buyerItem.origin] = parsedData.perBuyerSignals[buyerItem.origin]; - }); - const impId = igbid?.impid; - fledgeAuctionConfigs.push({ - impId, - config: { - seller: buyerdata?.seller, - resolveToConfig: buyerdata?.resolveToConfig, - sellerSignals: {}, - sellerTimeout: buyerdata?.sellerTimeout, - perBuyerSignals, - auctionSignals: {}, - decisionLogicUrl: buyerdata?.decisionLogicUrl, - interestGroupBuyers: buyerdata?.interestGroupBuyers, - perBuyerTimeouts: buyerdata?.perBuyerTimeouts, - }, - }); - }); - } - - if (fledgeAuctionConfigs.length) { - return { - bids, - paapi: fledgeAuctionConfigs, - }; - } return bids; }, onBidWon: (bid) => { diff --git a/modules/topLevelPaapi.js b/modules/topLevelPaapi.js deleted file mode 100644 index 3fb613ff728..00000000000 --- a/modules/topLevelPaapi.js +++ /dev/null @@ -1,207 +0,0 @@ -import {submodule} from '../src/hook.js'; -import {config} from '../src/config.js'; -import {logError, logInfo, logWarn, mergeDeep} from '../src/utils.js'; -import {auctionStore} from '../libraries/weakStore/weakStore.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import {emit} from '../src/events.js'; -import {BID_STATUS, EVENTS} from '../src/constants.js'; -import {PbPromise} from '../src/utils/promise.js'; -import {getBidToRender, getRenderingData, markWinningBid} from '../src/adRendering.js'; - -let getPAAPIConfig, expandFilters, moduleConfig; - -const paapiBids = auctionStore(); -const MODULE_NAME = 'topLevelPaapi'; - -config.getConfig('paapi', (cfg) => { - moduleConfig = cfg.paapi?.topLevelSeller; - if (moduleConfig) { - getBidToRender.before(renderPaapiHook); - getRenderingData.before(getRenderingDataHook); - markWinningBid.before(markWinningBidHook); - } else { - getBidToRender.getHooks({hook: renderPaapiHook}).remove(); - getRenderingData.getHooks({hook: getRenderingDataHook}).remove(); - markWinningBid.getHooks({hook: markWinningBidHook}).remove(); - } -}); - -function isPaapiBid(bid) { - return bid?.source === 'paapi'; -} - -function bidIfRenderable(bid) { - if (bid && !bid.urn) { - logWarn(MODULE_NAME, 'rendering in fenced frames is not supported. Consider using resolveToConfig: false', bid); - return; - } - return bid; -} - -function renderPaapiHook(next, adId, forRender = true, cb) { - PbPromise - .resolve() - .then(() => { - const ids = parsePaapiAdId(adId); - if (ids) { - const [auctionId, adUnitCode] = ids; - return paapiBids(auctionId)?.[adUnitCode]?.then(bid => { - if (!bid) { - logWarn(MODULE_NAME, `No PAAPI bid found for auctionId: "${auctionId}", adUnit: "${adUnitCode}"`); - } - return bidIfRenderable(bid); - }); - } - }) - .then((bid) => { - if (bid != null) return bid; - return new Promise(resolve => next(adId, forRender, resolve)) - }) - .then((bid) => { - if (bid == null || isPaapiBid(bid) || bid?.status === BID_STATUS.RENDERED) return bid; - return getPAAPIBids({adUnitCode: bid.adUnitCode}).then(res => { - const paapiBid = bidIfRenderable(res[bid.adUnitCode]); - if (paapiBid) { - if (!forRender) return paapiBid; - if (forRender && paapiBid.status !== BID_STATUS.RENDERED) { - paapiBid.overriddenAdId = bid.adId; - logInfo(MODULE_NAME, 'overriding contextual bid with PAAPI bid', bid, paapiBid) - return paapiBid; - } - } - return bid; - }); - }) - .then(cb); -} - -export function getRenderingDataHook(next, bid, options) { - if (isPaapiBid(bid)) { - next.bail({ - width: bid.width, - height: bid.height, - adUrl: bid.urn - }); - } else { - next(bid, options); - } -} - -export function markWinningBidHook(next, bid) { - if (isPaapiBid(bid)) { - emit(EVENTS.BID_WON, bid); - next.bail(); - } else { - next(bid); - } -} - -function getBaseAuctionConfig() { - if (moduleConfig?.auctionConfig) { - return Object.assign({ - resolveToConfig: false - }, moduleConfig.auctionConfig); - } -} - -function onAuctionConfig(auctionId, auctionConfigs) { - const base = getBaseAuctionConfig(); - if (base) { - Object.entries(auctionConfigs).forEach(([adUnitCode, auctionConfig]) => { - mergeDeep(auctionConfig, base); - if (moduleConfig.autorun ?? true) { - getPAAPIBids({adUnitCode, auctionId}); - } - }); - } -} - -export function parsePaapiSize(size) { - /* From https://github.com/WICG/turtledove/blob/main/FLEDGE.md#12-interest-group-attributes: - * Each size has the format {width: widthVal, height: heightVal}, - * where the values can have either pixel units (e.g. 100 or '100px') or screen dimension coordinates (e.g. 100sw or 100sh). - */ - if (typeof size === 'number') return size; - if (typeof size === 'string') { - const px = /^(\d+)(px)?$/.exec(size)?.[1]; - if (px) { - return parseInt(px, 10); - } - } - return null; -} - -export function getPaapiAdId(auctionId, adUnitCode) { - return `paapi:/${auctionId.replace(/:/g, '::')}/:/${adUnitCode.replace(/:/g, '::')}`; -} - -export function parsePaapiAdId(adId) { - const match = /^paapi:\/(.*)\/:\/(.*)$/.exec(adId); - if (match) { - return [match[1], match[2]].map(s => s.replace(/::/g, ':')); - } -} - -/** - * Returns the PAAPI runAdAuction result for the given filters, as a map from ad unit code to auction result - * (an object with `width`, `height`, and one of `urn` or `frameConfig`). - * - * @param filters - * @param raa - * @return {Promise<{[p: string]: any}>} - */ -export function getPAAPIBids(filters, raa = (...args) => navigator.runAdAuction(...args)) { - return Promise.all( - Object.entries(expandFilters(filters)) - .map(([adUnitCode, auctionId]) => { - const bids = paapiBids(auctionId); - if (bids && !bids.hasOwnProperty(adUnitCode)) { - const auctionConfig = getPAAPIConfig({adUnitCode, auctionId})[adUnitCode]; - if (auctionConfig) { - emit(EVENTS.RUN_PAAPI_AUCTION, { - auctionId, - adUnitCode, - auctionConfig - }); - bids[adUnitCode] = new Promise((resolve, reject) => raa(auctionConfig).then(resolve, reject)) - .then(result => { - if (result) { - const bid = { - source: 'paapi', - adId: getPaapiAdId(auctionId, adUnitCode), - width: parsePaapiSize(auctionConfig.requestedSize?.width), - height: parsePaapiSize(auctionConfig.requestedSize?.height), - adUnitCode, - auctionId, - [typeof result === 'string' ? 'urn' : 'frameConfig']: result, - auctionConfig, - }; - emit(EVENTS.PAAPI_BID, bid); - return bid; - } else { - emit(EVENTS.PAAPI_NO_BID, {auctionId, adUnitCode, auctionConfig}); - return null; - } - }).catch(error => { - logError(MODULE_NAME, `error (auction "${auctionId}", adUnit "${adUnitCode}"):`, error); - emit(EVENTS.PAAPI_ERROR, {auctionId, adUnitCode, error, auctionConfig}); - return null; - }); - } - } - return bids?.[adUnitCode]?.then(res => [adUnitCode, res]); - }).filter(e => e) - ).then(result => Object.fromEntries(result)); -} - -getGlobal().getPAAPIBids = (filters) => getPAAPIBids(filters); - -export const topLevelPAAPI = { - name: MODULE_NAME, - init(params) { - getPAAPIConfig = params.getPAAPIConfig; - expandFilters = params.expandFilters; - }, - onAuctionConfig -}; -submodule('paapi', topLevelPAAPI); diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 503edaa8864..f5b5de0097d 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -58,10 +58,6 @@ export const tripleliftAdapterSpec = { tlCall = tryAppendQueryString(tlCall, 'us_privacy', bidderRequest.uspConsent); } - if (bidderRequest?.paapi?.enabled) { - tlCall = tryAppendQueryString(tlCall, 'fledge', bidderRequest.paapi.enabled); - } - if (config.getConfig('coppa') === true) { tlCall = tryAppendQueryString(tlCall, 'coppa', true); } @@ -81,26 +77,8 @@ export const tripleliftAdapterSpec = { interpretResponse: function(serverResponse, {bidderRequest}) { let bids = serverResponse.body.bids || []; - const paapi = serverResponse.body.paapi || []; - - bids = bids.map(bid => _buildResponseObject(bidderRequest, bid)); - if (paapi.length > 0) { - const fledgeAuctionConfigs = paapi.map(config => { - return { - bidId: bidderRequest.bids[config.imp_id].bidId, - config: config.auctionConfig - }; - }); - - logMessage('Response with FLEDGE:', { bids, fledgeAuctionConfigs }); - return { - bids, - paapi: fledgeAuctionConfigs - }; - } else { - return bids; - } + return bids.map(bid => _buildResponseObject(bidderRequest, bid)); }, getUserSyncs: function(syncOptions, responses, gdprConsent, usPrivacy, gppConsent) { diff --git a/src/adRendering.ts b/src/adRendering.ts index 25aba25a59f..c031a8555bd 100644 --- a/src/adRendering.ts +++ b/src/adRendering.ts @@ -56,15 +56,6 @@ declare module './events' { } } -/** - * NOTE: this is here to support PAAPI, which is soon to be removed; - * and should *not* be made asynchronous or it breaks `legacyRender` (unyielding) - * rendering logic - */ -export const getBidToRender = hook('sync', function (adId, forRender, cb) { - cb(auctionManager.findBidByAdId(adId)); -}) - export const markWinningBid = hook('sync', function (bid) { (parseEventTrackers(bid.eventtrackers)[EVENT_TYPE_WIN]?.[TRACKER_METHOD_IMG] || []) .forEach(url => triggerPixel(url)); @@ -399,10 +390,8 @@ export const renderAdDirect = yieldsIf(() => !legacyRender, function renderAdDir if (!adId || !doc) { fail(AD_RENDER_FAILED_REASON.MISSING_DOC_OR_ADID, `missing ${adId ? 'doc' : 'adId'}`); } else { - getBidToRender(adId, true, (bidResponse) => { - bid = bidResponse; - handleRender({renderFn, resizeFn, adId, options: {clickUrl: options?.clickThrough}, bidResponse, doc}); - }); + bid = auctionManager.findBidByAdId(adId) + handleRender({renderFn, resizeFn, adId, options: {clickUrl: options?.clickThrough}, bidResponse: bid, doc}); } } catch (e) { fail(EXCEPTION, e.message); diff --git a/src/adapters/bidderFactory.ts b/src/adapters/bidderFactory.ts index 60f21964f88..1d97253e9e6 100644 --- a/src/adapters/bidderFactory.ts +++ b/src/adapters/bidderFactory.ts @@ -319,14 +319,6 @@ export function newBidder(spec: BidderSpec) { onTimelyResponse(spec.code); responses.push(resp) }, - onPaapi: (paapiConfig: any) => { - const bidRequest = bidRequestMap[paapiConfig.bidId]; - if (bidRequest) { - addPaapiConfig(bidRequest, paapiConfig); - } else { - logWarn('Received fledge auction configuration for an unknown bidId', paapiConfig); - } - }, // If the server responds with an error, there's not much we can do beside logging. onError: (errorMessage, error) => { if (!error.timedOut) { @@ -390,7 +382,12 @@ export function newBidder(spec: BidderSpec) { } } -const RESPONSE_PROPS = ['bids', 'paapi'] +const RESPONSE_PROPS = [ + 'bids', + // allow bid adapters to still reply with paapi (which will be ignored). + 'paapi', +] + /** * Run a set of bid requests - that entails converting them to HTTP requests, sending * them over the network, and parsing the responses. @@ -407,7 +404,7 @@ export const processBidderRequests = hook('async', function, ajax: Ajax, wrapCallback: (fn: T) => Wraps, - {onRequest, onResponse, onPaapi, onError, onBid, onCompletion}: { + {onRequest, onResponse, onError, onBid, onCompletion}: { /** * invoked once for each HTTP request built by the adapter - with the raw request */ @@ -424,10 +421,6 @@ export const processBidderRequests = hook('async', function void; - /** - * invoked once with each member of the adapter response's 'paapi' array. - */ - onPaapi: (paapi: unknown) => void; /** * invoked once when all bid requests have been processed */ @@ -483,16 +476,12 @@ export const processBidderRequests = hook('async', function !RESPONSE_PROPS.includes(key))) { bids = response.bids; - paapiConfigs = response.paapi; } else { bids = response; } - if (isArray(paapiConfigs)) { - paapiConfigs.forEach(onPaapi); - } if (bids) { if (isArray(bids)) { bids.forEach(addBid); @@ -616,9 +605,6 @@ export const registerSyncInner = hook('async', function(spec: BidderSpec { -}, 'addPaapiConfig'); - declare module '../bidfactory' { interface BannerBidProperties { width?: number; diff --git a/src/ajax.ts b/src/ajax.ts index 58ed89b6e83..b745c8e2b4e 100644 --- a/src/ajax.ts +++ b/src/ajax.ts @@ -53,10 +53,6 @@ export interface AjaxOptions { * Whether chrome's `Sec-Browing-Topics` header should be sent */ browsingTopics?: boolean - /** - * Whether chrome's PAAPI headers should be sent. - */ - adAuctionHeaders?: boolean; /** * If true, suppress warnings */ @@ -94,8 +90,8 @@ export function toFetchRequest(url, data, options: AjaxOptions = {}) { rqOpts.credentials = 'include'; } if (isSecureContext) { - ['browsingTopics', 'adAuctionHeaders'].forEach(opt => { - // the Request constructor will throw an exception if the browser supports topics/fledge + ['browsingTopics'].forEach(opt => { + // the Request constructor will throw an exception if the browser supports topics // but we're not in a secure context if (options[opt]) { rqOpts[opt] = true; diff --git a/src/constants.ts b/src/constants.ts index 6380d89f712..c1331d51361 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -43,11 +43,7 @@ export const EVENTS = { EXPIRED_RENDER: 'expiredRender', BILLABLE_EVENT: 'billableEvent', BID_ACCEPTED: 'bidAccepted', - RUN_PAAPI_AUCTION: 'paapiRunAuction', PBS_ANALYTICS: 'pbsAnalytics', - PAAPI_BID: 'paapiBid', - PAAPI_NO_BID: 'paapiNoBid', - PAAPI_ERROR: 'paapiError', BEFORE_PBS_HTTP: 'beforePBSHttp', BROWSI_INIT: 'browsiInit', BROWSI_DATA: 'browsiData', diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 8233c373d1a..a385113e54e 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -8,7 +8,6 @@ import {BID_STATUS, MESSAGES} from './constants.js'; import {isApnGetTagDefined, isGptPubadsDefined, logError, logWarn} from './utils.js'; import { deferRendering, - getBidToRender, handleCreativeEvent, handleNativeMessage, handleRender, @@ -16,6 +15,7 @@ import { } from './adRendering.js'; import {getCreativeRendererSource, PUC_MIN_VERSION} from './creativeRenderers.js'; import {PbPromise} from './utils/promise.js'; +import {auctionManager} from './auctionManager.js'; const { REQUEST, RESPONSE, NATIVE, EVENT } = MESSAGES; @@ -70,10 +70,8 @@ export function receiveMessage(ev, cb) { } if (data && data.adId && data.message && HANDLER_MAP.hasOwnProperty(data.message)) { - return getBidToRender(data.adId, data.message === MESSAGES.REQUEST, (adObject) => { - HANDLER_MAP[data.message](ensureAdId(data.adId, getReplier(ev)), data, adObject); - cb && cb(); - }); + HANDLER_MAP[data.message](ensureAdId(data.adId, getReplier(ev)), data, auctionManager.findBidByAdId(data.adId)); + cb && cb(); } } diff --git a/test/spec/modules/ccxBidAdapter_spec.js b/test/spec/modules/ccxBidAdapter_spec.js index 83865c72907..e512f12415f 100644 --- a/test/spec/modules/ccxBidAdapter_spec.js +++ b/test/spec/modules/ccxBidAdapter_spec.js @@ -495,78 +495,4 @@ describe('ccxAdapter', function () { expect(data.imp).to.deep.have.same.members(imps); }); }); - - describe('FLEDGE', function () { - it('should properly build a request when FLEDGE is enabled', async function () { - const bidderRequest = { - paapi: { - enabled: true - } - }; - const bids = [ - { - adUnitCode: 'banner', - auctionId: '0b9de793-8eda-481e-a548-aaaaaaaaaaa1', - bidId: '2e56e1af51ccc1', - bidder: 'ccx', - bidderRequestId: '17e7b9f58accc1', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - params: { - placementId: 609 - }, - sizes: [[300, 250]], - transactionId: 'befddd38-cfa0-48ab-8bdd-bbbbbbbbbbb1', - ortb2Imp: { - ext: { - ae: 1 - } - } - } - ]; - - const ortbRequest = spec.buildRequests(bids, await addFPDToBidderRequest(bidderRequest)); - const data = JSON.parse(ortbRequest.data); - expect(data.imp[0].ext.ae).to.equal(1); - }); - - it('should properly build a request when FLEDGE is disabled', async function () { - const bidderRequest = { - paapi: { - enabled: false - } - }; - const bids = [ - { - adUnitCode: 'banner', - auctionId: '0b9de793-8eda-481e-a548-aaaaaaaaaaa2', - bidId: '2e56e1af51ccc2', - bidder: 'ccx', - bidderRequestId: '17e7b9f58accc2', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - params: { - placementId: 610 - }, - sizes: [[300, 250]], - transactionId: 'befddd38-cfa0-48ab-8bdd-bbbbbbbbbbb2', - ortb2Imp: { - ext: { - ae: 1 - } - } - } - ]; - - const ortbRequest = spec.buildRequests(bids, await addFPDToBidderRequest(bidderRequest)); - const data = JSON.parse(ortbRequest.data); - expect(data.imp[0].ext.ae).to.be.undefined; - }); - }); }); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index f6f6d31fe72..3b1595f824d 100644 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -1872,70 +1872,6 @@ describe('The Criteo bidding adapter', function () { expect(ortbRequest.imp[0].ext?.rwdd).to.equal(0); }); - it('should properly build a request when FLEDGE is enabled', async function () { - const bidderRequest = { - paapi: { - enabled: true - } - }; - const bidRequests = [ - { - bidder: 'criteo', - adUnitCode: 'bid-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, - params: { - zoneId: 123 - }, - ortb2Imp: { - ext: { - igs: { - ae: 1 - } - } - } - }, - ]; - - const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)).data; - expect(ortbRequest.imp[0].ext.igs.ae).to.equal(1); - }); - - it('should properly build a request when FLEDGE is disabled', async function () { - const bidderRequest = { - paapi: { - enabled: false - }, - }; - const bidRequests = [ - { - bidder: 'criteo', - adUnitCode: 'bid-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, - params: { - zoneId: 123 - }, - ortb2Imp: { - ext: { - igs: { - ae: 1 - } - } - } - }, - ]; - - const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)).data; - expect(ortbRequest.imp[0].ext.igs?.ae).to.be.undefined; - }); - it('should properly transmit the pubid and slot uid if available', async function () { const bidderRequest = { ortb2: { @@ -2462,154 +2398,6 @@ describe('The Criteo bidding adapter', function () { }); } - it('should properly parse a bid response with FLEDGE auction configs', async function () { - const auctionConfig1 = { - auctionSignals: {}, - decisionLogicUrl: 'https://grid-mercury.criteo.com/fledge/decision', - interestGroupBuyers: ['https://first-buyer-domain.com', 'https://second-buyer-domain.com'], - perBuyerSignals: { - 'https://first-buyer-domain.com': { - foo: 'bar', - }, - 'https://second-buyer-domain.com': { - foo: 'baz' - }, - }, - perBuyerTimeout: { - '*': 500, - 'buyer1': 100, - 'buyer2': 200 - }, - perBuyerGroupLimits: { - '*': 60, - 'buyer1': 300, - 'buyer2': 400 - }, - seller: 'https://seller-domain.com', - sellerTimeout: 500, - sellerSignals: { - foo: 'bar', - foo2: 'bar2', - floor: 1, - currency: 'USD', - perBuyerTimeout: { - 'buyer1': 100, - 'buyer2': 200 - }, - perBuyerGroupLimits: { - 'buyer1': 300, - 'buyer2': 400 - }, - }, - sellerCurrency: 'USD', - }; - const auctionConfig2 = { - auctionSignals: {}, - decisionLogicUrl: 'https://grid-mercury.criteo.com/fledge/decision', - interestGroupBuyers: ['https://first-buyer-domain.com', 'https://second-buyer-domain.com'], - perBuyerSignals: { - 'https://first-buyer-domain.com': { - foo: 'bar', - }, - 'https://second-buyer-domain.com': { - foo: 'baz' - }, - }, - perBuyerTimeout: { - '*': 500, - 'buyer1': 100, - 'buyer2': 200 - }, - perBuyerGroupLimits: { - '*': 60, - 'buyer1': 300, - 'buyer2': 400 - }, - seller: 'https://seller-domain.com', - sellerTimeout: 500, - sellerSignals: { - foo: 'bar', - floor: 1, - perBuyerTimeout: { - 'buyer1': 100, - 'buyer2': 200 - }, - perBuyerGroupLimits: { - 'buyer1': 300, - 'buyer2': 400 - }, - }, - sellerCurrency: '???' - }; - const bidRequests = [ - { - bidId: 'test-bidId', - bidder: 'criteo', - adUnitCode: 'bid-123', - transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, - params: { - bidFloor: 1, - bidFloorCur: 'EUR' - } - }, - { - bidId: 'test-bidId-2', - bidder: 'criteo', - adUnitCode: 'bid-123', - transactionId: 'transaction-123', - mediaTypes: { - banner: { - sizes: [[728, 90]] - } - }, - params: { - bidFloor: 1, - bidFloorCur: 'EUR' - } - }, - ]; - const response = { - ext: { - igi: [{ - impid: 'test-bidId', - igs: [{ - impid: 'test-bidId', - bidId: 'test-bidId', - config: auctionConfig1 - }] - }, { - impid: 'test-bidId-2', - igs: [{ - impid: 'test-bidId-2', - bidId: 'test-bidId-2', - config: auctionConfig2 - }] - }] - }, - }; - const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); - const interpretedResponse = spec.interpretResponse({body: response}, request); - expect(interpretedResponse).to.have.property('bids'); - expect(interpretedResponse).to.have.property('paapi'); - expect(interpretedResponse.bids).to.have.lengthOf(0); - expect(interpretedResponse.paapi).to.have.lengthOf(2); - expect(interpretedResponse.paapi[0]).to.deep.equal({ - bidId: 'test-bidId', - impid: 'test-bidId', - config: auctionConfig1, - }); - expect(interpretedResponse.paapi[1]).to.deep.equal({ - bidId: 'test-bidId-2', - impid: 'test-bidId-2', - config: auctionConfig2, - }); - }); - [{ hasBidResponseLevelPafData: true, hasBidResponseBidLevelPafData: true, diff --git a/test/spec/modules/debugging_mod_spec.js b/test/spec/modules/debugging_mod_spec.js index 4989eb7c2e3..488543de582 100644 --- a/test/spec/modules/debugging_mod_spec.js +++ b/test/spec/modules/debugging_mod_spec.js @@ -111,8 +111,8 @@ describe('bid interceptor', () => { }); describe('rule', () => { - function matchingRule({replace, options, paapi}) { - setRules({when: {}, then: replace, options: options, paapi}); + function matchingRule({replace, options}) { + setRules({when: {}, then: replace, options: options}); return interceptor.match({}); } @@ -172,48 +172,6 @@ describe('bid interceptor', () => { }); }); - describe('paapi', () => { - it('should accept literals', () => { - const mockConfig = [ - {config: {paapi: 1}}, - {config: {paapi: 2}} - ] - const paapi = matchingRule({paapi: mockConfig}).paapi({}); - expect(paapi).to.eql(mockConfig); - }); - - it('should accept a function and pass extra args to it', () => { - const paapiDef = sinon.stub(); - const args = [{}, {}, {}]; - matchingRule({paapi: paapiDef}).paapi(...args); - expect(paapiDef.calledOnceWith(...args.map(sinon.match.same))).to.be.true; - }); - - Object.entries({ - 'literal': (cfg) => [cfg], - 'function': (cfg) => () => [cfg] - }).forEach(([t, makeConfigs]) => { - describe(`when paapi is defined as a ${t}`, () => { - it('should wrap top-level configs in "config"', () => { - const cfg = {decisionLogicURL: 'example'}; - expect(matchingRule({paapi: makeConfigs(cfg)}).paapi({})).to.eql([{ - config: cfg - }]) - }); - - Object.entries({ - 'config': {config: 1}, - 'igb': {igb: 1}, - 'config and igb': {config: 1, igb: 2} - }).forEach(([t, cfg]) => { - it(`should not wrap configs that define top-level ${t}`, () => { - expect(matchingRule({paapi: makeConfigs(cfg)}).paapi({})).to.eql([cfg]); - }) - }) - }) - }) - }) - describe('.options', () => { it('should include default rule options', () => { const optDef = {someOption: 'value'}; @@ -231,17 +189,16 @@ describe('bid interceptor', () => { }); describe('intercept()', () => { - let done, addBid, addPaapiConfig; + let done, addBid; function intercept(args = {}) { const bidRequest = {bids: args.bids || []}; - return interceptor.intercept(Object.assign({bidRequest, done, addBid, addPaapiConfig}, args)); + return interceptor.intercept(Object.assign({bidRequest, done, addBid}, args)); } beforeEach(() => { done = sinon.spy(); addBid = sinon.spy(); - addPaapiConfig = sinon.spy(); }); describe('on no match', () => { @@ -304,20 +261,6 @@ describe('bid interceptor', () => { }); }); - it('should call addPaapiConfigs when provided', () => { - const mockPaapiConfigs = [ - {config: {paapi: 1}}, - {config: {paapi: 2}} - ] - setRules({ - when: {id: 2}, - paapi: mockPaapiConfigs, - }); - intercept({bidRequest: REQUEST}); - expect(addPaapiConfig.callCount).to.eql(2); - mockPaapiConfigs.forEach(cfg => sinon.assert.calledWith(addPaapiConfig, cfg)) - }) - it('should not call onBid when then is null', () => { setRules({ when: {id: 2}, @@ -357,7 +300,7 @@ describe('Debugging config', () => { }); describe('bidderBidInterceptor', () => { - let next, interceptBids, onCompletion, interceptResult, done, addBid, wrapCallback, addPaapiConfig, wrapped, bidderBidInterceptor; + let next, interceptBids, onCompletion, interceptResult, done, addBid, wrapCallback, wrapped, bidderBidInterceptor; function interceptorArgs({spec = {}, bids = [], bidRequest = {}, ajax = {}, cbs = {}} = {}) { return [next, interceptBids, spec, bids, bidRequest, ajax, wrapCallback, Object.assign({onCompletion}, cbs)]; @@ -381,7 +324,6 @@ describe('bidderBidInterceptor', () => { interceptBids = sinon.stub().callsFake((opts) => { done = opts.done; addBid = opts.addBid; - addPaapiConfig = opts.addPaapiConfig; return interceptResult; }); onCompletion = sinon.spy(); @@ -400,15 +342,6 @@ describe('bidderBidInterceptor', () => { expect(onBid.calledWith(sinon.match.same(bid))).to.be.true; }); - it('should pass addPaapiConfig that triggers onPaapi', () => { - const onPaapi = sinon.stub().callsFake(() => { - expect(wrapped).to.be.true; - }); - bidderBidInterceptor(...interceptorArgs({cbs: {onPaapi}})); - addPaapiConfig({paapi: 'config'}, {bidId: 'bidId'}); - sinon.assert.calledWith(onPaapi, {paapi: 'config', bidId: 'bidId'}) - }) - describe('with no remaining bids', () => { it('should pass a done callback that triggers onCompletion', () => { bidderBidInterceptor(...interceptorArgs()); diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 1ceaf4f2646..95b4228e95a 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -332,24 +332,6 @@ describe('gumgumAdapter', function () { expect(bidRequest.data).to.have.property('gpid'); expect(bidRequest.data.gpid).to.equal('/17037559/jeusol/jeusol_D_1'); }); - it('should set ae value to 1 for PAAPI', function () { - const req = { ...bidRequests[0], - ortb2Imp: { - ext: { - ae: 1, - data: { - adserver: { - name: 'test', - adslot: 123456 - } - } - } - } } - const bidRequest = spec.buildRequests([req])[0]; - expect(bidRequest.data).to.have.property('ae'); - expect(bidRequest.data.ae).to.equal(true); - }); - it('should set the global placement id (gpid) if in gpid property', function () { const gpid = 'abc123' const req = { ...bidRequests[0], ortb2Imp: { ext: { data: {}, gpid } } } diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index eb352fa4ebe..1a5bd0f1c01 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -884,52 +884,6 @@ describe('IndexexchangeAdapter', function () { } }; - const DEFAULT_OPTION_FLEDGE_ENABLED_GLOBALLY = { - gdprConsent: { - gdprApplies: true, - consentString: '3huaa11=qu3198ae', - vendorData: {} - }, - refererInfo: { - page: 'https://www.prebid.org', - canonicalUrl: 'https://www.prebid.org/the/link/to/the/page' - }, - ortb2: { - site: { - page: 'https://www.prebid.org' - }, - source: { - tid: 'mock-tid' - } - }, - paapi: { - enabled: true - }, - }; - - const DEFAULT_OPTION_FLEDGE_ENABLED = { - gdprConsent: { - gdprApplies: true, - consentString: '3huaa11=qu3198ae', - vendorData: {} - }, - refererInfo: { - page: 'https://www.prebid.org', - canonicalUrl: 'https://www.prebid.org/the/link/to/the/page' - }, - ortb2: { - site: { - page: 'https://www.prebid.org' - }, - source: { - tid: 'mock-tid' - } - }, - paapi: { - enabled: true - } - }; - const DEFAULT_IDENTITY_RESPONSE = { IdentityIp: { responsePending: false, @@ -1055,10 +1009,8 @@ describe('IndexexchangeAdapter', function () { id: `uid_id_${i}`, }] }; - eids.push(newEid); } - return eids; } @@ -3629,78 +3581,6 @@ describe('IndexexchangeAdapter', function () { }); }); - describe('buildRequestFledge', function () { - it('impression should have ae=1 in ext when fledge module is enabled and ae is set in ad unit', function () { - const bidderRequest = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED); - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED[0]); - const requestBidFloor = spec.buildRequests([bid], bidderRequest)[0]; - const impression = extractPayload(requestBidFloor).imp[0]; - - expect(impression.ext.ae).to.equal(1); - }); - - it('impression should have ae=1 in ext when request has paapi.enabled = true and ext.ae = 1', function () { - const bidderRequest = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED); - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED[0]); - const requestBidFloor = spec.buildRequests([bid], bidderRequest)[0]; - const impression = extractPayload(requestBidFloor).imp[0]; - - expect(impression.ext.ae).to.equal(1); - }); - - it('impression should not have ae=1 in ext when fledge module is enabled globally through setConfig but overidden at ad unit level', function () { - const bidderRequest = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED); - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); - const requestBidFloor = spec.buildRequests([bid], bidderRequest)[0]; - const impression = extractPayload(requestBidFloor).imp[0]; - - expect(impression.ext.ae).to.be.undefined; - }); - - it('impression should not have ae=1 in ext when fledge module is disabled', function () { - const bidderRequest = deepClone(DEFAULT_OPTION); - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); - const requestBidFloor = spec.buildRequests([bid], bidderRequest)[0]; - const impression = extractPayload(requestBidFloor).imp[0]; - - expect(impression.ext.ae).to.be.undefined; - }); - - it('should contain correct IXdiag ae property for Fledge', function () { - const bid = DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED[0]; - const bidderRequestWithFledgeEnabled = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED); - const request = spec.buildRequests([bid], bidderRequestWithFledgeEnabled); - const diagObj = extractPayload(request[0]).ext.ixdiag; - expect(diagObj.ae).to.equal(true); - }); - - it('should log warning for non integer auction environment in ad unit for fledge', () => { - const logWarnSpy = sinon.spy(utils, 'logWarn'); - const bid = DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED[0]; - bid.ortb2Imp.ext.ae = 'malformed' - const bidderRequestWithFledgeEnabled = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED); - spec.buildRequests([bid], bidderRequestWithFledgeEnabled); - expect(logWarnSpy.calledWith('error setting auction environment flag - must be an integer')).to.be.true; - logWarnSpy.restore(); - }); - - it('impression should have paapi extension when passed', function () { - const bidderRequest = deepClone(DEFAULT_OPTION_FLEDGE_ENABLED); - const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED[0]); - bid.ortb2Imp.ext.ae = 1 - bid.ortb2Imp.ext.paapi = { - requestedSize: { - width: 300, - height: 250 - } - } - const requestBidFloor = spec.buildRequests([bid], bidderRequest)[0]; - const impression = extractPayload(requestBidFloor).imp[0]; - expect(impression.ext.paapi.requestedSize.width).to.equal(300); - expect(impression.ext.paapi.requestedSize.height).to.equal(250); - }); - }); - describe('integration through exchangeId and externalId', function () { const expectedExchangeId = 123456; // create banner bids with externalId but no siteId as bidder param @@ -4346,106 +4226,6 @@ describe('IndexexchangeAdapter', function () { expect(result[0]).to.deep.equal(expectedParse[0]); }); - describe('Auction config response', function () { - let bidderRequestWithFledgeEnabled; - let serverResponseWithoutFledgeConfigs; - let serverResponseWithFledgeConfigs; - let serverResponseWithMalformedAuctionConfig; - let serverResponseWithMalformedAuctionConfigs; - - beforeEach(() => { - bidderRequestWithFledgeEnabled = spec.buildRequests(DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED, {})[0]; - bidderRequestWithFledgeEnabled.paapi = {enabled: true}; - - serverResponseWithoutFledgeConfigs = { - body: { - ...DEFAULT_BANNER_BID_RESPONSE - } - }; - - serverResponseWithFledgeConfigs = { - body: { - ...DEFAULT_BANNER_BID_RESPONSE, - ext: { - protectedAudienceAuctionConfigs: [ - { - bidId: '59f219e54dc2fc', - config: { - seller: 'https://seller.test.indexexchange.com', - decisionLogicUrl: 'https://seller.test.indexexchange.com/decision-logic.js', - interestGroupBuyers: ['https://buyer.test.indexexchange.com'], - sellerSignals: { - callbackURL: 'https://test.com/ig/v1/ck74j8bcvc9c73a8eg6g' - }, - perBuyerSignals: { - 'https://buyer.test.indexexchange.com': {} - } - } - } - ] - } - } - }; - - serverResponseWithMalformedAuctionConfig = { - body: { - ...DEFAULT_BANNER_BID_RESPONSE, - ext: { - protectedAudienceAuctionConfigs: ['malformed'] - } - } - }; - - serverResponseWithMalformedAuctionConfigs = { - body: { - ...DEFAULT_BANNER_BID_RESPONSE, - ext: { - protectedAudienceAuctionConfigs: 'malformed' - } - } - }; - }); - - it('should correctly interpret response with auction configs', () => { - const result = spec.interpretResponse(serverResponseWithFledgeConfigs, bidderRequestWithFledgeEnabled); - const expectedOutput = [ - { - bidId: '59f219e54dc2fc', - config: { - ...serverResponseWithFledgeConfigs.body.ext.protectedAudienceAuctionConfigs[0].config, - perBuyerSignals: { - 'https://buyer.test.indexexchange.com': {} - } - } - } - ]; - expect(result.paapi).to.deep.equal(expectedOutput); - }); - - it('should correctly interpret response without auction configs', () => { - const result = spec.interpretResponse(serverResponseWithoutFledgeConfigs, bidderRequestWithFledgeEnabled); - expect(result.paapi).to.be.undefined; - }); - - it('should handle malformed auction configs gracefully', () => { - const result = spec.interpretResponse(serverResponseWithMalformedAuctionConfig, bidderRequestWithFledgeEnabled); - expect(result.paapi).to.be.empty; - }); - - it('should log warning for malformed auction configs', () => { - const logWarnSpy = sinon.spy(utils, 'logWarn'); - spec.interpretResponse(serverResponseWithMalformedAuctionConfig, bidderRequestWithFledgeEnabled); - expect(logWarnSpy.calledWith('Malformed auction config detected:', 'malformed')).to.be.true; - logWarnSpy.restore(); - }); - - it('should return bids when protected audience auction conigs is malformed', () => { - const result = spec.interpretResponse(serverResponseWithMalformedAuctionConfigs, bidderRequestWithFledgeEnabled); - expect(result.paapi).to.be.undefined; - expect(result.length).to.be.greaterThan(0); - }); - }); - describe('interpretResponse when server response is empty', function() { let serverResponseWithoutBody; let serverResponseWithoutSeatbid; @@ -4480,7 +4260,6 @@ describe('IndexexchangeAdapter', function () { }); }); }); - describe('bidrequest consent', function () { it('should have consent info if gdprApplies and consentString exist', function () { const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_OPTION); diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index c376b444246..7a5587cbf36 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -1900,55 +1900,6 @@ describe('kargo adapter tests', function() { advertiserDomains: [ 'https://foo.com', 'https://bar.com' ] }); }); - - it('should return paapi if provided in bid response', function () { - const auctionConfig = { - seller: 'https://kargo.com', - decisionLogicUrl: 'https://kargo.com/decision_logic.js', - interestGroupBuyers: ['https://some_buyer.com'], - perBuyerSignals: { - 'https://some_buyer.com': { a: 1 } - } - } - - const body = response.body; - for (const key in body) { - if (body.hasOwnProperty(key)) { - if (key % 2 !== 0) { // Add auctionConfig to every other object - body[key].auctionConfig = auctionConfig; - } - } - } - - const result = spec.interpretResponse(response, bidderRequest); - - // Test properties of bidResponses - result.bids.forEach(bid => { - expect(bid).to.have.property('requestId'); - expect(bid).to.have.property('cpm'); - expect(bid).to.have.property('width'); - expect(bid).to.have.property('height'); - expect(bid).to.have.property('ttl'); - expect(bid).to.have.property('creativeId'); - expect(bid.netRevenue).to.be.true; - expect(bid).to.have.property('meta').that.is.an('object'); - }); - - // Test properties of paapi - expect(result.paapi).to.have.lengthOf(3); - - const expectedBidIds = ['1', '3', '5']; // Expected bidIDs - result.paapi.forEach(config => { - expect(config).to.have.property('bidId'); - expect(expectedBidIds).to.include(config.bidId); - - expect(config).to.have.property('config').that.is.an('object'); - expect(config.config).to.have.property('seller', 'https://kargo.com'); - expect(config.config).to.have.property('decisionLogicUrl', 'https://kargo.com/decision_logic.js'); - expect(config.config.interestGroupBuyers).to.be.an('array').that.includes('https://some_buyer.com'); - expect(config.config.perBuyerSignals).to.have.property('https://some_buyer.com').that.deep.equals({ a: 1 }); - }); - }); }); describe('getUserSyncs', function() { diff --git a/test/spec/modules/logicadBidAdapter_spec.js b/test/spec/modules/logicadBidAdapter_spec.js index 24cc1faae62..715c4007fd6 100644 --- a/test/spec/modules/logicadBidAdapter_spec.js +++ b/test/spec/modules/logicadBidAdapter_spec.js @@ -36,11 +36,6 @@ describe('LogicadAdapter', function () { } }] }], - ortb2Imp: { - ext: { - ae: 1 - } - }, ortb2: { device: { sua: { @@ -197,9 +192,6 @@ describe('LogicadAdapter', function () { stack: [] }, auctionStart: 1563337198010, - paapi: { - enabled: true - } }; const serverResponse = { body: { @@ -227,48 +219,6 @@ describe('LogicadAdapter', function () { } }; - const paapiServerResponse = { - body: { - seatbid: - [{ - bid: { - requestId: '51ef8751f9aead', - cpm: 101.0234, - width: 300, - height: 250, - creativeId: '2019', - currency: 'JPY', - netRevenue: true, - ttl: 60, - ad: '
TEST
', - meta: { - advertiserDomains: ['logicad.com'] - } - } - }], - ext: { - fledgeAuctionConfigs: [{ - bidId: '51ef8751f9aead', - config: { - seller: 'https://fledge.ladsp.com', - decisionLogicUrl: 'https://fledge.ladsp.com/decision_logic.js', - interestGroupBuyers: ['https://fledge.ladsp.com'], - requestedSize: {width: '300', height: '250'}, - allSlotsRequestedSizes: [{width: '300', height: '250'}], - sellerSignals: {signal: 'signal'}, - sellerTimeout: '500', - perBuyerSignals: {'https://fledge.ladsp.com': {signal: 'signal'}}, - perBuyerCurrencies: {'https://fledge.ladsp.com': 'USD'} - } - }] - }, - userSync: { - type: 'image', - url: 'https://cr-p31.ladsp.jp/cookiesender/31' - } - } - }; - const nativeServerResponse = { body: { seatbid: @@ -339,10 +289,6 @@ describe('LogicadAdapter', function () { const data = JSON.parse(request.data); expect(data.auctionId).to.equal('18fd8b8b0bd757'); - // Protected Audience API flag - expect(data.bids[0]).to.have.property('ae'); - expect(data.bids[0].ae).to.equal(1); - expect(data.eids[0].source).to.equal('sharedid.org'); expect(data.eids[0].uids[0].id).to.equal('fakesharedid'); @@ -407,13 +353,6 @@ describe('LogicadAdapter', function () { expect(interpretedResponse[0].ttl).to.equal(serverResponse.body.seatbid[0].bid.ttl); expect(interpretedResponse[0].meta.advertiserDomains).to.equal(serverResponse.body.seatbid[0].bid.meta.advertiserDomains); - // Protected Audience API - const paapiRequest = spec.buildRequests(bidRequests, bidderRequest)[0]; - const paapiInterpretedResponse = spec.interpretResponse(paapiServerResponse, paapiRequest); - expect(paapiInterpretedResponse).to.have.property('bids'); - expect(paapiInterpretedResponse).to.have.property('paapi'); - expect(paapiInterpretedResponse.paapi[0]).to.deep.equal(paapiServerResponse.body.ext.fledgeAuctionConfigs[0]); - // native const nativeRequest = spec.buildRequests(nativeBidRequests, bidderRequest)[0]; const interpretedResponseForNative = spec.interpretResponse(nativeServerResponse, nativeRequest); diff --git a/test/spec/modules/luceadBidAdapter_spec.js b/test/spec/modules/luceadBidAdapter_spec.js index 464a467e9b2..91e50f9452d 100755 --- a/test/spec/modules/luceadBidAdapter_spec.js +++ b/test/spec/modules/luceadBidAdapter_spec.js @@ -2,7 +2,6 @@ import { expect } from 'chai'; import { spec } from 'modules/luceadBidAdapter.js'; import sinon from 'sinon'; import { newBidder } from 'src/adapters/bidderFactory.js'; -import {deepClone} from 'src/utils.js'; import * as ajax from 'src/ajax.js'; describe('Lucead Adapter', () => { @@ -172,12 +171,5 @@ describe('Lucead Adapter', () => { const result = spec.interpretResponse(serverResponse, bidRequest); expect(Object.keys(result.bids[0].meta)).to.include.members(['advertiserDomains']); }); - - it('should support enable_pa = false', function () { - serverResponse.body.enable_pa = false; - const result = spec.interpretResponse(serverResponse, bidRequest); - expect(result).to.be.an('array'); - expect(result[0].cpm).to.be.greaterThan(0); - }); }); }); diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index c3c14f3d0bb..728c68c20b1 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -2066,19 +2066,6 @@ describe('Media.net bid adapter', function () { expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_WITH_USERIDASEIDS); }); - it('should have valid payload when PAAPI is enabled', function () { - const bidReq = spec.buildRequests(VALID_BID_REQUEST_WITH_AE_IN_ORTB2IMP, {...VALID_AUCTIONDATA, paapi: {enabled: true}}); - expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_PAAPI); - }); - - it('should send whatever is set in ortb2imp.ext.ae in all bid requests when PAAPI is enabled', function () { - const bidReq = spec.buildRequests(VALID_BID_REQUEST_WITH_AE_IN_ORTB2IMP, {...VALID_AUCTIONDATA, paapi: {enabled: true}}); - const data = JSON.parse(bidReq.data); - expect(data).to.deep.equal(VALID_PAYLOAD_PAAPI); - expect(data.imp[0].ext).to.have.property('ae'); - expect(data.imp[0].ext.ae).to.equal(1); - }); - describe('build requests: when page meta-data is available', () => { beforeEach(() => { spec.clearPageMeta(); @@ -2254,32 +2241,6 @@ describe('Media.net bid adapter', function () { const bids = spec.interpretResponse(SERVER_RESPONSE_EMPTY_BIDLIST, []); expect(bids).to.deep.equal(validBids); }); - - it('should return paapi if PAAPI response is received', function() { - const response = spec.interpretResponse(SERVER_RESPONSE_PAAPI, []); - expect(response).to.have.property('bids'); - expect(response).to.have.property('paapi'); - expect(response.paapi[0]).to.deep.equal(SERVER_RESPONSE_PAAPI.body.ext.paApiAuctionConfigs[0]); - }); - - it('should return paapi if openRTB PAAPI response received', function () { - const response = spec.interpretResponse(SERVER_RESPONSE_PAAPI_ORTB, []); - expect(response).to.have.property('bids'); - expect(response).to.have.property('paapi'); - expect(response.paapi[0]).to.deep.equal(SERVER_RESPONSE_PAAPI_ORTB.body.ext.igi[0].igs[0]) - }); - - it('should have the correlation between paapi[0].bidId and bidreq.imp[0].id', function() { - const bidReq = spec.buildRequests(VALID_BID_REQUEST_WITH_AE_IN_ORTB2IMP, {...VALID_AUCTIONDATA, paapi: {enabled: true}}); - const bidRes = spec.interpretResponse(SERVER_RESPONSE_PAAPI, []); - expect(bidRes.paapi[0].bidId).to.equal(JSON.parse(bidReq.data).imp[0].id) - }); - - it('should have the correlation between paapi[0].bidId and bidreq.imp[0].id for openRTB response', function() { - const bidReq = spec.buildRequests(VALID_BID_REQUEST_WITH_AE_IN_ORTB2IMP, {...VALID_AUCTIONDATA, paapi: {enabled: true}}); - const bidRes = spec.interpretResponse(SERVER_RESPONSE_PAAPI_ORTB, []); - expect(bidRes.paapi[0].bidId).to.equal(JSON.parse(bidReq.data).imp[0].id) - }); }); describe('onTimeout', function () { diff --git a/test/spec/modules/onetagBidAdapter_spec.js b/test/spec/modules/onetagBidAdapter_spec.js index dd37a929b45..cda513fb1c2 100644 --- a/test/spec/modules/onetagBidAdapter_spec.js +++ b/test/spec/modules/onetagBidAdapter_spec.js @@ -768,38 +768,6 @@ describe('onetag', function () { expect(payload.ortb2).to.exist; expect(payload.ortb2).to.exist.and.to.deep.equal(dsa); }); - it('Should send FLEDGE eligibility flag when FLEDGE is enabled', function () { - const bidderRequest = { - 'bidderCode': 'onetag', - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000, - 'paapi': { - 'enabled': true - } - }; - const serverRequest = spec.buildRequests([bannerBid], bidderRequest); - const payload = JSON.parse(serverRequest.data); - - expect(payload.fledgeEnabled).to.exist; - expect(payload.fledgeEnabled).to.exist.and.to.equal(bidderRequest.paapi.enabled); - }); - it('Should send FLEDGE eligibility flag when FLEDGE is not enabled', function () { - const bidderRequest = { - 'bidderCode': 'onetag', - 'auctionId': '1d1a030790a475', - 'bidderRequestId': '22edbae2733bf6', - 'timeout': 3000, - paapi: { - enabled: false - } - }; - const serverRequest = spec.buildRequests([bannerBid], bidderRequest); - const payload = JSON.parse(serverRequest.data); - - expect(payload.fledgeEnabled).to.exist; - expect(payload.fledgeEnabled).to.exist.and.to.equal(bidderRequest.paapi.enabled); - }); it('Should send FLEDGE eligibility flag set to false when fledgeEnabled is not defined', function () { const bidderRequest = { 'bidderCode': 'onetag', @@ -821,13 +789,7 @@ describe('onetag', function () { const requestData = JSON.parse(request.data); it('Returns an array of valid server responses if response object is valid', function () { const interpretedResponse = spec.interpretResponse(response, request); - const fledgeInterpretedResponse = spec.interpretResponse(fledgeResponse, request); expect(interpretedResponse).to.be.an('array').that.is.not.empty; - expect(fledgeInterpretedResponse).to.be.an('object'); - expect(fledgeInterpretedResponse.bids).to.satisfy(function (value) { - return value === null || Array.isArray(value); - }); - expect(fledgeInterpretedResponse.paapi).to.be.an('array').that.is.not.empty; for (let i = 0; i < interpretedResponse.length; i++) { const dataItem = interpretedResponse[i]; expect(dataItem).to.include.all.keys('requestId', 'cpm', 'width', 'height', 'ttl', 'creativeId', 'netRevenue', 'currency', 'meta', 'dealId'); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index dfcdecdf586..1ba5df02786 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -13,7 +13,6 @@ import 'modules/multibid/index.js'; import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/paapi.js'; import {deepClone} from 'src/utils.js'; import {version} from 'package.json'; @@ -1226,18 +1225,6 @@ describe('OpenxRtbAdapter', function () { expect(request[0].data).to.not.have.any.keys('user'); }); }); - - context('FLEDGE', function() { - it('when FLEDGE is enabled, should send whatever is set in ortb2imp.ext.ae in all bid requests', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes, { - ...mockBidderRequest, - paapi: { - enabled: true - } - }); - expect(request[0].data.imp[0].ext.ae).to.equal(2); - }); - }); }); context('banner', function () { @@ -1885,104 +1872,6 @@ describe('OpenxRtbAdapter', function () { }); }); } - - context('when the response contains FLEDGE interest groups config', function() { - let response; - - beforeEach(function () { - sinon.stub(config, 'getConfig') - .withArgs('fledgeEnabled') - .returns(true); - - bidRequestConfigs = [{ - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]], - }, - }, - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id' - }]; - - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; - - bidResponse = { - seatbid: [{ - bid: [{ - impid: 'test-bid-id', - price: 2, - w: 300, - h: 250, - crid: 'test-creative-id', - dealid: 'test-deal-id', - adm: 'test-ad-markup' - }] - }], - cur: 'AUS', - ext: { - fledge_auction_configs: { - 'test-bid-id': { - seller: 'codinginadtech.com', - interestGroupBuyers: ['somedomain.com'], - sellerTimeout: 0, - perBuyerSignals: { - 'somedomain.com': { - base_bid_micros: 0.1, - disallowed_advertiser_ids: [ - '1234', - '2345' - ], - multiplier: 1.3, - use_bid_multiplier: true, - win_reporting_id: '1234567asdf' - } - } - } - } - } - }; - - response = spec.interpretResponse({body: bidResponse}, bidRequest); - }); - - afterEach(function () { - config.getConfig.restore(); - }); - - it('should return FLEDGE auction_configs alongside bids', function () { - expect(response).to.have.property('bids'); - expect(response).to.have.property('paapi'); - expect(response.paapi.length).to.equal(1); - expect(response.paapi[0].bidId).to.equal('test-bid-id'); - }); - - it('should inject ortb2Imp in auctionSignals', function () { - const auctionConfig = response.paapi[0].config; - expect(auctionConfig).to.deep.include({ - auctionSignals: { - ortb2Imp: { - id: 'test-bid-id', - tagid: '12345678', - banner: { - topframe: 0, - format: bidRequestConfigs[0].mediaTypes.banner.sizes.map(([w, h]) => ({w, h})) - }, - ext: { - divid: 'adunit-code', - }, - secure: 1 - } - } - }); - }) - }); }); describe('user sync', function () { diff --git a/test/spec/modules/optableBidAdapter_spec.js b/test/spec/modules/optableBidAdapter_spec.js deleted file mode 100644 index b7cf2e3b44d..00000000000 --- a/test/spec/modules/optableBidAdapter_spec.js +++ /dev/null @@ -1,116 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/optableBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory.js'; - -describe('optableBidAdapter', function() { - const adapter = newBidder(spec); - - describe('isBidRequestValid', function() { - const validBid = { - bidder: 'optable', - params: { site: '123' }, - }; - - it('should return true when required params are present', function() { - expect(spec.isBidRequestValid(validBid)).to.be.true; - }); - - it('should return false when site is missing', function() { - const invalidBid = { ...validBid }; - delete invalidBid.params.site; - expect(spec.isBidRequestValid(invalidBid)).to.be.false; - }); - }); - - describe('buildRequests', function() { - const validBid = { - bidder: 'optable', - params: { - site: '123', - }, - }; - - const bidderRequest = { - bidderRequestId: 'bid123', - refererInfo: { - domain: 'example.com', - page: 'https://example.com/page', - ref: 'https://referrer.com' - }, - }; - - it('should include site as tagid in imp', function() { - const request = spec.buildRequests([validBid], bidderRequest); - expect(request.url).to.equal('https://ads.optable.co/ca/ortb2/v1/ssp/bid'); - expect(request.method).to.equal('POST'); - expect(request.data.imp[0].tagid).to.equal('123') - }); - }); - - describe('buildPAAPIConfigs', () => { - function makeRequest({bidId, site = 'mockSite', ae = 1}) { - return { - bidId, - params: { - site - }, - ortb2Imp: { - ext: {ae} - } - } - } - it('should generate auction configs for ae requests', () => { - const configs = spec.buildPAAPIConfigs([ - makeRequest({bidId: 'bid1', ae: 1}), - makeRequest({bidId: 'bid2', ae: 0}), - makeRequest({bidId: 'bid3', ae: 1}), - ]); - expect(configs.map(cfg => cfg.bidId)).to.eql(['bid1', 'bid3']); - configs.forEach(cfg => sinon.assert.match(cfg.config, { - seller: 'https://ads.optable.co', - decisionLogicURL: `https://ads.optable.co/ca/paapi/v1/ssp/decision-logic.js?origin=mockSite`, - interestGroupBuyers: ['https://ads.optable.co'] - })) - }) - }) - - describe('interpretResponse', function() { - const validBid = { - bidder: 'optable', - params: { - site: '123', - }, - }; - - const bidderRequest = { - bidderRequestId: 'bid123', - refererInfo: { - domain: 'example.com', - page: 'https://example.com/page', - ref: 'https://referrer.com' - }, - }; - - const response = { - body: { - ext: { - optable: { - fledge: { - auctionconfigs: [ - { impid: 'bid123', seller: 'https://ads.optable.co' }, - ] - } - } - } - } - }; - - it('maps paapi from ext.optable.fledge.auctionconfigs', function() { - const request = spec.buildRequests([validBid], bidderRequest); - const result = spec.interpretResponse(response, request); - expect(result.paapi).to.deep.equal([ - { bidId: 'bid123', config: { seller: 'https://ads.optable.co' } } - ]); - }); - }); -}); diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index 3eabc8a5190..16440f7e11d 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -3154,15 +3154,6 @@ describe('ozone Adapter', function () { const payload = JSON.parse(request.data); expect(payload.ext.ozone.cookieDeprecationLabel).to.equal('none'); }); - it('should handle fledge requests', function () { - const bidderRequest = JSON.parse(JSON.stringify(validBidderRequest)); - const bidRequests = JSON.parse(JSON.stringify(validBidRequests)); - deepSetValue(bidRequests[0], 'ortb2Imp.ext.ae', 1); - bidderRequest.fledgeEnabled = true; - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - expect(payload.imp[0].ext.ae).to.equal(1); - }); it('Single request: should use ortb auction ID & transaction ID values if set (this will be the case when publisher opts in with config)', function() { var specMock = utils.deepClone(spec); config.setConfig({'ozone': {'singleRequest': true}}); @@ -3424,20 +3415,6 @@ describe('ozone Adapter', function () { const bid = result[0]; expect(bid.mediaType).to.equal('video'); }); - it('should handle fledge response', function () { - const req = spec.buildRequests(validBidRequests, validBidderRequest); - const objResp = JSON.parse(JSON.stringify(validResponse)); - objResp.body.ext = {igi: [{ - 'impid': '1', - 'igb': [{ - 'origin': 'https://paapi.dsp.com', - 'pbs': '{"key": "value"}' - }] - }]}; - const result = spec.interpretResponse(objResp, req); - expect(result).to.be.an('object'); - expect(result.fledgeAuctionConfigs[0]['impid']).to.equal('1'); - }); it('should add labels in the adserver request if they are present in the auction response', function () { const request = spec.buildRequests(validBidRequestsMulti, validBidderRequest); const validres = JSON.parse(JSON.stringify(validResponse2Bids)); diff --git a/test/spec/modules/paapiForGpt_spec.js b/test/spec/modules/paapiForGpt_spec.js deleted file mode 100644 index eb75d51540d..00000000000 --- a/test/spec/modules/paapiForGpt_spec.js +++ /dev/null @@ -1,216 +0,0 @@ -import { - getPAAPISizeHook, - onAuctionConfigFactory, - setPAAPIConfigFactory, setTargetingHookFactory, - slotConfigurator -} from 'modules/paapiForGpt.js'; -import * as gptUtils from '../../../libraries/gptUtils/gptUtils.js'; -import 'modules/appnexusBidAdapter.js'; -import 'modules/rubiconBidAdapter.js'; -import {deepSetValue} from '../../../src/utils.js'; -import {config} from 'src/config.js'; - -describe('paapiForGpt module', () => { - let sandbox, fledgeAuctionConfig; - - beforeEach(() => { - sandbox = sinon.createSandbox(); - fledgeAuctionConfig = { - seller: 'bidder', - mock: 'config' - }; - }); - afterEach(() => { - sandbox.restore(); - }); - - describe('slotConfigurator', () => { - let setGptConfig; - function mockGptSlot(auPath) { - return { - setConfig: sinon.stub(), - getAdUnitPath: () => auPath - } - } - beforeEach(() => { - setGptConfig = slotConfigurator(); - }); - - Object.entries({ - 'single slot': [mockGptSlot('mock/gpt/au')], - 'multiple slots': [mockGptSlot('mock/gpt/au'), mockGptSlot('mock/gpt/au2')] - }).forEach(([t, gptSlots]) => { - describe(`when ad unit code matches ${t}`, () => { - it('should set GPT slot config', () => { - setGptConfig('au', gptSlots, [fledgeAuctionConfig]); - gptSlots.forEach(slot => { - sinon.assert.calledWith(slot.setConfig, { - componentAuction: [{ - configKey: 'bidder', - auctionConfig: fledgeAuctionConfig, - }] - }); - }) - }); - describe('when reset = true', () => { - it('should reset GPT slot config', () => { - setGptConfig('au', gptSlots, [fledgeAuctionConfig]); - gptSlots.forEach(slot => slot.setConfig.resetHistory()); - setGptConfig('au', gptSlots, [], true); - gptSlots.forEach(slot => { - sinon.assert.calledWith(slot.setConfig, { - componentAuction: [{ - configKey: 'bidder', - auctionConfig: null - }] - }); - }) - }); - - it('should reset only sellers with no fresh config', () => { - setGptConfig('au', gptSlots, [{seller: 's1'}, {seller: 's2'}]); - gptSlots.forEach(slot => slot.setConfig.resetHistory()); - setGptConfig('au', gptSlots, [{seller: 's1'}], true); - gptSlots.forEach(slot => { - sinon.assert.calledWith(slot.setConfig, { - componentAuction: [{ - configKey: 's1', - auctionConfig: {seller: 's1'} - }, { - configKey: 's2', - auctionConfig: null - }] - }) - }) - }); - - it('should not reset sellers that were already reset', () => { - setGptConfig('au', gptSlots, [{seller: 's1'}]); - setGptConfig('au', gptSlots, [], true); - gptSlots.forEach(slot => slot.setConfig.resetHistory()); - setGptConfig('au', gptSlots, [], true); - gptSlots.forEach(slot => sinon.assert.notCalled(slot.setConfig)); - }) - - it('should keep track of configuration history by ad unit', () => { - setGptConfig('au1', gptSlots, [{seller: 's1'}]); - setGptConfig('au1', gptSlots, [{seller: 's2'}], false); - setGptConfig('au2', gptSlots, [{seller: 's3'}]); - gptSlots.forEach(slot => slot.setConfig.resetHistory()); - setGptConfig('au1', gptSlots, [], true); - gptSlots.forEach(slot => { - sinon.assert.calledWith(slot.setConfig, { - componentAuction: [{ - configKey: 's1', - auctionConfig: null - }, { - configKey: 's2', - auctionConfig: null - }] - }); - }) - }) - }); - }) - }) - }); - describe('setTargeting hook', () => { - let setPaapiConfig, setTargetingHook, next; - beforeEach(() => { - setPaapiConfig = sinon.stub() - setTargetingHook = setTargetingHookFactory(setPaapiConfig); - next = sinon.stub(); - }); - function expectFilters(...filters) { - expect(setPaapiConfig.args.length).to.eql(filters.length) - filters.forEach(filter => { - sinon.assert.calledWith(setPaapiConfig, filter, 'mock-matcher') - }) - } - function runHook(adUnit) { - setTargetingHook(next, adUnit, 'mock-matcher'); - sinon.assert.calledWith(next, adUnit, 'mock-matcher'); - } - it('should invoke with no filters when adUnit is undef', () => { - runHook(); - expectFilters(undefined); - }); - it('should invoke once when adUnit is a string', () => { - runHook('mock-au'); - expectFilters({adUnitCode: 'mock-au'}) - }); - it('should invoke once per ad unit when an array', () => { - runHook(['au1', 'au2']); - expectFilters({adUnitCode: 'au1'}, {adUnitCode: 'au2'}); - }) - }) - describe('setPAAPIConfigForGpt', () => { - let getPAAPIConfig, setGptConfig, getSlots, setPAAPIConfigForGPT; - beforeEach(() => { - getPAAPIConfig = sinon.stub(); - setGptConfig = sinon.stub(); - getSlots = sinon.stub().callsFake((codes) => Object.fromEntries(codes.map(code => [code, ['mock-slot']]))) - setPAAPIConfigForGPT = setPAAPIConfigFactory(getPAAPIConfig, setGptConfig, getSlots); - }); - - Object.entries({ - missing: null, - empty: {} - }).forEach(([t, configs]) => { - it(`does not set GPT slot config when config is ${t}`, () => { - getPAAPIConfig.returns(configs); - setPAAPIConfigForGPT('mock-filters'); - sinon.assert.calledWith(getPAAPIConfig, 'mock-filters'); - sinon.assert.notCalled(setGptConfig); - }) - }); - - it('passes customSlotMatching to getSlots', () => { - getPAAPIConfig.returns({au1: {}}); - setPAAPIConfigForGPT('mock-filters', 'mock-custom-matching'); - sinon.assert.calledWith(getSlots, ['au1'], 'mock-custom-matching'); - }) - - it('sets GPT slot config for each ad unit that has PAAPI config, and resets the rest', () => { - const cfg = { - au1: { - componentAuctions: [{seller: 's1'}, {seller: 's2'}] - }, - au2: { - componentAuctions: [{seller: 's3'}] - }, - au3: null - } - getPAAPIConfig.returns(cfg); - setPAAPIConfigForGPT('mock-filters'); - sinon.assert.calledWith(getPAAPIConfig, 'mock-filters'); - Object.entries(cfg).forEach(([au, config]) => { - sinon.assert.calledWith(setGptConfig, au, ['mock-slot'], config?.componentAuctions ?? [], true); - }) - }); - }); - - describe('getPAAPISizeHook', () => { - let next; - beforeEach(() => { - next = sinon.stub(); - next.bail = sinon.stub(); - }); - - it('should pick largest supported size over larger unsupported size', () => { - getPAAPISizeHook(next, [[999, 999], [300, 250], [300, 600], [1234, 4321]]); - sinon.assert.calledWith(next.bail, [300, 600]); - }); - - Object.entries({ - 'present': [], - 'supported': [[123, 4], [321, 5]], - 'defined': undefined, - }).forEach(([t, sizes]) => { - it(`should defer to next when no size is ${t}`, () => { - getPAAPISizeHook(next, sizes); - sinon.assert.calledWith(next, sizes); - }) - }) - }) -}); diff --git a/test/spec/modules/paapi_spec.js b/test/spec/modules/paapi_spec.js deleted file mode 100644 index 2d491cdfe14..00000000000 --- a/test/spec/modules/paapi_spec.js +++ /dev/null @@ -1,2014 +0,0 @@ -import {expect} from 'chai'; -import {config} from '../../../src/config.js'; -import adapterManager from '../../../src/adapterManager.js'; -import * as utils from '../../../src/utils.js'; -import {deepAccess, deepClone} from '../../../src/utils.js'; -import {hook} from '../../../src/hook.js'; -import 'modules/appnexusBidAdapter.js'; -import 'modules/rubiconBidAdapter.js'; -import { - adAuctionHeadersHook, - addPaapiConfigHook, - addPaapiData, - ASYNC_SIGNALS, AsyncPAAPIParam, buildPAAPIParams, - buyersToAuctionConfigs, - getPAAPIConfig, - getPAAPISize, - IGB_TO_CONFIG, - mergeBuyers, NAVIGATOR_APIS, - onAuctionInit, - parallelPaapiProcessing, - parseExtIgi, - parseExtPrebidFledge, - partitionBuyers, - partitionBuyersByBidder, - registerSubmodule, - reset, - setImpExtAe, - setResponsePaapiConfigs -} from 'modules/paapi.js'; -import * as events from 'src/events.js'; -import {EVENTS} from 'src/constants.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; -import {auctionManager} from '../../../src/auctionManager.js'; -import {stubAuctionIndex} from '../../helpers/indexStub.js'; -import {AuctionIndex} from '../../../src/auctionIndex.js'; -import {buildActivityParams} from '../../../src/activities/params.js'; - -describe('paapi module', () => { - let sandbox; - before(reset); - beforeEach(() => { - sandbox = sinon.createSandbox(); - }); - afterEach(() => { - sandbox.restore(); - reset(); - }); - - describe(`using paapi configuration`, () => { - let getPAAPISizeStub; - - function getPAAPISizeHook(next, sizes) { - next.bail(getPAAPISizeStub(sizes)); - } - - before(() => { - getPAAPISize.before(getPAAPISizeHook, 100); - }); - - after(() => { - getPAAPISize.getHooks({hook: getPAAPISizeHook}).remove(); - }); - - beforeEach(() => { - getPAAPISizeStub = sinon.stub(); - }); - - describe('adAuctionHeadersHook', () => { - let bidderRequest, ajax; - beforeEach(() => { - ajax = sinon.stub(); - bidderRequest = {paapi: {}} - }) - function getWrappedAjax() { - let wrappedAjax; - const next = sinon.stub().callsFake((spec, bids, br, ajax) => { - wrappedAjax = ajax; - }); - adAuctionHeadersHook(next, {}, [], bidderRequest, ajax); - return wrappedAjax; - } - describe('when PAAPI is enabled', () => { - beforeEach(() => { - bidderRequest.paapi.enabled = true; - }); - [ - undefined, - {}, - {adAuctionHeaders: true} - ].forEach(options => - it(`should set adAuctionHeaders = true (when options are ${JSON.stringify(options)})`, () => { - getWrappedAjax()('url', {}, 'data', options); - sinon.assert.calledWith(ajax, 'url', {}, 'data', sinon.match({adAuctionHeaders: true})); - })); - - it('should respect adAuctionHeaders: false', () => { - getWrappedAjax()('url', {}, 'data', {adAuctionHeaders: false}); - sinon.assert.calledWith(ajax, 'url', {}, 'data', sinon.match({adAuctionHeaders: false})); - }) - }); - it('should not alter ajax when paapi is not enabled', () => { - expect(getWrappedAjax()).to.equal(ajax); - }) - }) - - describe('getPAAPIConfig', function () { - let nextFnSpy, auctionConfig, paapiConfig; - before(() => { - config.setConfig({paapi: {enabled: true}}); - }); - beforeEach(() => { - auctionConfig = { - seller: 'bidder', - mock: 'config' - }; - paapiConfig = { - config: auctionConfig - }; - nextFnSpy = sinon.spy(); - }); - - describe('on a single auction', function () { - const auctionId = 'aid'; - beforeEach(function () { - sandbox.stub(auctionManager, 'index').value(stubAuctionIndex({auctionId})); - }); - - it('should call next()', function () { - const request = {auctionId, adUnitCode: 'auc'}; - addPaapiConfigHook(nextFnSpy, request, paapiConfig); - sinon.assert.calledWith(nextFnSpy, request, paapiConfig); - }); - - describe('igb', () => { - let igb1, igb2, buyerAuctionConfig; - beforeEach(() => { - igb1 = { - origin: 'buyer.1' - }; - igb2 = { - origin: 'buyer.2' - }; - buyerAuctionConfig = { - seller: 'seller', - decisionLogicURL: 'seller-decision-logic' - }; - config.mergeConfig({ - paapi: { - componentSeller: { - auctionConfig: buyerAuctionConfig - } - } - }); - }); - - function addIgb(request, igb) { - addPaapiConfigHook(nextFnSpy, Object.assign({auctionId}, request), {igb}); - } - - it('should be collected into an auction config', () => { - addIgb({adUnitCode: 'au1'}, igb1); - addIgb({adUnitCode: 'au1'}, igb2); - events.emit(EVENTS.AUCTION_END, {auctionId, adUnitCodes: ['au1']}); - const buyerConfig = getPAAPIConfig({auctionId}).au1.componentAuctions[0]; - sinon.assert.match(buyerConfig, { - interestGroupBuyers: [igb1.origin, igb2.origin], - ...buyerAuctionConfig - }); - }); - - describe('FPD', () => { - let ortb2, ortb2Imp; - beforeEach(() => { - ortb2 = {'fpd': 1}; - ortb2Imp = {'fpd': 2}; - }); - - function getBuyerAuctionConfig() { - addIgb({adUnitCode: 'au1', ortb2, ortb2Imp}, igb1); - events.emit(EVENTS.AUCTION_END, {auctionId, adUnitCodes: ['au1']}); - return getPAAPIConfig({auctionId}).au1.componentAuctions[0]; - } - - it('should be added to auction config', () => { - sinon.assert.match(getBuyerAuctionConfig().perBuyerSignals[igb1.origin], { - prebid: { - ortb2, - ortb2Imp - } - }); - }); - - it('should not override existing perBuyerSignals', () => { - const original = { - ortb2: { - fpd: 'original' - } - }; - igb1.pbs = { - prebid: deepClone(original) - }; - sinon.assert.match(getBuyerAuctionConfig().perBuyerSignals[igb1.origin], { - prebid: original - }); - }); - }); - }); - - describe('should collect auction configs', () => { - let cf1, cf2; - beforeEach(() => { - cf1 = {...auctionConfig, id: 1, seller: 'b1'}; - cf2 = {...auctionConfig, id: 2, seller: 'b2'}; - addPaapiConfigHook(nextFnSpy, {auctionId, adUnitCode: 'au1'}, {config: cf1}); - addPaapiConfigHook(nextFnSpy, {auctionId, adUnitCode: 'au2'}, {config: cf2}); - events.emit(EVENTS.AUCTION_END, {auctionId, adUnitCodes: ['au1', 'au2', 'au3']}); - }); - - it('and make them available at end of auction', () => { - sinon.assert.match(getPAAPIConfig({auctionId}), { - au1: { - componentAuctions: [cf1] - }, - au2: { - componentAuctions: [cf2] - } - }); - }); - - it('and filter them by ad unit', () => { - const cfg = getPAAPIConfig({auctionId, adUnitCode: 'au1'}); - expect(Object.keys(cfg)).to.have.members(['au1']); - sinon.assert.match(cfg.au1, { - componentAuctions: [cf1] - }); - }); - - it('and not return them again', () => { - getPAAPIConfig(); - const cfg = getPAAPIConfig(); - expect(cfg).to.eql({}); - }); - - describe('includeBlanks = true', () => { - it('includes all ad units', () => { - const cfg = getPAAPIConfig({}, true); - expect(Object.keys(cfg)).to.have.members(['au1', 'au2', 'au3']); - expect(cfg.au3).to.eql(null); - }); - it('includes the targeted adUnit', () => { - expect(getPAAPIConfig({adUnitCode: 'au3'}, true)).to.eql({ - au3: null - }); - }); - it('includes the targeted auction', () => { - const cfg = getPAAPIConfig({auctionId}, true); - expect(Object.keys(cfg)).to.have.members(['au1', 'au2', 'au3']); - expect(cfg.au3).to.eql(null); - }); - it('does not include non-existing ad units', () => { - expect(getPAAPIConfig({adUnitCode: 'other'})).to.eql({}); - }); - it('does not include non-existing auctions', () => { - expect(getPAAPIConfig({auctionId: 'other'})).to.eql({}); - }); - }); - }); - - it('should drop auction configs after end of auction', () => { - events.emit(EVENTS.AUCTION_END, {auctionId}); - addPaapiConfigHook(nextFnSpy, {auctionId, adUnitCode: 'au'}, paapiConfig); - expect(getPAAPIConfig({auctionId})).to.eql({}); - }); - - describe('FPD', () => { - let ortb2, ortb2Imp; - beforeEach(() => { - ortb2 = {fpd: 1}; - ortb2Imp = {fpd: 2}; - }); - - function getComponentAuctionConfig() { - addPaapiConfigHook(nextFnSpy, { - auctionId, - adUnitCode: 'au1', - ortb2: {fpd: 1}, - ortb2Imp: {fpd: 2} - }, paapiConfig); - events.emit(EVENTS.AUCTION_END, {auctionId}); - return getPAAPIConfig({auctionId}).au1.componentAuctions[0]; - } - - it('should be added to auctionSignals', () => { - sinon.assert.match(getComponentAuctionConfig().auctionSignals, { - prebid: {ortb2, ortb2Imp} - }); - }); - it('should not override existing auctionSignals', () => { - auctionConfig.auctionSignals = {prebid: {ortb2: {fpd: 'original'}}}; - sinon.assert.match(getComponentAuctionConfig().auctionSignals, { - prebid: { - ortb2: {fpd: 'original'}, - ortb2Imp - } - }); - }); - - it('should be added to perBuyerSignals', () => { - auctionConfig.interestGroupBuyers = ['buyer.1', 'buyer.2']; - const pbs = getComponentAuctionConfig().perBuyerSignals; - sinon.assert.match(pbs, { - 'buyer.1': {prebid: {ortb2, ortb2Imp}}, - 'buyer.2': {prebid: {ortb2, ortb2Imp}} - }); - }); - - it('should not override existing perBuyerSignals', () => { - auctionConfig.interestGroupBuyers = ['buyer']; - const original = { - prebid: { - ortb2: { - fpd: 'original' - } - } - }; - auctionConfig.perBuyerSignals = { - buyer: deepClone(original) - }; - sinon.assert.match(getComponentAuctionConfig().perBuyerSignals.buyer, original); - }); - }); - - describe('submodules', () => { - let submods; - beforeEach(() => { - submods = [1, 2].map(i => ({ - name: `test${i}`, - onAuctionConfig: sinon.stub() - })); - submods.forEach(registerSubmodule); - }); - - describe('onAuctionConfig', () => { - const auctionId = 'aid'; - it('is invoked with null configs when there\'s no config', () => { - events.emit(EVENTS.AUCTION_END, {auctionId, adUnitCodes: ['au']}); - submods.forEach(submod => sinon.assert.calledWith(submod.onAuctionConfig, auctionId, {au: null})); - }); - it('is invoked with relevant configs', () => { - addPaapiConfigHook(nextFnSpy, {auctionId, adUnitCode: 'au1'}, paapiConfig); - addPaapiConfigHook(nextFnSpy, {auctionId, adUnitCode: 'au2'}, paapiConfig); - events.emit(EVENTS.AUCTION_END, {auctionId, adUnitCodes: ['au1', 'au2', 'au3']}); - submods.forEach(submod => { - sinon.assert.calledWith(submod.onAuctionConfig, auctionId, { - au1: {componentAuctions: [auctionConfig]}, - au2: {componentAuctions: [auctionConfig]}, - au3: null - }); - }); - }); - }); - }); - - describe('floor signal', () => { - before(() => { - if (!getGlobal().convertCurrency) { - getGlobal().convertCurrency = () => null; - getGlobal().convertCurrency.mock = true; - } - }); - after(() => { - if (getGlobal().convertCurrency.mock) { - delete getGlobal().convertCurrency; - } - }); - - beforeEach(() => { - sandbox.stub(getGlobal(), 'convertCurrency').callsFake((amount, from, to) => { - if (from === to) return amount; - if (from === 'USD' && to === 'JPY') return amount * 100; - if (from === 'JPY' && to === 'USD') return amount / 100; - throw new Error('unexpected currency conversion'); - }); - }); - - Object.entries({ - 'bids': (payload, values) => { - payload.bidsReceived = values - .map((val) => ({adUnitCode: 'au', cpm: val.amount, currency: val.cur})) - .concat([{adUnitCode: 'other', cpm: 10000, currency: 'EUR'}]); - }, - 'no bids': (payload, values) => { - payload.bidderRequests = values - .map((val) => ({ - bids: [{ - adUnitCode: 'au', - getFloor: () => ({floor: val.amount, currency: val.cur}) - }] - })) - .concat([{bids: {adUnitCode: 'other', getFloor: () => ({floor: -10000, currency: 'EUR'})}}]); - } - }).forEach(([tcase, setup]) => { - describe(`when auction has ${tcase}`, () => { - Object.entries({ - 'no currencies': { - values: [{amount: 1}, {amount: 100}, {amount: 10}, {amount: 100}], - 'bids': { - bidfloor: 100, - bidfloorcur: undefined - }, - 'no bids': { - bidfloor: 1, - bidfloorcur: undefined, - } - }, - 'only zero values': { - values: [{amount: 0, cur: 'USD'}, {amount: 0, cur: 'JPY'}], - 'bids': { - bidfloor: undefined, - bidfloorcur: undefined, - }, - 'no bids': { - bidfloor: undefined, - bidfloorcur: undefined, - } - }, - 'matching currencies': { - values: [{amount: 10, cur: 'JPY'}, {amount: 100, cur: 'JPY'}], - 'bids': { - bidfloor: 100, - bidfloorcur: 'JPY', - }, - 'no bids': { - bidfloor: 10, - bidfloorcur: 'JPY', - } - }, - 'mixed currencies': { - values: [{amount: 10, cur: 'USD'}, {amount: 10, cur: 'JPY'}], - 'bids': { - bidfloor: 10, - bidfloorcur: 'USD' - }, - 'no bids': { - bidfloor: 10, - bidfloorcur: 'JPY', - } - } - }).forEach(([t, testConfig]) => { - const values = testConfig.values; - const {bidfloor, bidfloorcur} = testConfig[tcase]; - - describe(`with ${t}`, () => { - let payload; - beforeEach(() => { - payload = {auctionId}; - setup(payload, values); - }); - - it('should populate bidfloor/bidfloorcur', () => { - addPaapiConfigHook(nextFnSpy, {auctionId, adUnitCode: 'au'}, paapiConfig); - events.emit(EVENTS.AUCTION_END, payload); - const cfg = getPAAPIConfig({auctionId}).au; - const signals = cfg.auctionSignals; - sinon.assert.match(cfg.componentAuctions[0].auctionSignals, signals || {}); - expect(signals?.prebid?.bidfloor).to.eql(bidfloor); - expect(signals?.prebid?.bidfloorcur).to.eql(bidfloorcur); - }); - }); - }); - }); - }); - }); - - describe('requestedSize', () => { - let adUnit; - beforeEach(() => { - adUnit = { - code: 'au', - }; - }); - - function getConfig() { - addPaapiConfigHook(nextFnSpy, {auctionId, adUnitCode: adUnit.code}, paapiConfig); - events.emit(EVENTS.AUCTION_END, {auctionId, adUnitCodes: [adUnit.code], adUnits: [adUnit]}); - return getPAAPIConfig()[adUnit.code]; - } - - Object.entries({ - 'adUnit.ortb2Imp.ext.paapi.requestedSize'() { - adUnit.ortb2Imp = { - ext: { - paapi: { - requestedSize: { - width: 123, - height: 321 - } - } - } - }; - }, - 'largest size'() { - getPAAPISizeStub.returns([123, 321]); - } - }).forEach(([t, setup]) => { - describe(`should be set from ${t}`, () => { - beforeEach(setup); - - it('without overriding component auctions, if set', () => { - auctionConfig.requestedSize = {width: '1px', height: '2px'}; - expect(getConfig().componentAuctions[0].requestedSize).to.eql({ - width: '1px', - height: '2px' - }); - }); - - it('on component auction, if missing', () => { - expect(getConfig().componentAuctions[0].requestedSize).to.eql({ - width: 123, - height: 321 - }); - }); - - it('on top level auction', () => { - expect(getConfig().requestedSize).to.eql({ - width: 123, - height: 321, - }); - }); - }); - }); - }); - }); - - describe('with multiple auctions', () => { - const AUCTION1 = 'auction1'; - const AUCTION2 = 'auction2'; - - function mockAuction(auctionId) { - return { - getAuctionId() { - return auctionId; - } - }; - } - - function expectAdUnitsFromAuctions(actualConfig, auToAuctionMap) { - expect(Object.keys(actualConfig)).to.have.members(Object.keys(auToAuctionMap)); - Object.entries(actualConfig).forEach(([au, cfg]) => { - cfg.componentAuctions.forEach(cmp => expect(cmp.auctionId).to.eql(auToAuctionMap[au])); - }); - } - - let configs; - beforeEach(() => { - const mockAuctions = [mockAuction(AUCTION1), mockAuction(AUCTION2)]; - sandbox.stub(auctionManager, 'index').value(new AuctionIndex(() => mockAuctions)); - configs = {[AUCTION1]: {}, [AUCTION2]: {}}; - Object.entries({ - [AUCTION1]: [['au1', 'au2'], ['missing-1']], - [AUCTION2]: [['au2', 'au3'], []], - }).forEach(([auctionId, [adUnitCodes, noConfigAdUnitCodes]]) => { - adUnitCodes.forEach(adUnitCode => { - const cfg = {...auctionConfig, auctionId, adUnitCode}; - configs[auctionId][adUnitCode] = cfg; - addPaapiConfigHook(nextFnSpy, {auctionId, adUnitCode}, {config: cfg}); - }); - events.emit(EVENTS.AUCTION_END, {auctionId, adUnitCodes: adUnitCodes.concat(noConfigAdUnitCodes)}); - }); - }); - - it('should filter by auction', () => { - expectAdUnitsFromAuctions(getPAAPIConfig({auctionId: AUCTION1}), {au1: AUCTION1, au2: AUCTION1}); - expectAdUnitsFromAuctions(getPAAPIConfig({auctionId: AUCTION2}), {au2: AUCTION2, au3: AUCTION2}); - }); - - it('should filter by auction and ad unit', () => { - expectAdUnitsFromAuctions(getPAAPIConfig({auctionId: AUCTION1, adUnitCode: 'au2'}), {au2: AUCTION1}); - expectAdUnitsFromAuctions(getPAAPIConfig({auctionId: AUCTION2, adUnitCode: 'au2'}), {au2: AUCTION2}); - }); - - it('should use last auction for each ad unit', () => { - expectAdUnitsFromAuctions(getPAAPIConfig(), {au1: AUCTION1, au2: AUCTION2, au3: AUCTION2}); - }); - - it('should filter by ad unit and use latest auction', () => { - expectAdUnitsFromAuctions(getPAAPIConfig({adUnitCode: 'au2'}), {au2: AUCTION2}); - }); - - it('should keep track of which configs were returned', () => { - expectAdUnitsFromAuctions(getPAAPIConfig({auctionId: AUCTION1}), {au1: AUCTION1, au2: AUCTION1}); - expect(getPAAPIConfig({auctionId: AUCTION1})).to.eql({}); - expectAdUnitsFromAuctions(getPAAPIConfig(), {au2: AUCTION2, au3: AUCTION2}); - }); - - describe('includeBlanks = true', () => { - Object.entries({ - 'auction with blanks': { - filters: {auctionId: AUCTION1}, - expected: {au1: true, au2: true, 'missing-1': false} - }, - 'blank adUnit in an auction': { - filters: {auctionId: AUCTION1, adUnitCode: 'missing-1'}, - expected: {'missing-1': false} - }, - 'non-existing auction': { - filters: {auctionId: 'other'}, - expected: {} - }, - 'non-existing adUnit in an auction': { - filters: {auctionId: AUCTION2, adUnitCode: 'other'}, - expected: {} - }, - 'non-existing ad unit': { - filters: {adUnitCode: 'other'}, - expected: {}, - }, - 'non existing ad unit in a non-existing auction': { - filters: {adUnitCode: 'other', auctionId: 'other'}, - expected: {} - }, - 'all ad units': { - filters: {}, - expected: {'au1': true, 'au2': true, 'missing-1': false, 'au3': true} - } - }).forEach(([t, {filters, expected}]) => { - it(t, () => { - const cfg = getPAAPIConfig(filters, true); - expect(Object.keys(cfg)).to.have.members(Object.keys(expected)); - Object.entries(expected).forEach(([au, shouldBeFilled]) => { - if (shouldBeFilled) { - expect(cfg[au]).to.not.be.null; - } else { - expect(cfg[au]).to.be.null; - } - }); - }); - }); - }); - }); - }); - - describe('markForFledge', function () { - const navProps = Object.fromEntries(['runAdAuction', 'joinAdInterestGroup'].map(p => [p, navigator[p]])); - let adUnits; - - before(function () { - // navigator.runAdAuction & co may not exist, so we can't stub it normally with - // sinon.stub(navigator, 'runAdAuction') or something - Object.keys(navProps).forEach(p => { - navigator[p] = sinon.stub(); - }); - hook.ready(); - config.resetConfig(); - }); - - after(function () { - Object.entries(navProps).forEach(([p, orig]) => navigator[p] = orig); - }); - - beforeEach(() => { - getPAAPISizeStub = sinon.stub(); - adUnits = [{ - 'code': '/19968336/header-bid-tag1', - 'mediaTypes': { - 'banner': { - 'sizes': [[728, 90]] - }, - }, - 'bids': [ - { - 'bidder': 'appnexus', - }, - { - 'bidder': 'rubicon', - }, - ] - }]; - }); - - afterEach(function () { - config.resetConfig(); - }); - - describe('makeBidRequests', () => { - before(() => { - NAVIGATOR_APIS.forEach(method => { - if (navigator[method] == null) { - navigator[method] = () => null; - after(() => { - delete navigator[method]; - }) - } - }) - }); - beforeEach(() => { - NAVIGATOR_APIS.forEach(method => { - sandbox.stub(navigator, method) - }) - }); - - function mark() { - return Object.fromEntries( - adapterManager.makeBidRequests( - adUnits, - Date.now(), - utils.getUniqueIdentifierStr(), - function callback() { - }, - [] - ).map(b => [b.bidderCode, b]) - ); - } - - async function testAsyncParams(bidderRequest) { - for (const method of NAVIGATOR_APIS) { - navigator[method].returns('result'); - expect(await bidderRequest.paapi[method]('arg').resolve()).to.eql('result'); - sinon.assert.calledWith(navigator[method], 'arg'); - } - } - - async function expectFledgeFlags(...enableFlags) { - const bidRequests = mark(); - expect(bidRequests.appnexus.paapi?.enabled).to.eql(enableFlags[0].enabled); - if (bidRequests.appnexus.paapi?.enabled) { - await testAsyncParams(bidRequests.appnexus) - } - bidRequests.appnexus.bids.forEach(bid => expect(bid.ortb2Imp.ext.ae).to.eql(enableFlags[0].ae)); - - expect(bidRequests.rubicon.paapi?.enabled).to.eql(enableFlags[1].enabled); - if (bidRequests.rubicon.paapi?.enabled) { - testAsyncParams(bidRequests.rubicon); - } - - bidRequests.rubicon.bids.forEach(bid => expect(bid.ortb2Imp?.ext?.ae).to.eql(enableFlags[1].ae)); - - Object.values(bidRequests).flatMap(req => req.bids).forEach(bid => { - if (bid.ortb2Imp?.ext?.ae) { - sinon.assert.match(bid.ortb2Imp.ext.igs, { - ae: bid.ortb2Imp.ext.ae, - biddable: 1 - }); - } - }); - } - - describe('with setConfig()', () => { - it('should set paapi.enabled correctly per bidder', async function () { - config.setConfig({ - bidderSequence: 'fixed', - paapi: { - enabled: true, - bidders: ['appnexus'], - defaultForSlots: 1, - } - }); - await expectFledgeFlags({enabled: true, ae: 1}, {enabled: false, ae: 0}); - }); - - it('should set paapi.enabled correctly for all bidders', async function () { - config.setConfig({ - bidderSequence: 'fixed', - paapi: { - enabled: true, - defaultForSlots: 1, - } - }); - await expectFledgeFlags({enabled: true, ae: 1}, {enabled: true, ae: 1}); - }); - - Object.entries({ - 'not set': { - cfg: {}, - componentSeller: false - }, - 'set': { - cfg: { - componentSeller: { - auctionConfig: { - decisionLogicURL: 'publisher.example' - } - } - }, - componentSeller: true - } - }).forEach(([t, {cfg, componentSeller}]) => { - it(`should set request paapi.componentSeller = ${componentSeller} when config componentSeller is ${t}`, () => { - config.setConfig({ - paapi: { - enabled: true, - defaultForSlots: 1, - ...cfg - } - }); - Object.values(mark()).forEach(br => expect(br.paapi?.componentSeller).to.eql(componentSeller)); - }); - }); - }); - }); - describe('addPaapiData', () => { - function getEnrichedAdUnits() { - const next = sinon.stub(); - addPaapiData(next, adUnits); - sinon.assert.calledWith(next, adUnits); - return adUnits; - } - - function getImpExt() { - const next = sinon.stub(); - addPaapiData(next, adUnits); - sinon.assert.calledWith(next, adUnits); - return { - global: adUnits[0].ortb2Imp?.ext, - ...Object.fromEntries(adUnits[0].bids.map(bid => [bid.bidder, bid.ortb2Imp?.ext])) - } - } - - it('should not override pub-defined ext.ae', () => { - config.setConfig({ - paapi: { - enabled: true, - defaultForSlots: 1, - } - }); - Object.assign(adUnits[0], {ortb2Imp: {ext: {ae: 0}}}); - sinon.assert.match(getImpExt(), { - global: { - ae: 0, - }, - rubicon: undefined, - appnexus: undefined - }); - }); - - it('should override per-bidder when excluded via paapi.bidders', () => { - config.setConfig({ - paapi: { - enabled: true, - defaultForSlots: 1, - bidders: ['rubicon'] - } - }) - sinon.assert.match(getImpExt(), { - global: { - ae: 1, - igs: { - ae: 1, - biddable: 1 - } - }, - rubicon: undefined, - appnexus: { - ae: 0, - igs: { - ae: 0, - biddable: 0 - } - } - }) - }) - - it('should populate ext.igs when request has ext.ae', () => { - config.setConfig({ - paapi: { - enabled: true - } - }); - Object.assign(adUnits[0], {ortb2Imp: {ext: {ae: 3}}}); - sinon.assert.match(getImpExt(), { - global: { - ae: 3, - igs: { - ae: 3, - biddable: 1 - } - }, - rubicon: undefined, - appnexus: undefined, - }); - }); - - it('should not override pub-defined ext.igs', () => { - config.setConfig({ - paapi: { - enabled: true - } - }); - Object.assign(adUnits[0], {ortb2Imp: {ext: {ae: 1, igs: {biddable: 0}}}}); - sinon.assert.match(getImpExt(), { - global: { - ae: 1, - igs: { - ae: 1, - biddable: 0 - } - }, - rubicon: undefined, - appnexus: undefined - }) - }); - - it('should fill ext.ae from ext.igs, if defined', () => { - config.setConfig({ - paapi: { - enabled: true - } - }); - Object.assign(adUnits[0], {ortb2Imp: {ext: {igs: {}}}}); - sinon.assert.match(getImpExt(), { - global: { - ae: 1, - igs: { - ae: 1, - biddable: 1 - } - }, - appnexus: undefined, - rubicon: undefined - }) - }); - - describe('ortb2Imp.ext.paapi.requestedSize', () => { - beforeEach(() => { - config.setConfig({ - paapi: { - enabled: true, - defaultForSlots: 1, - } - }); - }); - - it('should default to value returned by getPAAPISize', () => { - getPAAPISizeStub.returns([123, 321]); - expect(getImpExt().global.paapi).to.eql({ - requestedSize: { - width: 123, - height: 321 - } - }); - }); - - it('should not be overridden, if provided by the pub', () => { - adUnits[0].ortb2Imp = { - ext: { - paapi: { - requestedSize: { - width: '123px', - height: '321px' - } - } - } - }; - expect(getImpExt().global.paapi).to.eql({ - requestedSize: { - width: '123px', - height: '321px' - } - }) - sinon.assert.notCalled(getPAAPISizeStub); - }); - - it('should not be set if adUnit has no banner sizes', () => { - adUnits[0].mediaTypes = { - video: {} - }; - expect(getImpExt().global?.paapi?.requestedSize).to.not.exist; - }); - }); - }); - }); - }); - - describe('igb', () => { - let igb1, igb2; - const buyer1 = 'https://buyer1.example'; - const buyer2 = 'https://buyer2.example'; - beforeEach(() => { - igb1 = { - origin: buyer1, - cur: 'EUR', - maxbid: 1, - pbs: { - signal: 1 - }, - ps: { - priority: 1 - } - }; - igb2 = { - origin: buyer2, - cur: 'USD', - maxbid: 2, - pbs: { - signal: 2 - }, - ps: { - priority: 2 - } - }; - }); - - describe('mergeBuyers', () => { - it('should merge multiple igb into a partial auction config', () => { - sinon.assert.match(mergeBuyers([igb1, igb2]), { - interestGroupBuyers: [buyer1, buyer2], - perBuyerCurrencies: { - [buyer1]: 'EUR', - [buyer2]: 'USD' - }, - perBuyerSignals: { - [buyer1]: { - signal: 1 - }, - [buyer2]: { - signal: 2 - } - }, - perBuyerPrioritySignals: { - [buyer1]: { - priority: 1 - }, - [buyer2]: { - priority: 2 - } - }, - auctionSignals: { - prebid: { - perBuyerMaxbid: { - [buyer1]: 1, - [buyer2]: 2 - } - } - } - }); - }); - - Object.entries(IGB_TO_CONFIG).forEach(([igbField, configField]) => { - it(`should not set ${configField} if ${igbField} is undefined`, () => { - delete igb1[igbField]; - expect(deepAccess(mergeBuyers([igb1, igb2]), configField)[buyer1]).to.not.exist; - }); - }); - - it('ignores igbs that have no origin', () => { - delete igb1.origin; - expect(mergeBuyers([igb1, igb2])).to.eql(mergeBuyers([igb2])); - }); - - it('ignores igbs with duplicate origin', () => { - igb2.origin = igb1.origin; - expect(mergeBuyers([igb1, igb2])).to.eql(mergeBuyers([igb1])); - }); - }); - - describe('partitionBuyers', () => { - it('should return a single partition when there are no duplicates', () => { - expect(partitionBuyers([igb1, igb2])).to.eql([[igb1, igb2]]); - }); - it('should ignore igbs that have no origin', () => { - delete igb1.origin; - expect(partitionBuyers([igb1, igb2])).to.eql([[igb2]]); - }); - it('should return a single partition when duplicates exist, but do not conflict', () => { - expect(partitionBuyers([igb1, igb2, deepClone(igb1)])).to.eql([[igb1, igb2]]); - }); - it('should return multiple partitions when there are conflicts', () => { - const igb3 = deepClone(igb1); - const igb4 = deepClone(igb1); - igb3.pbs.signal = 'conflict'; - igb4.ps.signal = 'conflict'; - expect(partitionBuyers([igb1, igb2, igb3, igb4])).to.eql([ - [igb1, igb2], - [igb3], - [igb4] - ]); - }); - }); - - describe('partitionBuyersByBidder', () => { - it('should split requests by bidder', () => { - expect(partitionBuyersByBidder([[{bidder: 'a'}, igb1], [{bidder: 'b'}, igb2]])).to.eql([ - [{bidder: 'a'}, [igb1]], - [{bidder: 'b'}, [igb2]] - ]); - }); - - it('accepts repeated buyers, if from different bidders', () => { - expect(partitionBuyersByBidder([ - [{bidder: 'a', extra: 'data'}, igb1], - [{bidder: 'b', more: 'data'}, igb1], - [{bidder: 'a'}, igb2], - [{bidder: 'b'}, igb2] - ])).to.eql([ - [{bidder: 'a', extra: 'data'}, [igb1, igb2]], - [{bidder: 'b', more: 'data'}, [igb1, igb2]] - ]); - }); - describe('buyersToAuctionConfig', () => { - let config, partitioners, merge, igbRequests; - beforeEach(() => { - config = { - auctionConfig: { - decisionLogicURL: 'mock-decision-logic' - } - }; - partitioners = { - compact: sinon.stub(), - expand: sinon.stub(), - }; - let i = 0; - merge = sinon.stub().callsFake(() => ({config: i++})); - igbRequests = [ - [{}, igb1], - [{}, igb2] - ]; - }); - - function toAuctionConfig(reqs = igbRequests) { - return buyersToAuctionConfigs(reqs, merge, config, partitioners); - } - - it('uses compact partitions by default, and returns an auction config for each one', () => { - partitioners.compact.returns([[{}, 1], [{}, 2]]); - const [cf1, cf2] = toAuctionConfig(); - sinon.assert.match(cf1[1], { - ...config.auctionConfig, - config: 0 - }); - sinon.assert.match(cf2[1], { - ...config.auctionConfig, - config: 1 - }); - sinon.assert.calledWith(partitioners.compact, igbRequests); - [1, 2].forEach(mockPart => sinon.assert.calledWith(merge, mockPart)); - }); - - it('uses per-bidder partition when config has separateAuctions', () => { - config.separateAuctions = true; - partitioners.expand.returns([]); - toAuctionConfig(); - sinon.assert.called(partitioners.expand); - }); - - it('does not return any auction config when configuration does not specify auctionConfig', () => { - delete config.auctionConfig; - expect(toAuctionConfig()).to.eql([]); - Object.values(partitioners).forEach(part => sinon.assert.notCalled(part)); - }); - - it('sets FPD in auction signals when partitioner returns it', () => { - const fpd = { - ortb2: {fpd: 1}, - ortb2Imp: {fpd: 2} - }; - partitioners.compact.returns([[{}], [fpd]]); - const [cf1, cf2] = toAuctionConfig(); - expect(cf1[1].auctionSignals?.prebid).to.not.exist; - expect(cf2[1].auctionSignals.prebid).to.eql(fpd); - }); - }); - }); - }); - - describe('getPAAPISize', () => { - before(() => { - getPAAPISize.getHooks().remove(); - }); - - Object.entries({ - 'ignores placeholders': { - in: [[1, 1], [0, 0], [3, 4]], - out: [3, 4] - }, - 'picks largest size by area': { - in: [[200, 100], [150, 150]], - out: [150, 150] - }, - 'can handle no sizes': { - in: [], - out: undefined - }, - 'can handle no input': { - in: undefined, - out: undefined - }, - 'can handle placeholder sizes': { - in: [[1, 1]], - out: undefined - } - }).forEach(([t, {in: input, out}]) => { - it(t, () => { - expect(getPAAPISize(input)).to.eql(out); - }); - }); - }); - - describe('buildPaapiParameters', () => { - let next, bidderRequest, spec, bids; - beforeEach(() => { - next = sinon.stub(); - spec = {}; - bidderRequest = {paapi: {enabled: true}}; - bids = []; - }); - - function runParamHook() { - return Promise.resolve(buildPAAPIParams(next, spec, bids, bidderRequest)); - } - - Object.entries({ - 'has no paapiParameters': () => null, - 'returns empty parameter map'() { - spec.paapiParameters = () => ({}) - }, - 'returns null parameter map'() { - spec.paapiParameters = () => null - }, - 'returns params, but PAAPI is disabled'() { - bidderRequest.paapi.enabled = false; - spec.paapiParameters = () => ({param: new AsyncPAAPIParam()}) - } - }).forEach(([t, setup]) => { - it(`should do nothing if spec ${t}`, async () => { - setup(); - await runParamHook(); - sinon.assert.calledWith(next, spec, bids, bidderRequest); - }) - }) - - describe('when paapiParameters returns a map', () => { - let params; - beforeEach(() => { - spec.paapiParameters = sinon.stub().callsFake(() => params); - }); - it('should be invoked with bids & bidderRequest', async () => { - await runParamHook(); - sinon.assert.calledWith(spec.paapiParameters, bids, bidderRequest); - }); - it('should leave most things (including promises) untouched', async () => { - params = { - 'p1': 'scalar', - 'p2': Promise.resolve() - } - await runParamHook(); - expect(bidderRequest.paapi.params).to.eql(params); - }); - it('should resolve async PAAPI parameeters', async () => { - params = { - 'resolved': new AsyncPAAPIParam(() => Promise.resolve('value')), - } - await runParamHook(); - expect(bidderRequest.paapi.params).to.eql({ - 'resolved': 'value' - }) - }) - - it('should still call next if the resolution fails', async () => { - params = { - error: new AsyncPAAPIParam(() => Promise.reject(new Error())) - } - await runParamHook(); - sinon.assert.called(next); - expect(bidderRequest.paapi.params).to.not.exist; - }) - }) - }) - - describe('parallel PAAPI auctions', () => { - describe('parallellPaapiProcessing', () => { - let next, spec, bids, bidderRequest, restOfTheArgs, mockConfig, mockAuction, bidsReceived, bidderRequests, adUnitCodes, adUnits; - - beforeEach(() => { - next = sinon.stub(); - spec = { - code: 'mockBidder', - }; - bids = [{ - bidder: 'mockBidder', - bidId: 'bidId', - adUnitCode: 'au', - auctionId: 'aid', - ortb2: { - source: { - tid: 'aid' - }, - }, - mediaTypes: { - banner: { - sizes: [[123, 321]] - } - } - }]; - bidderRequest = { - auctionId: 'aid', - bidderCode: 'mockBidder', - paapi: {enabled: true}, - bids, - ortb2: { - source: { - tid: 'aid' - } - } - }; - restOfTheArgs = [{more: 'args'}]; - mockConfig = { - seller: 'mock.seller', - decisionLogicURL: 'mock.seller/decisionLogic', - interestGroupBuyers: ['mock.buyer'] - } - mockAuction = {}; - bidsReceived = [{adUnitCode: 'au', cpm: 1}]; - adUnits = [{code: 'au'}] - adUnitCodes = ['au']; - bidderRequests = [bidderRequest]; - sandbox.stub(auctionManager.index, 'getAuction').callsFake(() => mockAuction); - sandbox.stub(auctionManager.index, 'getAdUnit').callsFake((req) => bids.find(bid => bid.adUnitCode === req.adUnitCode)) - config.setConfig({paapi: {enabled: true}}); - }); - - afterEach(() => { - sinon.assert.calledWith(next, spec, bids, bidderRequest, ...restOfTheArgs); - config.resetConfig(); - }); - - function startParallel() { - parallelPaapiProcessing(next, spec, bids, bidderRequest, ...restOfTheArgs); - onAuctionInit({auctionId: 'aid'}) - } - - function endAuction() { - events.emit(EVENTS.AUCTION_END, {auctionId: 'aid', bidsReceived, bidderRequests, adUnitCodes, adUnits}) - } - - describe('should have no effect when', () => { - afterEach(() => { - expect(getPAAPIConfig({}, true)).to.eql({au: null}); - }) - it('spec has no buildPAAPIConfigs', () => { - startParallel(); - }); - Object.entries({ - 'returns no configs': () => { spec.buildPAAPIConfigs = sinon.stub().callsFake(() => []); }, - 'throws': () => { spec.buildPAAPIConfigs = sinon.stub().callsFake(() => { throw new Error() }) }, - 'returns too little config': () => { spec.buildPAAPIConfigs = sinon.stub().callsFake(() => [ {bidId: 'bidId', config: {seller: 'mock.seller'}} ]) }, - 'bidder is not paapi enabled': () => { - bidderRequest.paapi.enabled = false; - spec.buildPAAPIConfigs = sinon.stub().callsFake(() => [{config: mockConfig, bidId: 'bidId'}]) - }, - 'paapi module is not enabled': () => { - delete bidderRequest.paapi; - spec.buildPAAPIConfigs = sinon.stub().callsFake(() => [{config: mockConfig, bidId: 'bidId'}]) - }, - 'bidId points to missing bid': () => { spec.buildPAAPIConfigs = sinon.stub().callsFake(() => [{config: mockConfig, bidId: 'missing'}]) } - }).forEach(([t, setup]) => { - it(`buildPAAPIConfigs ${t}`, () => { - setup(); - startParallel(); - }); - }); - }); - - function resolveConfig(auctionConfig) { - return Promise.all( - Object.entries(auctionConfig) - .map(([key, value]) => Promise.resolve(value).then(value => [key, value])) - ).then(result => Object.fromEntries(result)) - } - - describe('when buildPAAPIConfigs returns valid config', () => { - let builtCfg; - beforeEach(() => { - builtCfg = [{bidId: 'bidId', config: mockConfig}]; - spec.buildPAAPIConfigs = sinon.stub().callsFake(() => builtCfg); - }); - - it('should make async config available from getPAAPIConfig', () => { - startParallel(); - const actual = getPAAPIConfig(); - const promises = Object.fromEntries(ASYNC_SIGNALS.map(signal => [signal, sinon.match((arg) => arg instanceof Promise)])) - sinon.assert.match(actual, { - au: sinon.match({ - ...promises, - requestedSize: { - width: 123, - height: 321 - }, - componentAuctions: [ - sinon.match({ - ...mockConfig, - ...promises, - requestedSize: { - width: 123, - height: 321 - } - }) - ] - }) - }); - }); - - it('should work when called multiple times for the same auction', () => { - startParallel(); - spec.buildPAAPIConfigs = sinon.stub().callsFake(() => []); - startParallel(); - expect(getPAAPIConfig().au.componentAuctions.length).to.eql(1); - }); - - it('should hide TIDs from buildPAAPIConfigs', () => { - config.setConfig({enableTIDs: false}); - startParallel(); - sinon.assert.calledWith( - spec.buildPAAPIConfigs, - sinon.match(bidRequests => bidRequests.every(req => req.auctionId == null)), - sinon.match(bidderRequest => bidderRequest.auctionId == null) - ); - }); - - it('should show TIDs when enabled', () => { - config.setConfig({enableTIDs: true}); - startParallel(); - sinon.assert.calledWith( - spec.buildPAAPIConfigs, - sinon.match(bidRequests => bidRequests.every(req => req.auctionId === 'aid')), - sinon.match(bidderRequest => bidderRequest.auctionId === 'aid') - ) - }) - - it('should respect requestedSize from adapter', () => { - mockConfig.requestedSize = {width: 1, height: 2}; - startParallel(); - sinon.assert.match(getPAAPIConfig().au, { - requestedSize: { - width: 123, - height: 321 - }, - componentAuctions: [sinon.match({ - requestedSize: { - width: 1, - height: 2 - } - })] - }) - }) - - it('should not accept multiple partial configs for the same bid/seller', () => { - builtCfg.push(builtCfg[0]) - startParallel(); - expect(getPAAPIConfig().au.componentAuctions.length).to.eql(1); - }); - it('should resolve top level config with auction signals', async () => { - startParallel(); - let config = getPAAPIConfig().au; - endAuction(); - config = await resolveConfig(config); - sinon.assert.match(config, { - auctionSignals: { - prebid: {bidfloor: 1} - } - }) - }); - - describe('when adapter returns the rest of auction config', () => { - let configRemainder; - beforeEach(() => { - configRemainder = { - ...Object.fromEntries(ASYNC_SIGNALS.map(signal => [signal, {type: signal}])), - seller: 'mock.seller' - }; - }) - function returnRemainder() { - addPaapiConfigHook(sinon.stub(), bids[0], {config: configRemainder}); - } - it('should resolve component configs with values returned by adapters', async () => { - startParallel(); - let config = getPAAPIConfig().au.componentAuctions[0]; - returnRemainder(); - endAuction(); - config = await resolveConfig(config); - sinon.assert.match(config, configRemainder); - }); - - it('should pick first config that matches bidId/seller', async () => { - startParallel(); - let config = getPAAPIConfig().au.componentAuctions[0]; - returnRemainder(); - const expectedSignals = {...configRemainder}; - configRemainder = { - ...configRemainder, - auctionSignals: { - this: 'should be ignored' - } - } - returnRemainder(); - endAuction(); - config = await resolveConfig(config); - sinon.assert.match(config, expectedSignals); - }); - - describe('should default to values returned from buildPAAPIConfigs when interpretResponse does not return', () => { - beforeEach(() => { - ASYNC_SIGNALS.forEach(signal => mockConfig[signal] = {default: signal}) - }); - Object.entries({ - 'returns no matching config'() { - }, - 'does not include values in response'() { - configRemainder = {}; - returnRemainder(); - } - }).forEach(([t, postResponse]) => { - it(t, async () => { - startParallel(); - let config = getPAAPIConfig().au.componentAuctions[0]; - postResponse(); - endAuction(); - config = await resolveConfig(config); - sinon.assert.match(config, mockConfig); - }); - }); - }); - - it('should resolve to undefined when no value is available', async () => { - startParallel(); - let config = getPAAPIConfig().au.componentAuctions[0]; - delete configRemainder.sellerSignals; - returnRemainder(); - endAuction(); - config = await resolveConfig(config); - expect(config.sellerSignals).to.be.undefined; - }); - - [ - { - start: {t: 'scalar', value: 'str'}, - end: {t: 'array', value: ['abc']}, - should: {t: 'array', value: ['abc']} - }, - { - start: {t: 'object', value: {a: 'b'}}, - end: {t: 'scalar', value: 'abc'}, - should: {t: 'scalar', value: 'abc'} - }, - { - start: {t: 'object', value: {outer: {inner: 'val'}}}, - end: {t: 'object', value: {outer: {other: 'val'}}}, - should: {t: 'merge', value: {outer: {inner: 'val', other: 'val'}}} - } - ].forEach(({start, end, should}) => { - it(`when buildPAAPIConfigs returns ${start.t}, interpretResponse return ${end.t}, promise should resolve to ${should.t}`, async () => { - mockConfig.sellerSignals = start.value - startParallel(); - let config = getPAAPIConfig().au.componentAuctions[0]; - configRemainder.sellerSignals = end.value; - returnRemainder(); - endAuction(); - config = await resolveConfig(config); - expect(config.sellerSignals).to.eql(should.value); - }) - }) - - it('should make extra configs available', async () => { - startParallel(); - returnRemainder(); - configRemainder = {...configRemainder, seller: 'other.seller'}; - returnRemainder(); - endAuction(); - let configs = getPAAPIConfig().au.componentAuctions; - configs = [await resolveConfig(configs[0]), configs[1]]; - expect(configs.map(cfg => cfg.seller)).to.eql(['mock.seller', 'other.seller']); - }); - - describe('submodule\'s onAuctionConfig', () => { - let onAuctionConfig; - beforeEach(() => { - onAuctionConfig = sinon.stub(); - registerSubmodule({onAuctionConfig}) - }); - - Object.entries({ - 'parallel=true, some configs deferred': { - setup() { - config.mergeConfig({paapi: {parallel: true}}) - }, - delayed: false, - }, - 'parallel=true, no deferred configs': { - setup() { - config.mergeConfig({paapi: {parallel: true}}); - spec.buildPAAPIConfigs = sinon.stub().callsFake(() => []); - }, - delayed: true - }, - 'parallel=false, some configs deferred': { - setup() { - config.mergeConfig({paapi: {parallel: false}}) - }, - delayed: true - } - }).forEach(([t, {setup, delayed}]) => { - describe(`when ${t}`, () => { - beforeEach(() => { - mockAuction.requestsDone = Promise.resolve(); - setup(); - }); - - function expectInvoked(shouldBeInvoked) { - if (shouldBeInvoked) { - sinon.assert.calledWith(onAuctionConfig, 'aid', sinon.match(arg => arg.au.componentAuctions[0].seller === 'mock.seller')); - } else { - sinon.assert.notCalled(onAuctionConfig); - } - } - - it(`should invoke onAuctionConfig when ${delayed ? 'auction ends' : 'auction requests have started'}`, async () => { - startParallel(); - await mockAuction.requestsDone; - expectInvoked(!delayed); - onAuctionConfig.resetHistory(); - returnRemainder(); - endAuction(); - expectInvoked(delayed); - }) - }) - }) - }) - }); - }); - describe('when buildPAAPIConfigs returns igb', () => { - let builtCfg, igb, auctionConfig; - beforeEach(() => { - igb = {origin: 'mock.buyer'} - builtCfg = [{bidId: 'bidId', igb}]; - spec.buildPAAPIConfigs = sinon.stub().callsFake(() => builtCfg); - auctionConfig = { - seller: 'mock.seller', - decisionLogicUrl: 'mock.seller/decisionLogic' - } - config.mergeConfig({ - paapi: { - componentSeller: { - auctionConfig - } - } - }) - bidderRequest.paapi.componentSeller = true; - }); - Object.entries({ - 'componentSeller not configured'() { - bidderRequest.paapi.componentSeller = false; - }, - 'buildPAAPIconfig returns nothing'() { - builtCfg = [] - }, - 'returned igb is not valid'() { - builtCfg = [{bidId: 'bidId', igb: {}}]; - } - }).forEach(([t, setup]) => { - it(`should have no effect when ${t}`, () => { - setup(); - startParallel(); - expect(getPAAPIConfig()).to.eql({}); - }) - }) - - describe('when component seller is set up', () => { - it('should generate a deferred auctionConfig', () => { - startParallel(); - sinon.assert.match(getPAAPIConfig().au.componentAuctions[0], { - ...auctionConfig, - interestGroupBuyers: ['mock.buyer'], - }) - }); - - it('should use signal values from componentSeller.auctionConfig', async () => { - auctionConfig.auctionSignals = {test: 'signal'}; - config.mergeConfig({ - paapi: {componentSeller: {auctionConfig}} - }) - startParallel(); - endAuction(); - const cfg = await resolveConfig(getPAAPIConfig().au.componentAuctions[0]); - sinon.assert.match(cfg.auctionSignals, auctionConfig.auctionSignals); - }) - - it('should collate buyers', () => { - startParallel(); - startParallel(); - sinon.assert.match(getPAAPIConfig().au.componentAuctions[0], { - interestGroupBuyers: ['mock.buyer'] - }); - }); - - function returnIgb(igb) { - addPaapiConfigHook(sinon.stub(), bids[0], {igb}); - } - - it('should resolve to values from interpretResponse as well as buildPAAPIConfigs', async () => { - igb.cur = 'cur'; - igb.pbs = {over: 'ridden'} - startParallel(); - let cfg = getPAAPIConfig().au.componentAuctions[0]; - returnIgb({ - origin: 'mock.buyer', - pbs: {some: 'signal'} - }); - endAuction(); - cfg = await resolveConfig(cfg); - sinon.assert.match(cfg, { - perBuyerSignals: { - [igb.origin]: {some: 'signal'}, - }, - perBuyerCurrencies: { - [igb.origin]: 'cur' - } - }) - }); - - it('should not overwrite config once resolved', () => { - startParallel(); - returnIgb({ - origin: 'mock.buyer', - }); - endAuction(); - const cfg = getPAAPIConfig().au; - sinon.assert.match(cfg, Object.fromEntries(ASYNC_SIGNALS.map(signal => [signal, sinon.match(arg => arg instanceof Promise)]))) - }) - - it('can resolve multiple igbs', async () => { - igb.cur = 'cur1'; - startParallel(); - spec.code = 'other'; - igb.origin = 'other.buyer' - igb.cur = 'cur2' - startParallel(); - let cfg = getPAAPIConfig().au.componentAuctions[0]; - returnIgb({ - origin: 'mock.buyer', - pbs: {signal: 1} - }); - returnIgb({ - origin: 'other.buyer', - pbs: {signal: 2} - }); - endAuction(); - cfg = await resolveConfig(cfg); - sinon.assert.match(cfg, { - perBuyerSignals: { - 'mock.buyer': {signal: 1}, - 'other.buyer': {signal: 2} - }, - perBuyerCurrencies: { - 'mock.buyer': 'cur1', - 'other.buyer': 'cur2' - } - }) - }) - - function startMultiple() { - startParallel(); - spec.code = 'other'; - igb.origin = 'other.buyer' - startParallel(); - } - - describe('when using separateAuctions=false', () => { - beforeEach(() => { - config.mergeConfig({ - paapi: { - componentSeller: { - separateAuctions: false - } - } - }) - }); - - it('should merge igb from different specs into a single auction config', () => { - startMultiple(); - sinon.assert.match(getPAAPIConfig().au.componentAuctions[0], { - interestGroupBuyers: ['mock.buyer', 'other.buyer'] - }); - }); - }) - - describe('when using separateAuctions=true', () => { - beforeEach(() => { - config.mergeConfig({ - paapi: { - componentSeller: { - separateAuctions: true - } - } - }) - }); - it('should generate an auction config for each bidder', () => { - startMultiple(); - const components = getPAAPIConfig().au.componentAuctions; - sinon.assert.match(components[0], { - interestGroupBuyers: ['mock.buyer'] - }) - sinon.assert.match(components[1], { - interestGroupBuyers: ['other.buyer'] - }) - }) - }) - }) - }) - }); - }); - - describe('ortb processors for fledge', () => { - it('imp.ext.ae should be removed if fledge is not enabled', () => { - const imp = {ext: {ae: 1, igs: {}}}; - setImpExtAe(imp, {}, {bidderRequest: {}}); - expect(imp.ext.ae).to.not.exist; - expect(imp.ext.igs).to.not.exist; - }); - it('imp.ext.ae should be left intact if fledge is enabled', () => { - const imp = {ext: {ae: 2, igs: {biddable: 0}}}; - setImpExtAe(imp, {}, {bidderRequest: {paapi: {enabled: true}}}); - expect(imp.ext).to.eql({ - ae: 2, - igs: { - biddable: 0 - } - }); - }); - - describe('response parsing', () => { - function generateImpCtx(fledgeFlags) { - return Object.fromEntries(Object.entries(fledgeFlags).map(([impid, fledgeEnabled]) => [impid, {imp: {ext: {ae: fledgeEnabled}}}])); - } - - function extractResult(type, ctx) { - return Object.fromEntries( - Object.entries(ctx) - .map(([impid, ctx]) => [impid, ctx.paapiConfigs?.map(cfg => cfg[type].id)]) - .filter(([_, val]) => val != null) - ); - } - - Object.entries({ - 'parseExtPrebidFledge': { - parser: parseExtPrebidFledge, - responses: { - 'ext.prebid.fledge'(configs) { - return { - ext: { - prebid: { - fledge: { - auctionconfigs: configs - } - } - } - }; - }, - } - }, - 'parseExtIgi': { - parser: parseExtIgi, - responses: { - 'ext.igi.igs'(configs) { - return { - ext: { - igi: [{ - igs: configs - }] - } - }; - }, - 'ext.igi.igs with impid on igi'(configs) { - return { - ext: { - igi: configs.map(cfg => { - const impid = cfg.impid; - delete cfg.impid; - return { - impid, - igs: [cfg] - }; - }) - } - }; - }, - 'ext.igi.igs with conflicting impid'(configs) { - return { - ext: { - igi: [{ - impid: 'conflict', - igs: configs - }] - } - }; - } - } - } - }).forEach(([t, {parser, responses}]) => { - describe(t, () => { - Object.entries(responses).forEach(([t, packageConfigs]) => { - describe(`when response uses ${t}`, () => { - function generateCfg(impid, ...ids) { - return ids.map((id) => ({impid, config: {id}})); - } - - it('should collect auction configs by imp', () => { - const ctx = { - impContext: generateImpCtx({e1: 1, e2: 1, d1: 0}) - }; - const resp = packageConfigs( - generateCfg('e1', 1, 2, 3) - .concat(generateCfg('e2', 4) - .concat(generateCfg('d1', 5, 6))) - ); - parser({}, resp, ctx); - expect(extractResult('config', ctx.impContext)).to.eql({ - e1: [1, 2, 3], - e2: [4], - }); - }); - it('should not choke if fledge config references unknown imp', () => { - const ctx = {impContext: generateImpCtx({i: 1})}; - const resp = packageConfigs(generateCfg('unknown', 1)); - parser({}, resp, ctx); - expect(extractResult('config', ctx.impContext)).to.eql({}); - }); - }); - }); - }); - }); - - describe('response ext.igi.igb', () => { - it('should collect igb by imp', () => { - const ctx = { - impContext: generateImpCtx({e1: 1, e2: 1, d1: 0}) - }; - const resp = { - ext: { - igi: [ - { - impid: 'e1', - igb: [ - {id: 1}, - {id: 2} - ] - }, - { - impid: 'e2', - igb: [ - {id: 3} - ] - }, - { - impid: 'd1', - igb: [ - {id: 4} - ] - } - ] - } - }; - parseExtIgi({}, resp, ctx); - expect(extractResult('igb', ctx.impContext)).to.eql({ - e1: [1, 2], - e2: [3], - }); - }); - }); - }); - - describe('setResponsePaapiConfigs', () => { - it('should set paapi configs/igb paired with their corresponding bid id', () => { - const ctx = { - impContext: { - 1: { - bidRequest: {bidId: 'bid1'}, - paapiConfigs: [{config: {id: 1}}, {config: {id: 2}}] - }, - 2: { - bidRequest: {bidId: 'bid2'}, - paapiConfigs: [{config: {id: 3}}] - }, - 3: { - bidRequest: {bidId: 'bid3'} - }, - 4: { - bidRequest: {bidId: 'bid1'}, - paapiConfigs: [{igb: {id: 4}}] - } - } - }; - const resp = {}; - setResponsePaapiConfigs(resp, {}, ctx); - expect(resp.paapi).to.eql([ - {bidId: 'bid1', config: {id: 1}}, - {bidId: 'bid1', config: {id: 2}}, - {bidId: 'bid2', config: {id: 3}}, - {bidId: 'bid1', igb: {id: 4}} - ]); - }); - it('should not set paapi if no config or igb exists', () => { - const resp = {}; - setResponsePaapiConfigs(resp, {}, { - impContext: { - 1: { - paapiConfigs: [] - }, - 2: {} - } - }); - expect(resp).to.eql({}); - }); - }); - }); -}); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 595b95c6db8..a6deca70a57 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -23,17 +23,15 @@ import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; import 'modules/consentManagementGpp.js'; -import 'modules/paapi.js'; import * as redactor from 'src/activities/redactor.js'; import * as activityRules from 'src/activities/rules.js'; import {hook} from '../../../src/hook.js'; import {decorateAdUnitsWithNativeParams} from '../../../src/native.js'; import {auctionManager} from '../../../src/auctionManager.js'; import {stubAuctionIndex} from '../../helpers/indexStub.js'; -import {addPaapiConfig, registerBidder} from 'src/adapters/bidderFactory.js'; +import {registerBidder} from 'src/adapters/bidderFactory.js'; import {getGlobal} from '../../../src/prebidGlobal.js'; import {addFPDToBidderRequest} from '../../helpers/fpd.js'; -import {deepSetValue} from '../../../src/utils.js'; import {ACTIVITY_TRANSMIT_UFPD} from '../../../src/activities/activities.js'; import {MODULE_TYPE_PREBID} from '../../../src/activities/modules.js'; import { @@ -3734,108 +3732,6 @@ describe('S2S Adapter', function () { }); }); }); - describe('when the response contains ext.prebid.fledge', () => { - const AU = 'div-gpt-ad-1460505748561-0'; - const FLEDGE_RESP = { - ext: { - prebid: { - fledge: { - auctionconfigs: [ - { - impid: AU, - bidder: 'appnexus', - config: { - id: 1 - } - }, - { - impid: AU, - bidder: 'other', - config: { - id: 2 - } - } - ] - } - } - } - } - - let fledgeStub, request, bidderRequests; - - function fledgeHook(next, ...args) { - fledgeStub(...args); - } - - before(() => { - addPaapiConfig.before(fledgeHook); - }); - - after(() => { - addPaapiConfig.getHooks({hook: fledgeHook}).remove(); - }) - - beforeEach(function () { - fledgeStub = sinon.stub(); - config.setConfig({ - s2sConfig: CONFIG, - }); - bidderRequests = deepClone(BID_REQUESTS); - bidderRequests.forEach(req => { - Object.assign(req, { - paapi: { - enabled: true - }, - ortb2: { - fpd: 1 - } - }) - req.bids.forEach(bid => { - Object.assign(bid, { - ortb2Imp: { - fpd: 2, - } - }) - }) - }); - request = deepClone(REQUEST); - request.ad_units.forEach(au => deepSetValue(au, 'ortb2Imp.ext.ae', 1)); - }); - - function expectFledgeCalls() { - const auctionId = bidderRequests[0].auctionId; - sinon.assert.calledWith(fledgeStub, sinon.match({auctionId, adUnitCode: AU, ortb2: bidderRequests[0].ortb2, ortb2Imp: bidderRequests[0].bids[0].ortb2Imp}), sinon.match({config: {id: 1}})) - sinon.assert.calledWith(fledgeStub, sinon.match({auctionId, adUnitCode: AU, ortb2: undefined, ortb2Imp: undefined}), sinon.match({config: {id: 2}})) - } - - it('calls addPaapiConfig alongside addBidResponse', function () { - adapter.callBids(request, bidderRequests, addBidResponse, done, ajax); - server.requests[0].respond(200, {}, JSON.stringify(mergeDeep({}, RESPONSE_OPENRTB, FLEDGE_RESP))); - expect(addBidResponse.called).to.be.true; - expectFledgeCalls(); - }); - - it('calls addPaapiConfig when there is no bid in the response', () => { - adapter.callBids(request, bidderRequests, addBidResponse, done, ajax); - server.requests[0].respond(200, {}, JSON.stringify(FLEDGE_RESP)); - expect(addBidResponse.called).to.be.false; - expectFledgeCalls(); - }); - - it('wraps call in runWithBidder', () => { - let fail = false; - fledgeStub.callsFake(({bidder}) => { - try { - expect(bidder).to.exist.and.to.eql(config.getCurrentBidder()); - } catch (e) { - fail = true; - } - }); - adapter.callBids(request, bidderRequests, addBidResponse, done, ajax); - server.requests[0].respond(200, {}, JSON.stringify(FLEDGE_RESP)); - expect(fail).to.be.false; - }) - }); }); describe('bid won events', function () { diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index 56f238ff1ba..26e9e57da7c 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -963,22 +963,6 @@ describe('sharethrough adapter spec', function () { }); }); - describe('fledge', () => { - it('should attach "ae" as a property to the request if 1) fledge auctions are enabled, and 2) request is display (only supporting display for now)', () => { - // ASSEMBLE - const EXPECTED_AE_VALUE = 1; - - // ACT - bidderRequest.paapi = { enabled: true }; - const builtRequests = spec.buildRequests(bidRequests, bidderRequest); - const ACTUAL_AE_VALUE = builtRequests[0].data.imp[0].ext.ae; - - // ASSERT - expect(ACTUAL_AE_VALUE).to.equal(EXPECTED_AE_VALUE); - expect(builtRequests[1].data.imp[0].ext.ae).to.be.undefined; - }); - }); - describe('isEqtvTest', () => { it('should set publisher id if equativNetworkId param is present', () => { const builtRequest = spec.buildRequests(multiImpBidRequests, bidderRequest)[0]; @@ -1221,53 +1205,6 @@ describe('sharethrough adapter spec', function () { const resp = spec.interpretResponse(response, request)[0]; expect(resp.ttl).to.equal(360); }); - - it('should return correct properties when fledgeAuctionEnabled is true and isEqtvTest is false', () => { - request = spec.buildRequests(bidRequests, bidderRequest)[0]; - response = { - body: { - ext: { - auctionConfigs: { - key: 'value', - }, - }, - seatbid: [ - { - bid: [ - { - id: 'abcd1234', - impid: 'aaaabbbbccccdd', - w: 300, - h: 250, - price: 42, - crid: 'creative', - dealid: 'deal', - adomain: ['domain.com'], - adm: 'markup', - exp: -1, - }, - { - id: 'efgh5678', - impid: 'ddeeeeffffgggg', - w: 300, - h: 250, - price: 42, - crid: 'creative', - dealid: 'deal', - adomain: ['domain.com'], - adm: 'markup', - exp: -1, - }, - ], - }, - ], - }, - }; - - const resp = spec.interpretResponse(response, request); - expect(resp.bids.length).to.equal(2); - expect(resp.paapi).to.deep.equal({ key: 'value' }); - }); }); describe('video', () => { diff --git a/test/spec/modules/sspBCBidAdapter_spec.js b/test/spec/modules/sspBCBidAdapter_spec.js index 53261a3a734..5181f0ef02a 100644 --- a/test/spec/modules/sspBCBidAdapter_spec.js +++ b/test/spec/modules/sspBCBidAdapter_spec.js @@ -747,13 +747,6 @@ describe('SSPBC adapter', function () { expect(resultIncorrect.length).to.equal(0); }); - - it('should response with fledge auction configs', function () { - const { bids, fledgeAuctionConfigs } = spec.interpretResponse(serverResponsePaapi, requestSingle); - - expect(bids.length).to.equal(1); - expect(fledgeAuctionConfigs.length).to.equal(1); - }); }); describe('getUserSyncs', function () { diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 8c23be4bcd0..87c1a200747 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -1234,181 +1234,6 @@ describe('Taboola Adapter', function () { expect(res[0].meta.dchain).to.deep.equal(expectedDchainRes) }); - it('should interpret display response with PA', function () { - const [bid] = serverResponse.body.seatbid[0].bid; - - const expectedRes = { - 'bids': [ - { - requestId: request.bids[0].bidId, - seatBidId: serverResponse.body.seatbid[0].bid[0].id, - cpm: bid.price, - creativeId: bid.crid, - creative_id: bid.crid, - ttl: 60, - netRevenue: true, - currency: serverResponse.body.cur, - mediaType: 'banner', - ad: bid.adm, - width: bid.w, - height: bid.h, - nurl: 'http://win.example.com/', - meta: { - 'advertiserDomains': bid.adomain - }, - } - ], - 'paapi': [ - { - 'impId': request.bids[0].bidId, - 'config': { - 'seller': 'pa.taboola.com', - 'resolveToConfig': false, - 'sellerSignals': {}, - 'sellerTimeout': 100, - 'perBuyerSignals': { - 'https://pa.taboola.com': { - 'country': 'US', - 'route': 'AM', - 'cct': [ - 0.02241223, - -0.8686833, - 0.96153843 - ], - 'vct': '-1967600173', - 'ccv': null, - 'ect': [ - -0.13584597, - 2.5825605 - ], - 'ri': '100fb73d4064bc', - 'vcv': '165229814', - 'ecv': [ - -0.39882636, - -0.05216012 - ], - 'publisher': 'test-headerbidding', - 'platform': 'DESK' - } - }, - 'auctionSignals': {}, - 'decisionLogicUrl': 'https://pa.taboola.com/score/decisionLogic.js', - 'interestGroupBuyers': [ - 'https://pa.taboola.com' - ], - 'perBuyerTimeouts': { - '*': 50 - } - } - } - ] - } - - const res = spec.interpretResponse(serverResponseWithPa, request) - expect(res).to.deep.equal(expectedRes) - }); - - it('should interpret display response with partialPA', function () { - const [bid] = serverResponse.body.seatbid[0].bid; - const expectedRes = { - 'bids': [ - { - requestId: request.bids[0].bidId, - seatBidId: serverResponse.body.seatbid[0].bid[0].id, - cpm: bid.price, - creativeId: bid.crid, - creative_id: bid.crid, - ttl: 60, - netRevenue: true, - currency: serverResponse.body.cur, - mediaType: 'banner', - ad: bid.adm, - width: bid.w, - height: bid.h, - nurl: 'http://win.example.com/', - meta: { - 'advertiserDomains': bid.adomain - }, - } - ], - 'paapi': [ - { - 'impId': request.bids[0].bidId, - 'config': { - 'seller': undefined, - 'resolveToConfig': undefined, - 'sellerSignals': {}, - 'sellerTimeout': undefined, - 'perBuyerSignals': {}, - 'auctionSignals': {}, - 'decisionLogicUrl': undefined, - 'interestGroupBuyers': undefined, - 'perBuyerTimeouts': undefined - } - } - ] - } - - const res = spec.interpretResponse(serverResponseWithPartialPa, request) - expect(res).to.deep.equal(expectedRes) - }); - - it('should interpret display response with wrong PA', function () { - const [bid] = serverResponse.body.seatbid[0].bid; - - const expectedRes = [ - { - requestId: request.bids[0].bidId, - seatBidId: serverResponse.body.seatbid[0].bid[0].id, - cpm: bid.price, - creativeId: bid.crid, - creative_id: bid.crid, - ttl: 60, - netRevenue: true, - currency: serverResponse.body.cur, - mediaType: 'banner', - ad: bid.adm, - width: bid.w, - height: bid.h, - nurl: 'http://win.example.com/', - meta: { - 'advertiserDomains': bid.adomain - }, - } - ] - - const res = spec.interpretResponse(serverResponseWithWrongPa, request) - expect(res).to.deep.equal(expectedRes) - }); - - it('should interpret display response with empty igbid wrong PA', function () { - const [bid] = serverResponse.body.seatbid[0].bid; - - const expectedRes = [ - { - requestId: request.bids[0].bidId, - seatBidId: serverResponse.body.seatbid[0].bid[0].id, - cpm: bid.price, - creativeId: bid.crid, - creative_id: bid.crid, - ttl: 60, - netRevenue: true, - currency: serverResponse.body.cur, - mediaType: 'banner', - ad: bid.adm, - width: bid.w, - height: bid.h, - nurl: 'http://win.example.com/', - meta: { - 'advertiserDomains': bid.adomain - }, - } - ] - - const res = spec.interpretResponse(serverResponseWithEmptyIgbidWIthWrongPa, request) - expect(res).to.deep.equal(expectedRes) - }); - it('should set the correct ttl form the response', function () { // set exp-ttl to be 125 const [bid] = serverResponse.body.seatbid[0].bid; diff --git a/test/spec/modules/topLevelPaapi_spec.js b/test/spec/modules/topLevelPaapi_spec.js deleted file mode 100644 index c08a14f899f..00000000000 --- a/test/spec/modules/topLevelPaapi_spec.js +++ /dev/null @@ -1,515 +0,0 @@ -import { - addPaapiConfigHook, - getPAAPIConfig, - registerSubmodule, - reset as resetPaapi -} from '../../../modules/paapi.js'; -import {config} from 'src/config.js'; -import {BID_STATUS, EVENTS} from 'src/constants.js'; -import * as events from 'src/events.js'; -import { - getPaapiAdId, - getPAAPIBids, - getRenderingDataHook, markWinningBidHook, - parsePaapiAdId, - parsePaapiSize, resizeCreativeHook, - topLevelPAAPI -} from '../../../modules/topLevelPaapi.js'; -import {auctionManager} from '../../../src/auctionManager.js'; -import {expect} from 'chai/index.js'; -import {getBidToRender} from '../../../src/adRendering.js'; - -describe('topLevelPaapi', () => { - let sandbox, auctionConfig, next, auctionId, auctions; - before(() => { - resetPaapi(); - }); - beforeEach(() => { - registerSubmodule(topLevelPAAPI); - }); - afterEach(() => { - resetPaapi(); - }); - beforeEach(() => { - sandbox = sinon.createSandbox(); - auctions = {}; - sandbox.stub(auctionManager.index, 'getAuction').callsFake(({auctionId}) => auctions[auctionId]?.auction); - next = sinon.stub(); - auctionId = 'auct'; - auctionConfig = { - seller: 'mock.seller' - }; - config.setConfig({ - paapi: { - enabled: true, - defaultForSlots: 1 - } - }); - }); - afterEach(() => { - config.resetConfig(); - sandbox.restore(); - }); - - function addPaapiConfig(adUnitCode, auctionConfig, _auctionId = auctionId) { - let auction = auctions[_auctionId]; - if (!auction) { - auction = auctions[_auctionId] = { - auction: {}, - adUnits: {} - }; - } - if (!auction.adUnits.hasOwnProperty(adUnitCode)) { - auction.adUnits[adUnitCode] = { - code: adUnitCode, - ortb2Imp: { - ext: { - paapi: { - requestedSize: { - width: 123, - height: 321 - } - } - } - } - }; - } - addPaapiConfigHook(next, {adUnitCode, auctionId: _auctionId}, { - config: { - ...auctionConfig, - auctionId: _auctionId, - adUnitCode - } - }); - } - - function endAuctions() { - Object.entries(auctions).forEach(([auctionId, {adUnits}]) => { - events.emit(EVENTS.AUCTION_END, {auctionId, adUnitCodes: Object.keys(adUnits), adUnits: Object.values(adUnits)}); - }); - } - - describe('when configured', () => { - let auctionConfig; - beforeEach(() => { - auctionConfig = { - seller: 'top.seller', - decisionLogicURL: 'https://top.seller/decision-logic.js' - }; - config.mergeConfig({ - paapi: { - topLevelSeller: { - auctionConfig, - autorun: false - } - } - }); - }); - - it('should augment config returned by getPAAPIConfig', () => { - addPaapiConfig('au', auctionConfig); - endAuctions(); - sinon.assert.match(getPAAPIConfig().au, auctionConfig); - }); - - it('should not choke if auction config is not defined', () => { - const cfg = config.getConfig('paapi'); - delete cfg.topLevelSeller.auctionConfig; - config.setConfig(cfg); - addPaapiConfig('au', auctionConfig); - endAuctions(); - expect(getPAAPIConfig().au.componentAuctions).to.exist; - }); - - it('should default resolveToConfig: false', () => { - addPaapiConfig('au', auctionConfig); - endAuctions(); - expect(getPAAPIConfig()['au'].resolveToConfig).to.eql(false); - }); - - describe('when autoRun is set', () => { - let origRaa; - beforeEach(() => { - origRaa = navigator.runAdAuction; - navigator.runAdAuction = sinon.stub(); - }); - afterEach(() => { - navigator.runAdAuction = origRaa; - }); - - it('should start auctions automatically, when autoRun is set', () => { - config.mergeConfig({ - paapi: { - topLevelSeller: { - autorun: true - } - } - }) - addPaapiConfig('au', auctionConfig); - endAuctions(); - sinon.assert.called(navigator.runAdAuction); - }); - }); - - describe('getPAAPIBids', () => { - Object.entries({ - 'a string URN': { - pack: (val) => val, - unpack: (urn) => ({urn}), - canRender: true, - }, - 'a frameConfig object': { - pack: (val) => ({val}), - unpack: (val) => ({frameConfig: {val}}), - canRender: false - } - }).forEach(([t, {pack, unpack, canRender}]) => { - describe(`when runAdAuction returns ${t}`, () => { - let raa; - beforeEach(() => { - raa = sinon.stub().callsFake((cfg) => { - const {auctionId, adUnitCode} = cfg.componentAuctions[0]; - return Promise.resolve(pack(`raa-${adUnitCode}-${auctionId}`)); - }); - }); - - function getBids(filters) { - return getPAAPIBids(filters, raa); - } - - function expectBids(actual, expected) { - expect(Object.keys(actual)).to.eql(Object.keys(expected)); - Object.entries(expected).forEach(([au, val]) => { - sinon.assert.match(actual[au], val == null ? val : { - adId: sinon.match(val => parsePaapiAdId(val)[1] === au), - width: 123, - height: 321, - source: 'paapi', - ...unpack(val) - }); - }); - } - - describe('with one auction config', () => { - beforeEach(() => { - addPaapiConfig('au', auctionConfig, 'auct'); - endAuctions(); - }); - it('should resolve to raa result', () => { - return getBids({adUnitCode: 'au', auctionId}).then(result => { - sinon.assert.calledOnce(raa); - sinon.assert.calledWith( - raa, - sinon.match({ - ...auctionConfig, - componentAuctions: sinon.match([ - sinon.match({ - ...auctionConfig, - auctionId: 'auct', - adUnitCode: 'au' - }) - ]) - }) - ); - expectBids(result, {au: 'raa-au-auct'}); - }); - }); - - Object.entries({ - 'returns null': () => Promise.resolve(), - 'throws': () => { throw new Error() }, - 'rejects': () => Promise.reject(new Error()) - }).forEach(([t, behavior]) => { - it('should resolve to null when runAdAuction returns null', () => { - raa = sinon.stub().callsFake(behavior); - return getBids({adUnitCode: 'au', auctionId: 'auct'}).then(result => { - expectBids(result, {au: null}); - }); - }); - }) - - it('should resolve to the same result when called again', () => { - getBids({adUnitCode: 'au', auctionId}); - return getBids({adUnitCode: 'au', auctionId: 'auct'}).then(result => { - sinon.assert.calledOnce(raa); - expectBids(result, {au: 'raa-au-auct'}); - }); - }); - - describe('events', () => { - beforeEach(() => { - sandbox.stub(events, 'emit'); - }); - it('should fire PAAPI_RUN_AUCTION', () => { - return Promise.all([ - getBids({adUnitCode: 'au', auctionId}), - getBids({adUnitCode: 'other', auctionId}) - ]).then(() => { - sinon.assert.calledWith(events.emit, EVENTS.RUN_PAAPI_AUCTION, { - adUnitCode: 'au', - auctionId, - auctionConfig: sinon.match(auctionConfig) - }); - sinon.assert.neverCalledWith(events.emit, EVENTS.RUN_PAAPI_AUCTION, { - adUnitCode: 'other' - }); - }); - }); - it('should fire PAAPI_BID', () => { - return getBids({adUnitCode: 'au', auctionId}).then(() => { - sinon.assert.calledWith(events.emit, EVENTS.PAAPI_BID, sinon.match({ - ...unpack('raa-au-auct'), - adUnitCode: 'au', - auctionId: 'auct' - })); - }); - }); - it('should fire PAAPI_NO_BID', () => { - raa = sinon.stub().callsFake(() => Promise.resolve(null)); - return getBids({adUnitCode: 'au', auctionId}).then(() => { - sinon.assert.calledWith(events.emit, EVENTS.PAAPI_NO_BID, sinon.match({ - adUnitCode: 'au', - auctionId: 'auct' - })); - }); - }); - - it('should fire PAAPI_ERROR', () => { - raa = sinon.stub().callsFake(() => Promise.reject(new Error('message'))); - return getBids({adUnitCode: 'au', auctionId}).then(res => { - expect(res).to.eql({au: null}); - sinon.assert.calledWith(events.emit, EVENTS.PAAPI_ERROR, sinon.match({ - adUnitCode: 'au', - auctionId: 'auct', - error: sinon.match({message: 'message'}) - })); - }); - }); - }); - - function getBidToRenderPm(adId, forRender = true) { - return new Promise((resolve) => getBidToRender(adId, forRender, resolve)); - } - - it('should hook into getBidToRender', () => { - return getBids({adUnitCode: 'au', auctionId}).then(res => { - return getBidToRenderPm(res.au.adId).then(bidToRender => [res.au, bidToRender]) - }).then(([paapiBid, bidToRender]) => { - if (canRender) { - expect(bidToRender).to.eql(paapiBid) - } else { - expect(bidToRender).to.not.exist; - } - }); - }); - - describe('when overrideWinner is set', () => { - let mockContextual; - beforeEach(() => { - mockContextual = { - adId: 'mock', - adUnitCode: 'au' - } - sandbox.stub(auctionManager, 'findBidByAdId').returns(mockContextual); - config.mergeConfig({ - paapi: { - topLevelSeller: { - overrideWinner: true - } - } - }); - }); - - it(`should ${!canRender ? 'NOT' : ''} override winning bid for the same adUnit`, () => { - return Promise.all([ - getBids({adUnitCode: 'au', auctionId}).then(res => res.au), - getBidToRenderPm(mockContextual.adId) - ]).then(([paapiBid, bidToRender]) => { - if (canRender) { - expect(bidToRender).to.eql(paapiBid); - expect(paapiBid.overriddenAdId).to.eql(mockContextual.adId); - } else { - expect(bidToRender).to.eql(mockContextual) - } - }) - }); - - it('should not override when the ad unit has no paapi winner', () => { - mockContextual.adUnitCode = 'other'; - return getBidToRenderPm(mockContextual.adId).then(bidToRender => { - expect(bidToRender).to.eql(mockContextual); - }) - }); - - it('should not override when already a paapi bid', () => { - return getBids({adUnitCode: 'au', auctionId}).then(res => { - return getBidToRenderPm(res.au.adId).then((bidToRender) => [bidToRender, res.au]); - }).then(([bidToRender, paapiBid]) => { - expect(bidToRender).to.eql(canRender ? paapiBid : mockContextual) - }) - }); - - if (canRender) { - it('should not not override when the bid was already rendered', () => { - getBids(); - return getBidToRenderPm(mockContextual.adId).then((bid) => { - // first pass - paapi wins over contextual - expect(bid.source).to.eql('paapi'); - bid.status = BID_STATUS.RENDERED; - return getBidToRenderPm(mockContextual.adId, false).then(bidToRender => [bid, bidToRender]) - }).then(([paapiBid, bidToRender]) => { - // if `forRender` = false (bit retrieved for x-domain events and such) - // the referenced bid is still paapi - expect(bidToRender).to.eql(paapiBid); - return getBidToRenderPm(mockContextual.adId); - }).then(bidToRender => { - // second pass, paapi has been rendered, contextual should win - expect(bidToRender).to.eql(mockContextual); - bidToRender.status = BID_STATUS.RENDERED; - return getBidToRenderPm(mockContextual.adId, false); - }).then(bidToRender => { - // if the contextual bid has been rendered, it's the one being referenced - expect(bidToRender).to.eql(mockContextual); - }); - }) - } - }); - }); - - it('should resolve the same result from different filters', () => { - const targets = { - auct1: ['au1', 'au2'], - auct2: ['au1', 'au3'] - }; - Object.entries(targets).forEach(([auctionId, adUnitCodes]) => { - adUnitCodes.forEach(au => addPaapiConfig(au, auctionConfig, auctionId)); - }); - endAuctions(); - return Promise.all( - [ - [ - {adUnitCode: 'au1', auctionId: 'auct1'}, - { - au1: 'raa-au1-auct1' - } - ], - [ - {}, - { - au1: 'raa-au1-auct2', - au2: 'raa-au2-auct1', - au3: 'raa-au3-auct2' - } - ], - [ - {auctionId: 'auct1'}, - { - au1: 'raa-au1-auct1', - au2: 'raa-au2-auct1' - } - ], - [ - {adUnitCode: 'au1'}, - { - au1: 'raa-au1-auct2' - } - ], - ].map(([filters, expected]) => getBids(filters).then(res => [res, expected])) - ).then(res => { - res.forEach(([actual, expected]) => { - expectBids(actual, expected); - }); - }); - }); - }); - }); - }); - }); - - describe('when not configured', () => { - it('should not alter configs returned by getPAAPIConfig', () => { - addPaapiConfig('au', auctionConfig); - endAuctions(); - expect(getPAAPIConfig().au.seller).to.not.exist; - }); - }); - - describe('paapi adId', () => { - [ - ['auctionId', 'adUnitCode'], - ['auction:id', 'adUnit:code'], - ['auction:uid', 'ad:unit'] - ].forEach(([auctionId, adUnitCode]) => { - it(`can encode and decode ${auctionId}, ${adUnitCode}`, () => { - expect(parsePaapiAdId(getPaapiAdId(auctionId, adUnitCode))).to.eql([auctionId, adUnitCode]); - }); - }); - - [undefined, null, 'not-a-paapi-ad', 'paapi:/malformed'].forEach(adId => { - it(`returns null for adId ${adId}`, () => { - expect(parsePaapiAdId(adId)).to.not.exist; - }); - }); - }); - - describe('parsePaapiSize', () => { - [ - [null, null], - [undefined, null], - [123, 123], - ['123', 123], - ['123px', 123], - ['1sw', null], - ['garbage', null] - ].forEach(([input, expected]) => { - it(`can parse ${input} => ${expected}`, () => { - expect(parsePaapiSize(input)).to.eql(expected); - }); - }); - }); - - describe('rendering hooks', () => { - let next; - beforeEach(() => { - next = sinon.stub() - next.bail = sinon.stub() - }); - describe('getRenderingDataHook', () => { - it('intercepts paapi bids', () => { - getRenderingDataHook(next, { - source: 'paapi', - width: 123, - height: null, - urn: 'url' - }); - sinon.assert.calledWith(next.bail, { - width: 123, - height: null, - adUrl: 'url' - }); - }); - it('does not touch non-paapi bids', () => { - getRenderingDataHook(next, {bid: 'data'}, {other: 'options'}); - sinon.assert.calledWith(next, {bid: 'data'}, {other: 'options'}); - }); - }); - - describe('markWinnigBidsHook', () => { - beforeEach(() => { - sandbox.stub(events, 'emit'); - }); - it('handles paapi bids', () => { - const bid = {source: 'paapi'}; - markWinningBidHook(next, bid); - sinon.assert.notCalled(next); - sinon.assert.called(next.bail); - sinon.assert.calledWith(events.emit, EVENTS.BID_WON, bid); - }); - it('ignores non-paapi bids', () => { - markWinningBidHook(next, {other: 'bid'}); - sinon.assert.calledWith(next, {other: 'bid'}); - sinon.assert.notCalled(next.bail); - }); - }); - }); -}); diff --git a/test/spec/modules/trafficgateBidAdapter_spec.js b/test/spec/modules/trafficgateBidAdapter_spec.js index 27550b2cd20..ded4f1c0aa0 100644 --- a/test/spec/modules/trafficgateBidAdapter_spec.js +++ b/test/spec/modules/trafficgateBidAdapter_spec.js @@ -12,7 +12,6 @@ import 'modules/multibid/index.js'; import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import 'modules/paapi.js'; import {deepClone} from 'src/utils.js'; import {addFPDToBidderRequest} from '../../helpers/fpd.js'; diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index 19c537e4da3..72c6baff8cc 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -892,12 +892,6 @@ describe('triplelift adapter', function () { const url = request.url; expect(url).to.match(/(\?|&)us_privacy=1YYY/); }); - it('should pass fledge signal when Triplelift is eligible for fledge', function() { - bidderRequest.paapi = {enabled: true}; - const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); - const url = request.url; - expect(url).to.match(/(\?|&)fledge=true/); - }); it('should return coppa param when COPPA config is set to true', function() { sinon.stub(config, 'getConfig').withArgs('coppa').returns(true); const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); @@ -1400,57 +1394,6 @@ describe('triplelift adapter', function () { expect(result[2].meta.networkId).to.equal('5989'); expect(result[3].meta.networkId).to.equal('5989'); }); - - it('should return fledgeAuctionConfigs if PAAPI response is received', function() { - response.body.paapi = [ - { - imp_id: '0', - auctionConfig: { - seller: 'https://3lift.com', - decisionLogicUrl: 'https://3lift.com/decision_logic.js', - interestGroupBuyers: ['https://some_buyer.com'], - perBuyerSignals: { - 'https://some_buyer.com': { a: 1 } - } - } - }, - { - imp_id: '2', - auctionConfig: { - seller: 'https://3lift.com', - decisionLogicUrl: 'https://3lift.com/decision_logic.js', - interestGroupBuyers: ['https://some_other_buyer.com'], - perBuyerSignals: { - 'https://some_other_buyer.com': { b: 2 } - } - } - } - ]; - - const result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); - - expect(result).to.have.property('bids'); - expect(result).to.have.property('paapi'); - expect(result.paapi.length).to.equal(2); - expect(result.paapi[0].bidId).to.equal('30b31c1838de1e'); - expect(result.paapi[1].bidId).to.equal('73edc0ba8de203'); - expect(result.paapi[0].config).to.deep.equal( - { - 'seller': 'https://3lift.com', - 'decisionLogicUrl': 'https://3lift.com/decision_logic.js', - 'interestGroupBuyers': ['https://some_buyer.com'], - 'perBuyerSignals': { 'https://some_buyer.com': { 'a': 1 } } - } - ); - expect(result.paapi[1].config).to.deep.equal( - { - 'seller': 'https://3lift.com', - 'decisionLogicUrl': 'https://3lift.com/decision_logic.js', - 'interestGroupBuyers': ['https://some_other_buyer.com'], - 'perBuyerSignals': { 'https://some_other_buyer.com': { 'b': 2 } } - } - ); - }); }); describe('getUserSyncs', function() { diff --git a/test/spec/modules/twistDigitalBidAdapter_spec.js b/test/spec/modules/twistDigitalBidAdapter_spec.js index ea3779c8be8..25a521d957d 100644 --- a/test/spec/modules/twistDigitalBidAdapter_spec.js +++ b/test/spec/modules/twistDigitalBidAdapter_spec.js @@ -639,15 +639,6 @@ describe('TwistDigitalBidAdapter', function () { expect(requests).to.have.length(2); }); - it('should set fledge correctly if enabled', function () { - config.resetConfig(); - const bidderRequest = utils.deepClone(BIDDER_REQUEST); - bidderRequest.paapi = {enabled: true}; - deepSetValue(bidderRequest, 'ortb2Imp.ext.ae', 1); - const requests = adapter.buildRequests([BID], bidderRequest); - expect(requests[0].data.fledge).to.equal(1); - }); - after(function () { getGlobal().bidderSettings = {}; config.resetConfig(); diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js index ab0820ef32e..77aaeb8a458 100644 --- a/test/spec/modules/vidazooBidAdapter_spec.js +++ b/test/spec/modules/vidazooBidAdapter_spec.js @@ -659,15 +659,6 @@ describe('VidazooBidAdapter', function () { expect(requests).to.have.length(2); }); - it('should set fledge correctly if enabled', function () { - config.resetConfig(); - const bidderRequest = utils.deepClone(BIDDER_REQUEST); - bidderRequest.paapi = {enabled: true}; - deepSetValue(bidderRequest, 'ortb2Imp.ext.ae', 1); - const requests = adapter.buildRequests([BID], bidderRequest); - expect(requests[0].data.fledge).to.equal(1); - }); - after(function () { getGlobal().bidderSettings = {}; config.resetConfig(); diff --git a/test/spec/unit/adRendering_spec.js b/test/spec/unit/adRendering_spec.js index b7be604b85b..bc5acd10317 100644 --- a/test/spec/unit/adRendering_spec.js +++ b/test/spec/unit/adRendering_spec.js @@ -35,27 +35,6 @@ describe('adRendering', () => { sandbox.restore(); }) - describe('getBidToRender', () => { - beforeEach(() => { - sandbox.stub(auctionManager, 'findBidByAdId').callsFake(() => 'auction-bid') - }); - it('should default to bid from auctionManager', async () => { - await new Promise((resolve) => { - getBidToRender('adId', true, (res) => { - expect(res).to.eql('auction-bid'); - sinon.assert.calledWith(auctionManager.findBidByAdId, 'adId'); - resolve(); - }) - }) - }); - it('should, by default, not give up the thread', () => { - let ran = false; - getBidToRender('adId', true, () => { - ran = true; - }); - expect(ran).to.be.true; - }) - }) describe('getRenderingData', () => { let bidResponse; beforeEach(() => { diff --git a/test/spec/unit/core/ajax_spec.js b/test/spec/unit/core/ajax_spec.js index dd62bed97c1..2646ed2cc10 100644 --- a/test/spec/unit/core/ajax_spec.js +++ b/test/spec/unit/core/ajax_spec.js @@ -186,7 +186,7 @@ describe('toFetchRequest', () => { }); describe('chrome options', () => { - ['browsingTopics', 'adAuctionHeaders'].forEach(option => { + ['browsingTopics'].forEach(option => { Object.entries({ [`${option} = true`]: [{[option]: true}, true], [`${option} = false`]: [{[option]: false}, false], diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 79b09cfbe11..ff390b95268 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -1,4 +1,4 @@ -import {addPaapiConfig, addIGBuyer, isValid, newBidder, registerBidder} from 'src/adapters/bidderFactory.js'; +import {isValid, newBidder, registerBidder} from 'src/adapters/bidderFactory.js'; import adapterManager from 'src/adapterManager.js'; import * as ajax from 'src/ajax.js'; import {expect} from 'chai'; @@ -1640,59 +1640,6 @@ describe('bidderFactory', () => { bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); sinon.assert.calledWith(addBidResponseStub, 'mock/placement', sinon.match(bid)); }) - - describe('when response has PAAPI config', function() { - let paapiStub; - - function paapiHook(next, ...args) { - paapiStub(...args); - } - - function runBidder(response) { - const bidder = newBidder(spec); - spec.interpretResponse.returns(response); - bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); - } - - before(() => { - addPaapiConfig.before(paapiHook); - }); - - after(() => { - addPaapiConfig.getHooks({hook: paapiHook}).remove(); - }) - - beforeEach(function () { - paapiStub = sinon.stub(); - }); - - describe(`when response has paapi`, () => { - it('should call paapi config hook with auction configs', function () { - runBidder({ - bids: bids, - paapi: [paapiConfig] - }); - expect(paapiStub.calledOnce).to.equal(true); - sinon.assert.calledWith(paapiStub, bidRequest.bids[0], paapiConfig); - sinon.assert.calledWith(addBidResponseStub, 'mock/placement', sinon.match(bids[0])); - }); - - Object.entries({ - 'missing': undefined, - 'an empty array': [] - }).forEach(([t, bids]) => { - it(`should call paapi config hook with PAAPI configs even when bids is ${t}`, function () { - runBidder({ - bids, - paapi: [paapiConfig] - }); - expect(paapiStub.calledOnce).to.be.true; - sinon.assert.calledWith(paapiStub, bidRequest.bids[0], paapiConfig); - expect(addBidResponseStub.calledOnce).to.equal(false); - }); - }); - }); - }); }); }); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 5939298765e..9a6cbdaac1a 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -26,7 +26,6 @@ import {mockFpdEnrichments} from '../../helpers/fpd.js'; import {deepAccess, deepSetValue, generateUUID} from '../../../src/utils.js'; import {getCreativeRenderer} from '../../../src/creativeRenderers.js'; import {BID_STATUS, EVENTS, GRANULARITY_OPTIONS, PB_LOCATOR, TARGETING_KEYS} from 'src/constants.js'; -import {getBidToRender} from '../../../src/adRendering.js'; import {getGlobal} from '../../../src/prebidGlobal.js'; var assert = require('chai').assert; diff --git a/test/spec/unit/secureCreatives_spec.js b/test/spec/unit/secureCreatives_spec.js index 084341358b4..9e3f2cab132 100644 --- a/test/spec/unit/secureCreatives_spec.js +++ b/test/spec/unit/secureCreatives_spec.js @@ -14,24 +14,12 @@ import 'modules/nativeRendering.js'; import {expect} from 'chai'; import {AD_RENDER_FAILED_REASON, BID_STATUS, EVENTS} from 'src/constants.js'; -import {getBidToRender} from '../../../src/adRendering.js'; import {PUC_MIN_VERSION} from 'src/creativeRenderers.js'; import {getGlobal} from '../../../src/prebidGlobal.js'; describe('secureCreatives', () => { let sandbox; - function getBidToRenderHook(next, ...args) { - // make sure that bids can be retrieved asynchronously - setTimeout(() => next(...args)) - } - before(() => { - getBidToRender.before(getBidToRenderHook); - }); - after(() => { - getBidToRender.getHooks({hook: getBidToRenderHook}).remove() - }); - beforeEach(() => { sandbox = sinon.createSandbox(); }); From c2bb76e1f0b41c9d1ad902f6b1a53f4def89c4d5 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Mon, 9 Feb 2026 15:36:01 -0500 Subject: [PATCH 12/48] Fix JSON formatting in quantcastBidAdapter.json From ffdfb593a4943028bd17b8af6923c93889849d5a Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Tue, 10 Feb 2026 12:55:46 -0500 Subject: [PATCH 13/48] Core: default storageControl enforcement to strict (#14439) --- modules/storageControl.ts | 8 ++++---- test/spec/modules/storageControl_spec.js | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/storageControl.ts b/modules/storageControl.ts index 93411fba3ac..0302ece3f4b 100644 --- a/modules/storageControl.ts +++ b/modules/storageControl.ts @@ -116,7 +116,7 @@ export function storageControlRule(getEnforcement = () => enforcement, check = c const {disclosed, parent, reason} = check(params); if (disclosed === null) return; if (!disclosed) { - const enforcement = getEnforcement(); + const enforcement = getEnforcement() ?? ENFORCE_STRICT; if (enforcement === ENFORCE_STRICT || (enforcement === ENFORCE_ALIAS && !parent)) return {allow: false, reason}; if (reason) { logWarn('storageControl:', reason); @@ -129,10 +129,10 @@ registerActivityControl(ACTIVITY_ACCESS_DEVICE, 'storageControl', storageControl export type StorageControlConfig = { /** - * - 'off': logs a warning when an undisclosed storage key is used - * - 'strict': deny access to undisclosed storage keys + * - 'strict': deny access to undisclosed storage keys (default) * - 'allowAliases': deny access to undisclosed storage keys, unless the use is from an alias of a module that does * disclose them + * - 'off': logs a warning when an undisclosed storage key is used */ enforcement?: typeof ENFORCE_OFF | typeof ENFORCE_ALIAS | typeof ENFORCE_STRICT; } @@ -144,7 +144,7 @@ declare module '../src/config' { } config.getConfig('storageControl', (cfg) => { - enforcement = cfg?.storageControl?.enforcement ?? ENFORCE_OFF; + enforcement = cfg?.storageControl?.enforcement ?? ENFORCE_STRICT; }) export function dynamicDisclosureCollector() { diff --git a/test/spec/modules/storageControl_spec.js b/test/spec/modules/storageControl_spec.js index a3fb571256b..9ac8a34a463 100644 --- a/test/spec/modules/storageControl_spec.js +++ b/test/spec/modules/storageControl_spec.js @@ -208,6 +208,12 @@ describe('storageControl', () => { expect(rule()).to.eql({allow: false, reason: 'denied'}); }); + it('should deny by default when enforcement is not set', () => { + enforcement = undefined; + checkResult = {disclosed: false, parent: false, reason: 'denied'}; + expect(rule()).to.eql({allow: false, reason: 'denied'}); + }); + it('should allow when enforcement is allowAliases and disclosure is done by the aliased module', () => { enforcement = ENFORCE_ALIAS; checkResult = {disclosed: false, parent: true, reason: 'allowed'}; From f0cff685602cb5ac38d0bccdccc449b97521ac9e Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 11 Feb 2026 11:06:20 -0500 Subject: [PATCH 14/48] Core: remove bidAccepted event emission (#14449) --- modules/rtdModule/index.ts | 3 +-- modules/rtdModule/spec.ts | 3 +-- src/auction.ts | 5 ----- src/constants.ts | 1 - test/spec/unit/pbjs_api_spec.js | 8 -------- 5 files changed, 2 insertions(+), 18 deletions(-) diff --git a/modules/rtdModule/index.ts b/modules/rtdModule/index.ts index 1b3bff0baf3..440eae27fd9 100644 --- a/modules/rtdModule/index.ts +++ b/modules/rtdModule/index.ts @@ -53,8 +53,7 @@ const setEventsListeners = (function () { [EVENTS.AUCTION_INIT]: ['onAuctionInitEvent'], [EVENTS.AUCTION_END]: ['onAuctionEndEvent', getAdUnitTargeting], [EVENTS.BID_RESPONSE]: ['onBidResponseEvent'], - [EVENTS.BID_REQUESTED]: ['onBidRequestEvent'], - [EVENTS.BID_ACCEPTED]: ['onBidAcceptedEvent'] + [EVENTS.BID_REQUESTED]: ['onBidRequestEvent'] }).forEach(([ev, [handler, preprocess]]) => { events.on(ev as any, (args) => { preprocess && (preprocess as any)(args); diff --git a/modules/rtdModule/spec.ts b/modules/rtdModule/spec.ts index 7abf38e1247..4dbff40ca2f 100644 --- a/modules/rtdModule/spec.ts +++ b/modules/rtdModule/spec.ts @@ -32,8 +32,7 @@ export type RTDProviderConfig

= BaseConfig

& ( type RTDEvent = typeof EVENTS.AUCTION_INIT | typeof EVENTS.AUCTION_END | typeof EVENTS.BID_RESPONSE | - typeof EVENTS.BID_REQUESTED | - typeof EVENTS.BID_ACCEPTED; + typeof EVENTS.BID_REQUESTED; type EventHandlers

= { [EV in RTDEvent]: (payload: EventPayload, config: RTDProviderConfig

, consent: AllConsentData) => void; diff --git a/src/auction.ts b/src/auction.ts index a6912be69be..5f2a1ad63c0 100644 --- a/src/auction.ts +++ b/src/auction.ts @@ -100,10 +100,6 @@ declare module './events' { * Fired when an auction times out. */ [EVENTS.BID_TIMEOUT]: [BidRequest[]]; - /** - * Fired when a bid is received. - */ - [EVENTS.BID_ACCEPTED]: [Partial]; /** * Fired when a bid is rejected. */ @@ -530,7 +526,6 @@ export function auctionCallbacks(auctionDone, auctionInstance, {index = auctionM function acceptBidResponse(adUnitCode: string, bid: Partial) { handleBidResponse(adUnitCode, bid, (done) => { const bidResponse = getPreparedBidForAuction(bid); - events.emit(EVENTS.BID_ACCEPTED, bidResponse); if ((FEATURES.VIDEO && bidResponse.mediaType === VIDEO) || (FEATURES.AUDIO && bidResponse.mediaType === AUDIO)) { tryAddVideoAudioBid(auctionInstance, bidResponse, done); } else { diff --git a/src/constants.ts b/src/constants.ts index c1331d51361..b9525e51e3a 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -42,7 +42,6 @@ export const EVENTS = { STALE_RENDER: 'staleRender', EXPIRED_RENDER: 'expiredRender', BILLABLE_EVENT: 'billableEvent', - BID_ACCEPTED: 'bidAccepted', PBS_ANALYTICS: 'pbsAnalytics', BEFORE_PBS_HTTP: 'beforePBSHttp', BROWSI_INIT: 'browsiInit', diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 9a6cbdaac1a..105b3392d00 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -3242,14 +3242,6 @@ describe('Unit: Prebid Module', function () { assert.ok(spyEventsOn.calledWith('bidWon', Function)); events.on.restore(); }); - - it('should emit event BID_ACCEPTED when invoked', function () { - var callback = sinon.spy(); - pbjs.onEvent('bidAccepted', callback); - events.emit(EVENTS.BID_ACCEPTED); - sinon.assert.calledOnce(callback); - }); - describe('beforeRequestBids', function () { let bidRequestedHandler; let beforeRequestBidsHandler; From a3001da1c9e72da02f061827382657034c2720f9 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 11 Feb 2026 11:55:59 -0500 Subject: [PATCH 15/48] 33across ID System: fix getId storage test stub isolation (#14457) --- test/spec/modules/33acrossIdSystem_spec.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/test/spec/modules/33acrossIdSystem_spec.js b/test/spec/modules/33acrossIdSystem_spec.js index 3a1bf6da2b3..909fef4c6fa 100644 --- a/test/spec/modules/33acrossIdSystem_spec.js +++ b/test/spec/modules/33acrossIdSystem_spec.js @@ -21,6 +21,10 @@ describe('33acrossIdSystem', () => { }); describe('getId', () => { + afterEach(() => { + sinon.restore(); + }); + it('should call endpoint', () => { const completeCallback = sinon.spy(); @@ -96,6 +100,7 @@ describe('33acrossIdSystem', () => { const removeDataFromLocalStorage = sinon.stub(storage, 'removeDataFromLocalStorage'); const setCookie = sinon.stub(storage, 'setCookie'); + sinon.stub(storage, 'cookiesAreEnabled').returns(true); sinon.stub(domainUtils, 'domainOverride').returns('foo.com'); request.respond(200, { @@ -110,10 +115,6 @@ describe('33acrossIdSystem', () => { expect(removeDataFromLocalStorage.calledWithExactly('33acrossIdHm')).to.be.false; expect(setCookie.calledWithExactly('33acrossIdHm', '', sinon.match.string, 'Lax', 'foo.com')).to.be.false; - - removeDataFromLocalStorage.restore(); - setCookie.restore(); - domainUtils.domainOverride.restore(); }); }); @@ -614,6 +615,7 @@ describe('33acrossIdSystem', () => { const removeDataFromLocalStorage = sinon.stub(storage, 'removeDataFromLocalStorage'); const setCookie = sinon.stub(storage, 'setCookie'); + sinon.stub(storage, 'cookiesAreEnabled').returns(true); sinon.stub(domainUtils, 'domainOverride').returns('foo.com'); request.respond(200, { @@ -630,10 +632,6 @@ describe('33acrossIdSystem', () => { expect(removeDataFromLocalStorage.calledWith(`33acrossId${suffix}`)).to.be.true; expect(setCookie.calledWithExactly(`33acrossId${suffix}`, '', sinon.match.string, 'Lax', 'foo.com')).to.be.true; }); - - removeDataFromLocalStorage.restore(); - setCookie.restore(); - domainUtils.domainOverride.restore(); }); }); From c0c52f022a2ee27813a6ba016b53efe685093060 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 11 Feb 2026 12:29:16 -0500 Subject: [PATCH 16/48] ShinezRtb Adapter: stabilize unique deal id timing test (#14446) --- test/spec/modules/shinezRtbBidAdapter_spec.js | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/test/spec/modules/shinezRtbBidAdapter_spec.js b/test/spec/modules/shinezRtbBidAdapter_spec.js index 2dd33d7ef5b..fc7b2bccd92 100644 --- a/test/spec/modules/shinezRtbBidAdapter_spec.js +++ b/test/spec/modules/shinezRtbBidAdapter_spec.js @@ -680,6 +680,8 @@ describe('ShinezRtbBidAdapter', function () { }); describe('unique deal id', function () { + let clock; + before(function () { getGlobal().bidderSettings = { shinezRtb: { @@ -693,24 +695,27 @@ describe('ShinezRtbBidAdapter', function () { const key = 'myKey'; let uniqueDealId; beforeEach(() => { + clock = useFakeTimers({ + now: Date.now() + }); uniqueDealId = getUniqueDealId(storage, key, 0); - }) + }); + + afterEach(() => { + clock.restore(); + }); + + it('should get current unique deal id', function () { + // advance time in a deterministic way + clock.tick(200); + const current = getUniqueDealId(storage, key); + expect(current).to.be.equal(uniqueDealId); + }); - it('should get current unique deal id', function (done) { - // waiting some time so `now` will become past - setTimeout(() => { - const current = getUniqueDealId(storage, key); - expect(current).to.be.equal(uniqueDealId); - done(); - }, 200); - }); - - it('should get new unique deal id on expiration', function (done) { - setTimeout(() => { - const current = getUniqueDealId(storage, key, 100); - expect(current).to.not.be.equal(uniqueDealId); - done(); - }, 200) + it('should get new unique deal id on expiration', function () { + clock.tick(200); + const current = getUniqueDealId(storage, key, 100); + expect(current).to.not.be.equal(uniqueDealId); }); }); From 4e9759a5b837ea6baf7a637407e887544829562d Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 11 Feb 2026 13:04:57 -0500 Subject: [PATCH 17/48] ShinezRtb Adapter: stabilize unique deal id test (#14458) --- test/spec/modules/shinezRtbBidAdapter_spec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/spec/modules/shinezRtbBidAdapter_spec.js b/test/spec/modules/shinezRtbBidAdapter_spec.js index fc7b2bccd92..3f2dfcc83a8 100644 --- a/test/spec/modules/shinezRtbBidAdapter_spec.js +++ b/test/spec/modules/shinezRtbBidAdapter_spec.js @@ -692,12 +692,13 @@ describe('ShinezRtbBidAdapter', function () { after(function () { getGlobal().bidderSettings = {}; }); - const key = 'myKey'; + let key; let uniqueDealId; beforeEach(() => { clock = useFakeTimers({ now: Date.now() }); + key = `myKey_${Date.now()}`; uniqueDealId = getUniqueDealId(storage, key, 0); }); From 1794187c266838e230a04e70909a9f331342b4e7 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 11 Feb 2026 13:16:01 -0500 Subject: [PATCH 18/48] Core: remove null callback placeholders from storage manager reads/writes (#14461) --- libraries/vidazooUtils/bidderUtils.js | 6 +++--- modules/sirdataRtdProvider.js | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/vidazooUtils/bidderUtils.js b/libraries/vidazooUtils/bidderUtils.js index 98da155ed10..60934c0ed88 100644 --- a/libraries/vidazooUtils/bidderUtils.js +++ b/libraries/vidazooUtils/bidderUtils.js @@ -64,7 +64,7 @@ export function setStorageItem(storage, key, value, timestamp) { export function getStorageItem(storage, key) { try { - return tryParseJSON(storage.getDataFromLocalStorage(key, null)); + return tryParseJSON(storage.getDataFromLocalStorage(key)); } catch (e) { } @@ -72,10 +72,10 @@ export function getStorageItem(storage, key) { } export function getCacheOpt(storage, useKey) { - let data = storage.getDataFromLocalStorage(useKey, null); + let data = storage.getDataFromLocalStorage(useKey); if (!data) { data = String(Date.now()); - storage.setDataInLocalStorage(useKey, data, null); + storage.setDataInLocalStorage(useKey, data); } return data; diff --git a/modules/sirdataRtdProvider.js b/modules/sirdataRtdProvider.js index 77c6f939a95..9115c7dc542 100644 --- a/modules/sirdataRtdProvider.js +++ b/modules/sirdataRtdProvider.js @@ -107,7 +107,7 @@ export function setCookieOnTopDomain(key, value, hostname, deleteCookie) { try { STORAGE.setCookie(key, value, expTime.toUTCString(), 'Lax', '.' + domain); // Try to read the cookie to check if we wrote it - if (STORAGE.getCookie(key, null) === value) return true; // Check if the cookie was set, and if so top domain was found. If deletion with expire date -1 will parse until complete host + if (STORAGE.getCookie(key) === value) return true; // Check if the cookie was set, and if so top domain was found. If deletion with expire date -1 will parse until complete host } catch (e) { logError(LOG_PREFIX, e); } @@ -120,10 +120,10 @@ export function setCookieOnTopDomain(key, value, hostname, deleteCookie) { * @returns {Array|null} - Array of UID objects or null if no UID found */ export function getUidFromStorage() { - let cUid = STORAGE.getCookie(EUIDS_STORAGE_NAME, null); - const lsUid = STORAGE.getDataFromLocalStorage(EUIDS_STORAGE_NAME, null); + let cUid = STORAGE.getCookie(EUIDS_STORAGE_NAME); + const lsUid = STORAGE.getDataFromLocalStorage(EUIDS_STORAGE_NAME); if (cUid && (!lsUid || cUid !== lsUid)) { - STORAGE.setDataInLocalStorage(EUIDS_STORAGE_NAME, cUid, null); + STORAGE.setDataInLocalStorage(EUIDS_STORAGE_NAME, cUid); } else if (lsUid && !cUid) { setCookieOnTopDomain(EUIDS_STORAGE_NAME, lsUid, cookieDomain, false); cUid = lsUid; @@ -140,7 +140,7 @@ export function setUidInStorage(sddanId) { if (!sddanId) return false; sddanId = encodeURI(sddanId.toString()); setCookieOnTopDomain(EUIDS_STORAGE_NAME, sddanId, cookieDomain, false); - STORAGE.setDataInLocalStorage(EUIDS_STORAGE_NAME, sddanId, null); + STORAGE.setDataInLocalStorage(EUIDS_STORAGE_NAME, sddanId); return true; } From 50fbdbd0307034a9da3064a59a7ec756ede79c0b Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 11 Feb 2026 13:41:17 -0500 Subject: [PATCH 19/48] Prebid 11: remove adpod mediatype (#14451) * Core: remove dead adpod code paths from appnexus and mediafuse * Delete libraries/categoryTranslationMapping/index.js * Delete modules/categoryTranslation.js * Delete metadata/modules/categoryTranslation.json * Delete test/spec/modules/categoryTranslation_spec.js * Delete metadata/disclosures/prebid/categoryTranslation.json * Remove notifyTranslationModule and its hook registration Removed notifyTranslationModule function and its registration. * Remove brand category exclusion from payload Removed brand category uniqueness setting from payload. * Remove brand category uniqueness from payload Removed brand category uniqueness setting from payload. * Update appnexusBidAdapter_spec.js * Update mediafuseBidAdapter_spec.js * Update gamAdServerVideo.js * Update test_deps.js * Adapters: remove adpod media type handling across bidders (#14456) * Update aidemBidAdapter.js * Update aidemBidAdapter_spec.js --- .../longform/basic_w_bidderSettings.html | 148 -- .../basic_w_custom_adserver_translation.html | 135 -- .../longform/basic_w_priceGran.html | 156 --- .../basic_w_requireExactDuration.html | 133 -- .../basic_wo_brandCategoryExclusion.html | 133 -- .../basic_wo_requireExactDuration.html | 134 -- libraries/categoryTranslationMapping/index.js | 100 -- .../prebid/categoryTranslation.json | 26 - metadata/modules/categoryTranslation.json | 31 - modules/.submodules.json | 4 - modules/adoceanBidAdapter.js | 20 - modules/adpod.js | 657 --------- modules/adtelligentBidAdapter.js | 22 +- modules/appnexusBidAdapter.js | 96 +- modules/categoryTranslation.js | 105 -- modules/freeWheelAdserverVideo.js | 19 - modules/gamAdServerVideo.js | 7 - modules/gamAdpod.js | 95 -- modules/mediafuseBidAdapter.js | 94 +- modules/pubmaticBidAdapter.js | 26 +- modules/smaatoBidAdapter.js | 188 +-- src/targeting.ts | 3 +- src/utils.js | 2 +- test/spec/modules/adoceanBidAdapter_spec.js | 67 - test/spec/modules/adpod_spec.js | 1238 ----------------- .../modules/adtelligentBidAdapter_spec.js | 31 - test/spec/modules/appnexusBidAdapter_spec.js | 261 ---- test/spec/modules/categoryTranslation_spec.js | 109 -- .../modules/freeWheelAdserverVideo_spec.js | 350 ----- test/spec/modules/gamAdpod_spec.js | 257 ---- test/spec/modules/mediafuseBidAdapter_spec.js | 261 ---- test/spec/modules/smaatoBidAdapter_spec.js | 356 +---- test/spec/unit/core/targeting_spec.js | 11 - test/test_deps.js | 1 - 34 files changed, 47 insertions(+), 5229 deletions(-) delete mode 100644 integrationExamples/longform/basic_w_bidderSettings.html delete mode 100644 integrationExamples/longform/basic_w_custom_adserver_translation.html delete mode 100644 integrationExamples/longform/basic_w_priceGran.html delete mode 100644 integrationExamples/longform/basic_w_requireExactDuration.html delete mode 100644 integrationExamples/longform/basic_wo_brandCategoryExclusion.html delete mode 100644 integrationExamples/longform/basic_wo_requireExactDuration.html delete mode 100644 libraries/categoryTranslationMapping/index.js delete mode 100644 metadata/disclosures/prebid/categoryTranslation.json delete mode 100644 metadata/modules/categoryTranslation.json delete mode 100644 modules/adpod.js delete mode 100644 modules/categoryTranslation.js delete mode 100644 modules/freeWheelAdserverVideo.js delete mode 100644 modules/gamAdpod.js delete mode 100644 test/spec/modules/adpod_spec.js delete mode 100644 test/spec/modules/categoryTranslation_spec.js delete mode 100644 test/spec/modules/freeWheelAdserverVideo_spec.js delete mode 100644 test/spec/modules/gamAdpod_spec.js diff --git a/integrationExamples/longform/basic_w_bidderSettings.html b/integrationExamples/longform/basic_w_bidderSettings.html deleted file mode 100644 index fb87ea5d990..00000000000 --- a/integrationExamples/longform/basic_w_bidderSettings.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - Prebid Freewheel Integration Demo - - - - - - - - - - - - - - - - - - - -

Prebid Freewheel Test Page

-

requireExactDuration = false

-
-
- -
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-
-
- - - - \ No newline at end of file diff --git a/integrationExamples/longform/basic_w_custom_adserver_translation.html b/integrationExamples/longform/basic_w_custom_adserver_translation.html deleted file mode 100644 index 2dbb89506b5..00000000000 --- a/integrationExamples/longform/basic_w_custom_adserver_translation.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - Prebid Freewheel Integration Demo - - - - - - - - - - - - - - - - - - - -

Prebid Freewheel Integration Demo

-

custom adserver translation file

-
-
- -
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-
-
- - - - diff --git a/integrationExamples/longform/basic_w_priceGran.html b/integrationExamples/longform/basic_w_priceGran.html deleted file mode 100644 index 4ea9d5d19be..00000000000 --- a/integrationExamples/longform/basic_w_priceGran.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - Prebid Freewheel Integration Demo - - - - - - - - - - - - - - - - - - - -

Prebid Freewheel Test Page

-

requireExactDuration = false

-
-
- -
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-
-
- - - - \ No newline at end of file diff --git a/integrationExamples/longform/basic_w_requireExactDuration.html b/integrationExamples/longform/basic_w_requireExactDuration.html deleted file mode 100644 index 46b91887cfb..00000000000 --- a/integrationExamples/longform/basic_w_requireExactDuration.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Prebid Freewheel Integration Demo - - - - - - - - - - - - - - - - - - - -

Prebid Freewheel Test Page

-

requireExactDuration = true

-
-
- -
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-
-
- - - - diff --git a/integrationExamples/longform/basic_wo_brandCategoryExclusion.html b/integrationExamples/longform/basic_wo_brandCategoryExclusion.html deleted file mode 100644 index 47ea4b7f47d..00000000000 --- a/integrationExamples/longform/basic_wo_brandCategoryExclusion.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Prebid Freewheel Integration Demo - - - - - - - - - - - - - - - - - - - -

Prebid Freewheel Test Page

-

brandCategoryExclusion = false

-
-
- -
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-
-
- - - - diff --git a/integrationExamples/longform/basic_wo_requireExactDuration.html b/integrationExamples/longform/basic_wo_requireExactDuration.html deleted file mode 100644 index 6dbedbc6d39..00000000000 --- a/integrationExamples/longform/basic_wo_requireExactDuration.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - - Prebid Freewheel Integration Demo - - - - - - - - - - - - - - - - - - - -

Prebid Freewheel Test Page

-

requireExactDuration = false

-
-
- -
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-

- -

-
-
-
- // bids -
-
-
-
-
-
-
- - - - diff --git a/libraries/categoryTranslationMapping/index.js b/libraries/categoryTranslationMapping/index.js deleted file mode 100644 index 13b10423450..00000000000 --- a/libraries/categoryTranslationMapping/index.js +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Provides mapping objects used by bidders for categoryTranslation type logic for Adpod feature - */ -export const APPNEXUS_CATEGORY_MAPPING = { - '1': 'IAB20-3', - '2': 'IAB18-5', - '3': 'IAB10-1', - '4': 'IAB2-3', - '5': 'IAB19-8', - '6': 'IAB22-1', - '7': 'IAB18-1', - '8': 'IAB12-3', - '9': 'IAB5-1', - '10': 'IAB4-5', - '11': 'IAB13-4', - '12': 'IAB8-7', - '13': 'IAB9-7', - '14': 'IAB7-1', - '15': 'IAB20-18', - '16': 'IAB10-7', - '17': 'IAB19-18', - '18': 'IAB13-6', - '19': 'IAB18-4', - '20': 'IAB1-5', - '21': 'IAB1-6', - '22': 'IAB3-4', - '23': 'IAB19-13', - '24': 'IAB22-2', - '25': 'IAB3-9', - '26': 'IAB17-18', - '27': 'IAB19-6', - '28': 'IAB1-7', - '29': 'IAB9-30', - '30': 'IAB20-7', - '31': 'IAB20-17', - '32': 'IAB7-32', - '33': 'IAB16-5', - '34': 'IAB19-34', - '35': 'IAB11-5', - '36': 'IAB12-3', - '37': 'IAB11-4', - '38': 'IAB12-3', - '39': 'IAB9-30', - '41': 'IAB7-44', - '42': 'IAB7-1', - '43': 'IAB7-30', - '50': 'IAB19-30', - '51': 'IAB17-12', - '52': 'IAB19-30', - '53': 'IAB3-1', - '55': 'IAB13-2', - '56': 'IAB19-30', - '57': 'IAB19-30', - '58': 'IAB7-39', - '59': 'IAB22-1', - '60': 'IAB7-39', - '61': 'IAB21-3', - '62': 'IAB5-1', - '63': 'IAB12-3', - '64': 'IAB20-18', - '65': 'IAB11-2', - '66': 'IAB17-18', - '67': 'IAB9-9', - '68': 'IAB9-5', - '69': 'IAB7-44', - '71': 'IAB22-3', - '73': 'IAB19-30', - '74': 'IAB8-5', - '78': 'IAB22-1', - '85': 'IAB12-2', - '86': 'IAB22-3', - '87': 'IAB11-3', - '112': 'IAB7-32', - '113': 'IAB7-32', - '114': 'IAB7-32', - '115': 'IAB7-32', - '118': 'IAB9-5', - '119': 'IAB9-5', - '120': 'IAB9-5', - '121': 'IAB9-5', - '122': 'IAB9-5', - '123': 'IAB9-5', - '124': 'IAB9-5', - '125': 'IAB9-5', - '126': 'IAB9-5', - '127': 'IAB22-1', - '132': 'IAB1-2', - '133': 'IAB19-30', - '137': 'IAB3-9', - '138': 'IAB19-3', - '140': 'IAB2-3', - '141': 'IAB2-1', - '142': 'IAB2-3', - '143': 'IAB17-13', - '166': 'IAB11-4', - '175': 'IAB3-1', - '176': 'IAB13-4', - '182': 'IAB8-9', - '183': 'IAB3-5' -}; diff --git a/metadata/disclosures/prebid/categoryTranslation.json b/metadata/disclosures/prebid/categoryTranslation.json deleted file mode 100644 index 82934ef440e..00000000000 --- a/metadata/disclosures/prebid/categoryTranslation.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "disclosures": [ - { - "identifier": "iabToFwMappingkey", - "type": "web", - "domains": ["*"], - "purposes": [ - 1 - ] - }, - { - "identifier": "iabToFwMappingkeyPub", - "type": "web", - "domains": ["*"], - "purposes": [ - 1 - ] - } - ], - "domains": [ - { - "domain": "*", - "use": "Category translation mappings are cached in localStorage" - } - ] -} diff --git a/metadata/modules/categoryTranslation.json b/metadata/modules/categoryTranslation.json deleted file mode 100644 index d1aa7a19217..00000000000 --- a/metadata/modules/categoryTranslation.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "NOTICE": "do not edit - this file is autogenerated by `gulp update-metadata`", - "disclosures": { - "https://cdn.jsdelivr.net/gh/prebid/Prebid.js/metadata/disclosures/prebid/categoryTranslation.json": { - "timestamp": "2026-02-06T14:30:25.253Z", - "disclosures": [ - { - "identifier": "iabToFwMappingkey", - "type": "web", - "purposes": [ - 1 - ] - }, - { - "identifier": "iabToFwMappingkeyPub", - "type": "web", - "purposes": [ - 1 - ] - } - ] - } - }, - "components": [ - { - "componentType": "prebid", - "componentName": "categoryTranslation", - "disclosureURL": "https://cdn.jsdelivr.net/gh/prebid/Prebid.js/metadata/disclosures/prebid/categoryTranslation.json" - } - ] -} \ No newline at end of file diff --git a/modules/.submodules.json b/modules/.submodules.json index c8436500f0a..7a195632e06 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -64,10 +64,6 @@ "yandexIdSystem", "zeotapIdPlusIdSystem" ], - "adpod": [ - "freeWheelAdserverVideo", - "gamAdpod" - ], "rtdModule": [ "1plusXRtdProvider", "51DegreesRtdProvider", diff --git a/modules/adoceanBidAdapter.js b/modules/adoceanBidAdapter.js index 410b3c92338..e6b89272bc7 100644 --- a/modules/adoceanBidAdapter.js +++ b/modules/adoceanBidAdapter.js @@ -54,17 +54,6 @@ function buildRequest(bid, gdprConsent) { } payload.spots = 1; } - if (bid.mediaTypes.video.context === 'adpod') { - const durationRangeSec = bid.mediaTypes.video.durationRangeSec; - if (!bid.mediaTypes.video.adPodDurationSec || !isArray(durationRangeSec) || durationRangeSec.length === 0) { - return; - } - const spots = calculateAdPodSpotsNumber(bid.mediaTypes.video.adPodDurationSec, bid.mediaTypes.video.durationRangeSec); - const maxDuration = Math.max(...durationRangeSec); - payload.dur = bid.mediaTypes.video.adPodDurationSec; - payload.maxdur = maxDuration; - payload.spots = spots; - } } else if (bid.mediaTypes.banner) { payload.aosize = parseSizesInput(bid.mediaTypes.banner.sizes).join(','); } @@ -77,12 +66,6 @@ function buildRequest(bid, gdprConsent) { }; } -function calculateAdPodSpotsNumber(adPodDurationSec, durationRangeSec) { - const minAllowedDuration = Math.min(...durationRangeSec); - const numberOfSpots = Math.floor(adPodDurationSec / minAllowedDuration); - return numberOfSpots; -} - function interpretResponse(placementResponse, bidRequest, bids) { const requestId = bidRequest.bidIdMap[placementResponse.id]; if (!placementResponse.error && requestId) { @@ -134,9 +117,6 @@ export const spec = { if (bid.mediaTypes.video.context === 'instream') { return true; } - if (bid.mediaTypes.video.context === 'adpod') { - return !bid.mediaTypes.video.requireExactDuration; - } } return false; }, diff --git a/modules/adpod.js b/modules/adpod.js deleted file mode 100644 index 3d82c91e42e..00000000000 --- a/modules/adpod.js +++ /dev/null @@ -1,657 +0,0 @@ -/** - * This module houses the functionality to evaluate and process adpod adunits/bids. Specifically there are several hooked functions, - * that either supplement the base function (ie to check something additional or unique to adpod objects) or to replace the base function - * entirely when appropriate. - * - * Brief outline of each hook: - * - `callPrebidCacheHook` - for any adpod bids, this function will temporarily hold them in a queue in order to send the bids to Prebid Cache in bulk - * - `checkAdUnitSetupHook` - evaluates the adUnits to ensure that required fields for adpod adUnits are present. Invalid adpod adUntis are removed from the array. - * - `checkVideoBidSetupHook` - evaluates the adpod bid returned from an adaptor/bidder to ensure required fields are populated; also initializes duration bucket field. - * - * To initialize the module, there is an `initAdpodHooks()` function that should be imported and executed by a corresponding `...AdServerVideo` - * module that designed to support adpod video type ads. This import process allows this module to effectively act as a sub-module. - */ - -import { - deepAccess, - generateUUID, - groupBy, - isArray, - isArrayOfNums, - isNumber, - isPlainObject, - logError, - logInfo, - logWarn -} from '../src/utils.js'; -import { - addBidToAuction, - AUCTION_IN_PROGRESS, - getPriceByGranularity, - getPriceGranularity -} from '../src/auction.js'; -import {checkAdUnitSetup} from '../src/prebid.js'; -import {checkVideoBidSetup} from '../src/video.js'; -import {getHook, module, setupBeforeHookFnOnce} from '../src/hook.js'; -import {store} from '../src/videoCache.js'; -import {config} from '../src/config.js'; -import {ADPOD} from '../src/mediaTypes.js'; -import {auctionManager} from '../src/auctionManager.js'; -import { TARGETING_KEYS } from '../src/constants.js'; - -const TARGETING_KEY_PB_CAT_DUR = 'hb_pb_cat_dur'; -const TARGETING_KEY_CACHE_ID = 'hb_cache_id'; - -let queueTimeDelay = 50; -let queueSizeLimit = 5; -const bidCacheRegistry = createBidCacheRegistry(); - -/** - * Create a registry object that stores/manages bids while be held in queue for Prebid Cache. - * @returns registry object with defined accessor functions - */ -function createBidCacheRegistry() { - const registry = {}; - - function setupRegistrySlot(auctionId) { - registry[auctionId] = {}; - registry[auctionId].bidStorage = new Set(); - registry[auctionId].queueDispatcher = createDispatcher(queueTimeDelay); - registry[auctionId].initialCacheKey = generateUUID(); - } - - return { - addBid: function (bid) { - // create parent level object based on auction ID (in case there are concurrent auctions running) to store objects for that auction - if (!registry[bid.auctionId]) { - setupRegistrySlot(bid.auctionId); - } - registry[bid.auctionId].bidStorage.add(bid); - }, - removeBid: function (bid) { - registry[bid.auctionId].bidStorage.delete(bid); - }, - getBids: function (bid) { - return registry[bid.auctionId] && registry[bid.auctionId].bidStorage.values(); - }, - getQueueDispatcher: function (bid) { - return registry[bid.auctionId] && registry[bid.auctionId].queueDispatcher; - }, - setupInitialCacheKey: function (bid) { - if (!registry[bid.auctionId]) { - registry[bid.auctionId] = {}; - registry[bid.auctionId].initialCacheKey = generateUUID(); - } - }, - getInitialCacheKey: function (bid) { - return registry[bid.auctionId] && registry[bid.auctionId].initialCacheKey; - } - } -} - -/** - * Creates a function that when called updates the bid queue and extends the running timer (when called subsequently). - * Once the time threshold for the queue (defined by queueSizeLimit) is reached, the queue will be flushed by calling the `firePrebidCacheCall` function. - * If there is a long enough time between calls (based on timeoutDration), the queue will automatically flush itself. - * @param {Number} timeoutDuration number of milliseconds to pass before timer expires and current bid queue is flushed - * @returns {Function} - */ -function createDispatcher(timeoutDuration) { - let timeout; - let counter = 1; - - return function (auctionInstance, bidListArr, afterBidAdded, killQueue) { - const context = this; - - var callbackFn = function () { - firePrebidCacheCall.call(context, auctionInstance, bidListArr, afterBidAdded); - }; - - clearTimeout(timeout); - - if (!killQueue) { - // want to fire off the queue if either: size limit is reached or time has passed since last call to dispatcher - if (counter === queueSizeLimit) { - counter = 1; - callbackFn(); - } else { - counter++; - timeout = setTimeout(callbackFn, timeoutDuration); - } - } else { - counter = 1; - } - }; -} - -function getPricePartForAdpodKey(bid) { - let pricePart - const prioritizeDeals = config.getConfig('adpod.prioritizeDeals'); - if (prioritizeDeals && deepAccess(bid, 'video.dealTier')) { - const adpodDealPrefix = config.getConfig(`adpod.dealTier.${bid.bidderCode}.prefix`); - pricePart = (adpodDealPrefix) ? adpodDealPrefix + deepAccess(bid, 'video.dealTier') : deepAccess(bid, 'video.dealTier'); - } else { - const granularity = getPriceGranularity(bid); - pricePart = getPriceByGranularity(granularity)(bid); - } - return pricePart -} - -/** - * This function reads certain fields from the bid to generate a specific key used for caching the bid in Prebid Cache - * @param {Object} bid bid object to update - * @param {Boolean} brandCategoryExclusion value read from setConfig; influences whether category is required or not - */ -function attachPriceIndustryDurationKeyToBid(bid, brandCategoryExclusion) { - const initialCacheKey = bidCacheRegistry.getInitialCacheKey(bid); - const duration = deepAccess(bid, 'video.durationBucket'); - const pricePart = getPricePartForAdpodKey(bid); - let pcd; - - if (brandCategoryExclusion) { - const category = deepAccess(bid, 'meta.adServerCatId'); - pcd = `${pricePart}_${category}_${duration}s`; - } else { - pcd = `${pricePart}_${duration}s`; - } - - if (!bid.adserverTargeting) { - bid.adserverTargeting = {}; - } - bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] = pcd; - bid.adserverTargeting[TARGETING_KEY_CACHE_ID] = initialCacheKey; - bid.videoCacheKey = initialCacheKey; - bid.customCacheKey = `${pcd}_${initialCacheKey}`; -} - -/** - * Updates the running queue for the associated auction. - * Does a check to ensure the auction is still running; if it's not - the previously running queue is killed. - * @param {*} auctionInstance running context of the auction - * @param {Object} bidResponse bid object being added to queue - * @param {Function} afterBidAdded callback function used when Prebid Cache responds - */ -function updateBidQueue(auctionInstance, bidResponse, afterBidAdded) { - const bidListIter = bidCacheRegistry.getBids(bidResponse); - - if (bidListIter) { - const bidListArr = Array.from(bidListIter); - const callDispatcher = bidCacheRegistry.getQueueDispatcher(bidResponse); - const killQueue = !!(auctionInstance.getAuctionStatus() !== AUCTION_IN_PROGRESS); - callDispatcher(auctionInstance, bidListArr, afterBidAdded, killQueue); - } else { - logWarn('Attempted to cache a bid from an unknown auction. Bid:', bidResponse); - } -} - -/** - * Small helper function to remove bids from internal storage; normally b/c they're about to sent to Prebid Cache for processing. - * @param {Array[Object]} bidResponses list of bids to remove - */ -function removeBidsFromStorage(bidResponses) { - for (let i = 0; i < bidResponses.length; i++) { - bidCacheRegistry.removeBid(bidResponses[i]); - } -} - -/** - * This function will send a list of bids to Prebid Cache. It also removes the same bids from the internal bidCacheRegistry - * to maintain which bids are in queue. - * If the bids are successfully cached, they will be added to the respective auction. - * @param {*} auctionInstance running context of the auction - * @param {Array[Object]} bidList list of bid objects that need to be sent to Prebid Cache - * @param {Function} afterBidAdded callback function used when Prebid Cache responds - */ -function firePrebidCacheCall(auctionInstance, bidList, afterBidAdded) { - // remove entries now so other incoming bids won't accidentally have a stale version of the list while PBC is processing the current submitted list - removeBidsFromStorage(bidList); - - store(bidList, function (error, cacheIds) { - if (error) { - logWarn(`Failed to save to the video cache: ${error}. Video bid(s) must be discarded.`); - } else { - for (let i = 0; i < cacheIds.length; i++) { - // when uuid in response is empty string then the key already existed, so this bid wasn't cached - if (cacheIds[i].uuid !== '') { - addBidToAuction(auctionInstance, bidList[i]); - } else { - logInfo(`Detected a bid was not cached because the custom key was already registered. Attempted to use key: ${bidList[i].customCacheKey}. Bid was: `, bidList[i]); - } - afterBidAdded(); - } - } - }); -} - -/** - * This is the main hook function to handle adpod bids; maintains the logic to temporarily hold bids in a queue in order to send bulk requests to Prebid Cache. - * @param {Function} fn reference to original function (used by hook logic) - * @param {*} auctionInstance running context of the auction - * @param {Object} bidResponse incoming bid; if adpod, will be processed through hook function. If not adpod, returns to original function. - * @param {Function} afterBidAdded callback function used when Prebid Cache responds - * @param {Object} videoConfig mediaTypes.video from the bid's adUnit - */ -export function callPrebidCacheHook(fn, auctionInstance, bidResponse, afterBidAdded, videoConfig) { - if (videoConfig && videoConfig.context === ADPOD) { - const brandCategoryExclusion = config.getConfig('adpod.brandCategoryExclusion'); - const adServerCatId = deepAccess(bidResponse, 'meta.adServerCatId'); - if (!adServerCatId && brandCategoryExclusion) { - logWarn('Detected a bid without meta.adServerCatId while setConfig({adpod.brandCategoryExclusion}) was enabled. This bid has been rejected:', bidResponse); - afterBidAdded(); - } else { - if (config.getConfig('adpod.deferCaching') === false) { - bidCacheRegistry.addBid(bidResponse); - attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); - - updateBidQueue(auctionInstance, bidResponse, afterBidAdded); - } else { - // generate targeting keys for bid - bidCacheRegistry.setupInitialCacheKey(bidResponse); - attachPriceIndustryDurationKeyToBid(bidResponse, brandCategoryExclusion); - - // add bid to auction - addBidToAuction(auctionInstance, bidResponse); - afterBidAdded(); - } - } - } else { - fn.call(this, auctionInstance, bidResponse, afterBidAdded, videoConfig); - } -} - -/** - * This hook function will review the adUnit setup and verify certain required values are present in any adpod adUnits. - * If the fields are missing or incorrectly setup, the adUnit is removed from the list. - * @param {Function} fn reference to original function (used by hook logic) - * @param {Array[Object]} adUnits list of adUnits to be evaluated - * @returns {Array[Object]} list of adUnits that passed the check - */ -export function checkAdUnitSetupHook(fn, adUnits) { - const goodAdUnits = adUnits.filter(adUnit => { - const mediaTypes = deepAccess(adUnit, 'mediaTypes'); - const videoConfig = deepAccess(mediaTypes, 'video'); - if (videoConfig && videoConfig.context === ADPOD) { - // run check to see if other mediaTypes are defined (ie multi-format); reject adUnit if so - if (Object.keys(mediaTypes).length > 1) { - logWarn(`Detected more than one mediaType in adUnitCode: ${adUnit.code} while attempting to define an 'adpod' video adUnit. 'adpod' adUnits cannot be mixed with other mediaTypes. This adUnit will be removed from the auction.`); - return false; - } - - let errMsg = `Detected missing or incorrectly setup fields for an adpod adUnit. Please review the following fields of adUnitCode: ${adUnit.code}. This adUnit will be removed from the auction.`; - - const playerSize = !!( - ( - videoConfig.playerSize && ( - isArrayOfNums(videoConfig.playerSize, 2) || ( - isArray(videoConfig.playerSize) && videoConfig.playerSize.every(sz => isArrayOfNums(sz, 2)) - ) - ) - ) || (videoConfig.sizeConfig) - ); - const adPodDurationSec = !!(videoConfig.adPodDurationSec && isNumber(videoConfig.adPodDurationSec) && videoConfig.adPodDurationSec > 0); - const durationRangeSec = !!(videoConfig.durationRangeSec && isArrayOfNums(videoConfig.durationRangeSec) && videoConfig.durationRangeSec.every(range => range > 0)); - - if (!playerSize || !adPodDurationSec || !durationRangeSec) { - errMsg += (!playerSize) ? '\nmediaTypes.video.playerSize' : ''; - errMsg += (!adPodDurationSec) ? '\nmediaTypes.video.adPodDurationSec' : ''; - errMsg += (!durationRangeSec) ? '\nmediaTypes.video.durationRangeSec' : ''; - logWarn(errMsg); - return false; - } - } - return true; - }); - adUnits = goodAdUnits; - fn.call(this, adUnits); -} - -/** - * This check evaluates the incoming bid's `video.durationSeconds` field and tests it against specific logic depending on adUnit config. Summary of logic below: - * when adUnit.mediaTypes.video.requireExactDuration is true - * - only bids that exactly match those listed values are accepted (don't round at all). - * - populate the `bid.video.durationBucket` field with the matching duration value - * when adUnit.mediaTypes.video.requireExactDuration is false - * - round the duration to the next highest specified duration value based on adunit. If the duration is above a range within a set buffer, that bid falls down into that bucket. - * (eg if range was [5, 15, 30] -> 2s is rounded to 5s; 17s is rounded back to 15s; 18s is rounded up to 30s) - * - if the bid is above the range of the listed durations (and outside the buffer), reject the bid - * - set the rounded duration value in the `bid.video.durationBucket` field for accepted bids - * @param {Object} videoMediaType 'mediaTypes.video' associated to bidResponse - * @param {Object} bidResponse incoming bidResponse being evaluated by bidderFactory - * @returns {boolean} return false if bid duration is deemed invalid as per adUnit configuration; return true if fine - */ -function checkBidDuration(videoMediaType, bidResponse) { - const buffer = 2; - const bidDuration = deepAccess(bidResponse, 'video.durationSeconds'); - const adUnitRanges = videoMediaType.durationRangeSec; - adUnitRanges.sort((a, b) => a - b); // ensure the ranges are sorted in numeric order - - if (!videoMediaType.requireExactDuration) { - const max = Math.max(...adUnitRanges); - if (bidDuration <= (max + buffer)) { - const nextHighestRange = ((adUnitRanges) || []).find(range => (range + buffer) >= bidDuration); - bidResponse.video.durationBucket = nextHighestRange; - } else { - logWarn(`Detected a bid with a duration value outside the accepted ranges specified in adUnit.mediaTypes.video.durationRangeSec. Rejecting bid: `, bidResponse); - return false; - } - } else { - if (((adUnitRanges) || []).find(range => range === bidDuration)) { - bidResponse.video.durationBucket = bidDuration; - } else { - logWarn(`Detected a bid with a duration value not part of the list of accepted ranges specified in adUnit.mediaTypes.video.durationRangeSec. Exact match durations must be used for this adUnit. Rejecting bid: `, bidResponse); - return false; - } - } - return true; -} - -/** - * This hooked function evaluates an adpod bid and determines if the required fields are present. - * If it's found to not be an adpod bid, it will return to original function via hook logic - * @param {Function} fn reference to original function (used by hook logic) - * @param {Object} bid incoming bid object - * @param {Object} adUnit adUnit object of associated bid - * @param {Object} videoMediaType copy of the `bidRequest.mediaTypes.video` object; used in original function - * @param {String} context value of the `bidRequest.mediaTypes.video.context` field; used in original function - * @returns {boolean} this return is only used for adpod bids - */ -export function checkVideoBidSetupHook(fn, bid, adUnit, videoMediaType, context) { - if (context === ADPOD) { - let result = true; - const brandCategoryExclusion = config.getConfig('adpod.brandCategoryExclusion'); - if (brandCategoryExclusion && !deepAccess(bid, 'meta.primaryCatId')) { - result = false; - } - - if (deepAccess(bid, 'video')) { - if (!deepAccess(bid, 'video.context') || bid.video.context !== ADPOD) { - result = false; - } - - if (!deepAccess(bid, 'video.durationSeconds') || bid.video.durationSeconds <= 0) { - result = false; - } else { - const isBidGood = checkBidDuration(videoMediaType, bid); - if (!isBidGood) result = false; - } - } - - if (!config.getConfig('cache.url') && bid.vastXml && !bid.vastUrl) { - logError(` - This bid contains only vastXml and will not work when a prebid cache url is not specified. - Try enabling prebid cache with pbjs.setConfig({ cache: {url: "..."} }); - `); - result = false; - }; - - fn.bail(result); - } else { - fn.call(this, bid, adUnit, videoMediaType, context); - } -} - -/** - * This function reads the (optional) settings for the adpod as set from the setConfig() - * @param {Object} config contains the config settings for adpod module - */ -export function adpodSetConfig(config) { - if (config.bidQueueTimeDelay !== undefined) { - if (typeof config.bidQueueTimeDelay === 'number' && config.bidQueueTimeDelay > 0) { - queueTimeDelay = config.bidQueueTimeDelay; - } else { - logWarn(`Detected invalid value for adpod.bidQueueTimeDelay in setConfig; must be a positive number. Using default: ${queueTimeDelay}`) - } - } - - if (config.bidQueueSizeLimit !== undefined) { - if (typeof config.bidQueueSizeLimit === 'number' && config.bidQueueSizeLimit > 0) { - queueSizeLimit = config.bidQueueSizeLimit; - } else { - logWarn(`Detected invalid value for adpod.bidQueueSizeLimit in setConfig; must be a positive number. Using default: ${queueSizeLimit}`) - } - } -} -config.getConfig('adpod', config => adpodSetConfig(config.adpod)); - -/** - * This function initializes the adpod module's hooks. This is called by the corresponding adserver video module. - * PBJS 10: Adding a deprecation warning - */ -function initAdpodHooks() { - logWarn('DEPRECATION NOTICE: Prebid.js is not aware of any transactions requiring the ADPOD video mediatype context. Please open a github issue if you are relying on it as support for it may be removed in a future version.'); - - setupBeforeHookFnOnce(getHook('callPrebidCache'), callPrebidCacheHook); - setupBeforeHookFnOnce(checkAdUnitSetup, checkAdUnitSetupHook); - setupBeforeHookFnOnce(checkVideoBidSetup, checkVideoBidSetupHook); -} - -initAdpodHooks() - -/** - * - * @param {Array[Object]} bids list of 'winning' bids that need to be cached - * @param {Function} callback send the cached bids (or error) back to adserverVideoModule for further processing - }} - */ -export function callPrebidCacheAfterAuction(bids, callback) { - // will call PBC here and execute cb param to initialize player code - store(bids, function (error, cacheIds) { - if (error) { - callback(error, null); - } else { - const successfulCachedBids = []; - for (let i = 0; i < cacheIds.length; i++) { - if (cacheIds[i] !== '') { - successfulCachedBids.push(bids[i]); - } - } - callback(null, successfulCachedBids); - } - }) -} - -/** - * Compare function to be used in sorting long-form bids. This will compare bids on price per second. - */ -export function sortByPricePerSecond(a, b) { - if (a.adserverTargeting[TARGETING_KEYS.PRICE_BUCKET] / a.video.durationBucket < b.adserverTargeting[TARGETING_KEYS.PRICE_BUCKET] / b.video.durationBucket) { - return 1; - } - if (a.adserverTargeting[TARGETING_KEYS.PRICE_BUCKET] / a.video.durationBucket > b.adserverTargeting[TARGETING_KEYS.PRICE_BUCKET] / b.video.durationBucket) { - return -1; - } - return 0; -} - -/** - * This function returns targeting keyvalue pairs for long-form adserver modules. Freewheel and GAM are currently supporting Prebid long-form - * @param {Object} options - Options for targeting. - * @param {Array} options.codes - Array of ad unit codes. - * @param {function} options.callback - Callback function to handle the targeting key-value pairs. - * @returns {Object} Targeting key-value pairs for ad unit codes. - */ -export function getTargeting({ codes, callback } = {}) { - if (!callback) { - logError('No callback function was defined in the getTargeting call. Aborting getTargeting().'); - return; - } - codes = codes || []; - const adPodAdUnits = getAdPodAdUnits(codes); - const bidsReceived = auctionManager.getBidsReceived(); - const competiveExclusionEnabled = config.getConfig('adpod.brandCategoryExclusion'); - const deferCachingSetting = config.getConfig('adpod.deferCaching'); - const deferCachingEnabled = (typeof deferCachingSetting === 'boolean') ? deferCachingSetting : true; - - let bids = getBidsForAdpod(bidsReceived, adPodAdUnits); - bids = (competiveExclusionEnabled || deferCachingEnabled) ? getExclusiveBids(bids) : bids; - - const prioritizeDeals = config.getConfig('adpod.prioritizeDeals'); - if (prioritizeDeals) { - const [otherBids, highPriorityDealBids] = bids.reduce((partitions, bid) => { - const bidDealTier = deepAccess(bid, 'video.dealTier'); - const minDealTier = config.getConfig(`adpod.dealTier.${bid.bidderCode}.minDealTier`); - if (minDealTier && bidDealTier) { - if (bidDealTier >= minDealTier) { - partitions[1].push(bid) - } else { - partitions[0].push(bid) - } - } else if (bidDealTier) { - partitions[1].push(bid) - } else { - partitions[0].push(bid); - } - return partitions; - }, [[], []]); - highPriorityDealBids.sort(sortByPricePerSecond); - otherBids.sort(sortByPricePerSecond); - bids = highPriorityDealBids.concat(otherBids); - } else { - bids.sort(sortByPricePerSecond); - } - - const targeting = {}; - if (deferCachingEnabled === false) { - adPodAdUnits.forEach((adUnit) => { - const adPodTargeting = []; - let adPodDurationSeconds = deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); - - bids - .filter((bid) => bid.adUnitCode === adUnit.code) - .forEach((bid, index, arr) => { - if (bid.video.durationBucket <= adPodDurationSeconds) { - adPodTargeting.push({ - [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] - }); - adPodDurationSeconds -= bid.video.durationBucket; - } - if (index === arr.length - 1 && adPodTargeting.length > 0) { - adPodTargeting.push({ - [TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID] - }); - } - }); - targeting[adUnit.code] = adPodTargeting; - }); - - callback(null, targeting); - } else { - const bidsToCache = []; - adPodAdUnits.forEach((adUnit) => { - let adPodDurationSeconds = deepAccess(adUnit, 'mediaTypes.video.adPodDurationSec'); - - bids - .filter((bid) => bid.adUnitCode === adUnit.code) - .forEach((bid) => { - if (bid.video.durationBucket <= adPodDurationSeconds) { - bidsToCache.push(bid); - adPodDurationSeconds -= bid.video.durationBucket; - } - }); - }); - - callPrebidCacheAfterAuction(bidsToCache, function (error, bidsSuccessfullyCached) { - if (error) { - callback(error, null); - } else { - const groupedBids = groupBy(bidsSuccessfullyCached, 'adUnitCode'); - Object.keys(groupedBids).forEach((adUnitCode) => { - const adPodTargeting = []; - - groupedBids[adUnitCode].forEach((bid, index, arr) => { - adPodTargeting.push({ - [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] - }); - - if (index === arr.length - 1 && adPodTargeting.length > 0) { - adPodTargeting.push({ - [TARGETING_KEY_CACHE_ID]: bid.adserverTargeting[TARGETING_KEY_CACHE_ID] - }); - } - }); - targeting[adUnitCode] = adPodTargeting; - }); - - callback(null, targeting); - } - }); - } - return targeting; -} - -/** - * This function returns the adunit of mediaType adpod - * @param {Array} codes adUnitCodes - * @returns {Array[Object]} adunits of mediaType adpod - */ -function getAdPodAdUnits(codes) { - return auctionManager.getAdUnits() - .filter((adUnit) => deepAccess(adUnit, 'mediaTypes.video.context') === ADPOD) - .filter((adUnit) => (codes.length > 0) ? codes.indexOf(adUnit.code) !== -1 : true); -} - -/** - * This function will create compare function to sort on object property - * @param {string} property - * @returns {function} compare function to be used in sorting - */ -function compareOn(property) { - return function compare(a, b) { - if (a[property] < b[property]) { - return 1; - } - if (a[property] > b[property]) { - return -1; - } - return 0; - } -} - -/** - * This function removes bids of same category. It will be used when competitive exclusion is enabled. - * @param {Array[Object]} bidsReceived - * @returns {Array[Object]} unique category bids - */ -function getExclusiveBids(bidsReceived) { - let bids = bidsReceived - .map((bid) => Object.assign({}, bid, { [TARGETING_KEY_PB_CAT_DUR]: bid.adserverTargeting[TARGETING_KEY_PB_CAT_DUR] })); - bids = groupBy(bids, TARGETING_KEY_PB_CAT_DUR); - const filteredBids = []; - Object.keys(bids).forEach((targetingKey) => { - bids[targetingKey].sort(compareOn('responseTimestamp')); - filteredBids.push(bids[targetingKey][0]); - }); - return filteredBids; -} - -/** - * This function returns bids for adpod adunits - * @param {Array[Object]} bidsReceived - * @param {Array[Object]} adPodAdUnits - * @returns {Array[Object]} bids of mediaType adpod - */ -function getBidsForAdpod(bidsReceived, adPodAdUnits) { - const adUnitCodes = adPodAdUnits.map((adUnit) => adUnit.code); - return bidsReceived - .filter((bid) => adUnitCodes.indexOf(bid.adUnitCode) !== -1 && (bid.video && bid.video.context === ADPOD)) -} - -const sharedMethods = { - TARGETING_KEY_PB_CAT_DUR: TARGETING_KEY_PB_CAT_DUR, - TARGETING_KEY_CACHE_ID: TARGETING_KEY_CACHE_ID, - 'getTargeting': getTargeting -} -Object.freeze(sharedMethods); - -module('adpod', function shareAdpodUtilities(...args) { - if (!isPlainObject(args[0])) { - logError('Adpod module needs plain object to share methods with submodule'); - return; - } - function addMethods(object, func) { - for (const name in func) { - object[name] = func[name]; - } - } - addMethods(args[0], sharedMethods); -}); diff --git a/modules/adtelligentBidAdapter.js b/modules/adtelligentBidAdapter.js index 010d2b74409..b7cd1a1dcda 100644 --- a/modules/adtelligentBidAdapter.js +++ b/modules/adtelligentBidAdapter.js @@ -1,6 +1,6 @@ import {_map, deepAccess, flatten, isArray, parseSizesInput} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {ADPOD, BANNER, VIDEO} from '../src/mediaTypes.js'; +import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; import {Renderer} from '../src/Renderer.js'; import {chunk} from '../libraries/chunk/chunk.js'; @@ -187,14 +187,6 @@ function prepareBidRequests(bidReq) { bidReqParams.GPID = gpid; } - if (mediaType === VIDEO) { - const context = deepAccess(bidReq, 'mediaTypes.video.context'); - - if (context === ADPOD) { - bidReqParams.Adpod = deepAccess(bidReq, 'mediaTypes.video'); - } - } - return bidReqParams; } @@ -237,18 +229,6 @@ function createBid(bidResponse, bidRequest) { adUrl: bidResponse.adUrl, }); } - if (context === ADPOD) { - Object.assign(bid, { - meta: { - primaryCatId: bidResponse.primaryCatId, - }, - video: { - context: ADPOD, - durationSeconds: bidResponse.durationSeconds - } - }); - } - Object.assign(bid, { vastUrl: bidResponse.vastUrl }); diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 0204c3e02b7..c710789640d 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -21,19 +21,18 @@ import { import {Renderer} from '../src/Renderer.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {ADPOD, BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; +import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {INSTREAM, OUTSTREAM} from '../src/video.js'; import {getStorageManager} from '../src/storageManager.js'; import {bidderSettings} from '../src/bidderSettings.js'; import {hasPurpose1Consent} from '../src/utils/gdpr.js'; import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; -import {APPNEXUS_CATEGORY_MAPPING} from '../libraries/categoryTranslationMapping/index.js'; import { convertKeywordStringToANMap, getANKewyordParamFromMaps, getANKeywordParam } from '../libraries/appnexusUtils/anKeywords.js'; -import {convertCamelToUnderscore, fill, appnexusAliases} from '../libraries/appnexusUtils/anUtils.js'; +import {convertCamelToUnderscore, appnexusAliases} from '../libraries/appnexusUtils/anUtils.js'; import {convertTypes} from '../libraries/transformParamsUtils/convertTypes.js'; import {chunk} from '../libraries/chunk/chunk.js'; @@ -295,10 +294,6 @@ export const spec = { } } - if (config.getConfig('adpod.brandCategoryExclusion')) { - payload.brand_category_uniqueness = true; - } - if (debugObjParams.enabled) { payload.debug = debugObjParams; logInfo('AppNexus Debug Auction Settings:\n\n' + JSON.stringify(debugObjParams, null, 4)); @@ -350,18 +345,6 @@ export const spec = { payload.referrer_detection = refererinfo; } - if (FEATURES.VIDEO) { - const hasAdPodBid = ((bidRequests) || []).find(hasAdPod); - if (hasAdPodBid) { - bidRequests.filter(hasAdPod).forEach(adPodBid => { - const adPodTags = createAdPodRequest(tags, adPodBid); - // don't need the original adpod placement because it's in adPodTags - const nonPodTags = payload.tags.filter(tag => tag.uuid !== adPodBid.bidId); - payload.tags = [...nonPodTags, ...adPodTags]; - }); - } - } - if (bidRequests[0].userIdAsEids?.length > 0) { const eids = []; bidRequests[0].userIdAsEids.forEach(eid => { @@ -612,7 +595,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { } if (FEATURES.VIDEO && rtbBid.rtb.video) { - // shared video properties used for all 3 contexts + // shared video properties used for both stream contexts Object.assign(bid, { width: rtbBid.rtb.video.player_width, height: rtbBid.rtb.video.player_height, @@ -622,17 +605,6 @@ function newBid(serverBid, rtbBid, bidderRequest) { const videoContext = deepAccess(bidRequest, 'mediaTypes.video.context'); switch (videoContext) { - case ADPOD: - const primaryCatId = (APPNEXUS_CATEGORY_MAPPING[rtbBid.brand_category_id]) ? APPNEXUS_CATEGORY_MAPPING[rtbBid.brand_category_id] : null; - bid.meta = Object.assign({}, bid.meta, { primaryCatId }); - const dealTier = rtbBid.deal_priority; - bid.video = { - context: ADPOD, - durationSeconds: Math.floor(rtbBid.rtb.video.duration_ms / 1000), - dealTier - }; - bid.vastUrl = rtbBid.rtb.video.asset_url; - break; case OUTSTREAM: bid.adResponse = serverBid; bid.adResponse.ad = bid.adResponse.ads[0]; @@ -934,11 +906,7 @@ function bidToTag(bid) { const videoMediaType = deepAccess(bid, `mediaTypes.${VIDEO}`); const context = deepAccess(bid, 'mediaTypes.video.context'); - if (videoMediaType && context === 'adpod') { - tag.hb_source = 7; - } else { - tag.hb_source = 1; - } + tag.hb_source = 1; if (bid.mediaType === VIDEO || videoMediaType) { tag.ad_types.push(VIDEO); } @@ -1154,14 +1122,6 @@ function hasDebug(bid) { return !!bid.debug } -function hasAdPod(bid) { - return ( - bid.mediaTypes && - bid.mediaTypes.video && - bid.mediaTypes.video.context === ADPOD - ); -} - function hasOmidSupport(bid) { let hasOmid = false; const bidderParams = bid.params; @@ -1175,54 +1135,6 @@ function hasOmidSupport(bid) { return hasOmid; } -/** - * Expand an adpod placement into a set of request objects according to the - * total adpod duration and the range of duration seconds. Sets minduration/ - * maxduration video property according to requireExactDuration configuration - */ -function createAdPodRequest(tags, adPodBid) { - const { durationRangeSec, requireExactDuration } = adPodBid.mediaTypes.video; - - const numberOfPlacements = getAdPodPlacementNumber(adPodBid.mediaTypes.video); - const maxDuration = Math.max(...durationRangeSec); - - const tagToDuplicate = tags.filter(tag => tag.uuid === adPodBid.bidId); - const request = fill(...tagToDuplicate, numberOfPlacements); - - if (requireExactDuration) { - const divider = Math.ceil(numberOfPlacements / durationRangeSec.length); - const chunked = chunk(request, divider); - - // each configured duration is set as min/maxduration for a subset of requests - durationRangeSec.forEach((duration, index) => { - chunked[index].forEach(tag => { - setVideoProperty(tag, 'minduration', duration); - setVideoProperty(tag, 'maxduration', duration); - }); - }); - } else { - // all maxdurations should be the same - request.forEach(tag => setVideoProperty(tag, 'maxduration', maxDuration)); - } - - return request; -} - -function getAdPodPlacementNumber(videoParams) { - const { adPodDurationSec, durationRangeSec, requireExactDuration } = videoParams; - const minAllowedDuration = Math.min(...durationRangeSec); - const numberOfPlacements = Math.floor(adPodDurationSec / minAllowedDuration); - - return requireExactDuration - ? Math.max(numberOfPlacements, durationRangeSec.length) - : numberOfPlacements; -} - -function setVideoProperty(tag, key, value) { - if (isEmpty(tag.video)) { tag.video = {}; } - tag.video[key] = value; -} - function getRtbBid(tag) { return tag && tag.ads && tag.ads.length && ((tag.ads) || []).find(ad => ad.rtb); } diff --git a/modules/categoryTranslation.js b/modules/categoryTranslation.js deleted file mode 100644 index a0ef902412e..00000000000 --- a/modules/categoryTranslation.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * This module translates iab category to freewheel industry using translation mapping file - * Publisher can set translation file by using setConfig method - * - * Example: - * config.setConfig({ - * 'brandCategoryTranslation': { - * 'translationFile': 'http://sample.com' - * } - * }); - * If publisher has not defined translation file than prebid will use default prebid translation file provided here //cdn.jsdelivr.net/gh/prebid/category-mapping-file@1/freewheel-mapping.json - */ - -import {config} from '../src/config.js'; -import {hook, setupBeforeHookFnOnce, ready} from '../src/hook.js'; -import {ajax} from '../src/ajax.js'; -import {logError, timestamp} from '../src/utils.js'; -import {addBidResponse} from '../src/auction.js'; -import {getCoreStorageManager} from '../src/storageManager.js'; -import {timedBidResponseHook} from '../src/utils/perfMetrics.js'; - -export const storage = getCoreStorageManager('categoryTranslation'); -const DEFAULT_TRANSLATION_FILE_URL = 'https://cdn.jsdelivr.net/gh/prebid/category-mapping-file@1/freewheel-mapping.json'; -const DEFAULT_IAB_TO_FW_MAPPING_KEY = 'iabToFwMappingkey'; -const DEFAULT_IAB_TO_FW_MAPPING_KEY_PUB = 'iabToFwMappingkeyPub'; -const refreshInDays = 1; - -export const registerAdserver = hook('async', function(adServer) { - let url; - if (adServer === 'freewheel') { - url = DEFAULT_TRANSLATION_FILE_URL; - initTranslation(url, DEFAULT_IAB_TO_FW_MAPPING_KEY); - } -}, 'registerAdserver'); - -ready.then(() => registerAdserver()); - -export const getAdserverCategoryHook = timedBidResponseHook('categoryTranslation', function getAdserverCategoryHook(fn, adUnitCode, bid, reject) { - if (!bid) { - return fn.call(this, adUnitCode, bid, reject); // if no bid, call original and let it display warnings - } - - if (!config.getConfig('adpod.brandCategoryExclusion')) { - return fn.call(this, adUnitCode, bid, reject); - } - - const localStorageKey = (config.getConfig('brandCategoryTranslation.translationFile')) ? DEFAULT_IAB_TO_FW_MAPPING_KEY_PUB : DEFAULT_IAB_TO_FW_MAPPING_KEY; - - if (bid.meta && !bid.meta.adServerCatId) { - let mapping = storage.getDataFromLocalStorage(localStorageKey); - if (mapping) { - try { - mapping = JSON.parse(mapping); - } catch (error) { - logError('Failed to parse translation mapping file'); - } - if (bid.meta.primaryCatId && mapping['mapping'] && mapping['mapping'][bid.meta.primaryCatId]) { - bid.meta.adServerCatId = mapping['mapping'][bid.meta.primaryCatId]['id']; - } else { - // This bid will be automatically ignored by adpod module as adServerCatId was not found - bid.meta.adServerCatId = undefined; - } - } else { - logError('Translation mapping data not found in local storage'); - } - } - fn.call(this, adUnitCode, bid, reject); -}); - -export function initTranslation(url, localStorageKey) { - setupBeforeHookFnOnce(addBidResponse, getAdserverCategoryHook, 50); - let mappingData = storage.getDataFromLocalStorage(localStorageKey); - try { - mappingData = mappingData ? JSON.parse(mappingData) : undefined; - if (!mappingData || timestamp() > mappingData.lastUpdated + refreshInDays * 24 * 60 * 60 * 1000) { - ajax(url, - { - success: (response) => { - try { - response = JSON.parse(response); - response['lastUpdated'] = timestamp(); - storage.setDataInLocalStorage(localStorageKey, JSON.stringify(response)); - } catch (error) { - logError('Failed to parse translation mapping file'); - } - }, - error: () => { - logError('Failed to load brand category translation file.') - } - }, - ); - } - } catch (error) { - logError('Failed to parse translation mapping file'); - } -} - -function setConfig(config) { - if (config.translationFile) { - // if publisher has defined the translation file, preload that file here - initTranslation(config.translationFile, DEFAULT_IAB_TO_FW_MAPPING_KEY_PUB); - } -} - -config.getConfig('brandCategoryTranslation', config => setConfig(config.brandCategoryTranslation)); diff --git a/modules/freeWheelAdserverVideo.js b/modules/freeWheelAdserverVideo.js deleted file mode 100644 index cb4bd938373..00000000000 --- a/modules/freeWheelAdserverVideo.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * This module adds Freewheel support for Video to Prebid. - */ - -import { registerVideoSupport } from '../src/adServerManager.js'; -import { getHook, submodule } from '../src/hook.js'; - -export const adpodUtils = {}; -export function notifyTranslationModule(fn) { - fn.call(this, 'freewheel'); -} - -getHook('registerAdserver').before(notifyTranslationModule); - -registerVideoSupport('freewheel', { - getTargeting: (args) => adpodUtils.getTargeting(args) -}); - -submodule('adpod', adpodUtils); diff --git a/modules/gamAdServerVideo.js b/modules/gamAdServerVideo.js index b97f4ff598c..abf1a5d6b25 100644 --- a/modules/gamAdServerVideo.js +++ b/modules/gamAdServerVideo.js @@ -9,7 +9,6 @@ import { auctionManager } from '../src/auctionManager.js'; import { config } from '../src/config.js'; import { EVENTS } from '../src/constants.js'; import * as events from '../src/events.js'; -import { getHook } from '../src/hook.js'; import { getRefererInfo } from '../src/refererDetection.js'; import { targeting } from '../src/targeting.js'; import { @@ -183,12 +182,6 @@ export function buildGamVideoUrl(options) { return buildUrl(Object.assign({}, GAM_ENDPOINT, urlComponents, { search: queryParams })); } -export function notifyTranslationModule(fn) { - fn.call(this, 'dfp'); -} - -if (config.getConfig('brandCategoryTranslation.translationFile')) { getHook('registerAdserver').before(notifyTranslationModule); } - /** * Builds a video url from a base dfp video url and a winning bid, appending * Prebid-specific key-values. diff --git a/modules/gamAdpod.js b/modules/gamAdpod.js deleted file mode 100644 index c21c71c0c3c..00000000000 --- a/modules/gamAdpod.js +++ /dev/null @@ -1,95 +0,0 @@ -import {submodule} from '../src/hook.js'; -import {buildUrl, deepAccess, formatQS, logError, parseSizesInput} from '../src/utils.js'; -import {auctionManager} from '../src/auctionManager.js'; -import {DEFAULT_GAM_PARAMS, GAM_ENDPOINT, gdprParams} from '../libraries/gamUtils/gamUtils.js'; -import {registerVideoSupport} from '../src/adServerManager.js'; - -export const adpodUtils = {}; - -/** - * @typedef {Object} DfpAdpodOptions - * - * @param {string} code Ad Unit code - * @param {Object} params Query params which should be set on the DFP request. - * These will override this module's defaults whenever they conflict. - * @param {function} callback Callback function to execute when master tag is ready - */ - -/** - * Creates master tag url for long-form - * @param {DfpAdpodOptions} options - * @returns {string} A URL which calls DFP with custom adpod targeting key values to compete with rest of the demand in DFP - */ -export function buildAdpodVideoUrl({code, params, callback} = {}) { - // TODO: the public API for this does not take in enough info to fill all DFP params (adUnit/bid), - // and is marked "alpha": https://docs.prebid.org/dev-docs/publisher-api-reference/adServers.gam.buildAdpodVideoUrl.html - if (!params || !callback) { - logError(`A params object and a callback is required to use pbjs.adServers.gam.buildAdpodVideoUrl`); - return; - } - - const derivedParams = { - correlator: Date.now(), - sz: getSizeForAdUnit(code), - url: encodeURIComponent(location.href), - }; - - function getSizeForAdUnit(code) { - const adUnit = auctionManager.getAdUnits() - .filter((adUnit) => adUnit.code === code) - const sizes = deepAccess(adUnit[0], 'mediaTypes.video.playerSize'); - return parseSizesInput(sizes).join('|'); - } - - adpodUtils.getTargeting({ - 'codes': [code], - 'callback': createMasterTag - }); - - function createMasterTag(err, targeting) { - if (err) { - callback(err, null); - return; - } - - const initialValue = { - [adpodUtils.TARGETING_KEY_PB_CAT_DUR]: undefined, - [adpodUtils.TARGETING_KEY_CACHE_ID]: undefined - }; - let customParams = {}; - if (targeting[code]) { - customParams = targeting[code].reduce((acc, curValue) => { - if (Object.keys(curValue)[0] === adpodUtils.TARGETING_KEY_PB_CAT_DUR) { - acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] = (typeof acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] !== 'undefined') ? acc[adpodUtils.TARGETING_KEY_PB_CAT_DUR] + ',' + curValue[adpodUtils.TARGETING_KEY_PB_CAT_DUR] : curValue[adpodUtils.TARGETING_KEY_PB_CAT_DUR]; - } else if (Object.keys(curValue)[0] === adpodUtils.TARGETING_KEY_CACHE_ID) { - acc[adpodUtils.TARGETING_KEY_CACHE_ID] = curValue[adpodUtils.TARGETING_KEY_CACHE_ID] - } - return acc; - }, initialValue); - } - - const encodedCustomParams = encodeURIComponent(formatQS(customParams)); - - const queryParams = Object.assign({}, - DEFAULT_GAM_PARAMS, - derivedParams, - params, - { cust_params: encodedCustomParams }, - gdprParams(), - ); - - const masterTag = buildUrl({ - ...GAM_ENDPOINT, - search: queryParams - }); - - callback(null, masterTag); - } -} - -registerVideoSupport('gam', { - buildAdpodVideoUrl: buildAdpodVideoUrl, - getAdpodTargeting: (args) => adpodUtils.getTargeting(args) -}); - -submodule('adpod', adpodUtils); diff --git a/modules/mediafuseBidAdapter.js b/modules/mediafuseBidAdapter.js index 0bffb9219ce..a2922c6cd3e 100644 --- a/modules/mediafuseBidAdapter.js +++ b/modules/mediafuseBidAdapter.js @@ -19,18 +19,17 @@ import { import {Renderer} from '../src/Renderer.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {ADPOD, BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; +import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {INSTREAM, OUTSTREAM} from '../src/video.js'; import {getStorageManager} from '../src/storageManager.js'; import {bidderSettings} from '../src/bidderSettings.js'; import {hasPurpose1Consent} from '../src/utils/gdpr.js'; import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; -import {APPNEXUS_CATEGORY_MAPPING} from '../libraries/categoryTranslationMapping/index.js'; import { getANKewyordParamFromMaps, getANKeywordParam } from '../libraries/appnexusUtils/anKeywords.js'; -import {convertCamelToUnderscore, fill} from '../libraries/appnexusUtils/anUtils.js'; +import {convertCamelToUnderscore} from '../libraries/appnexusUtils/anUtils.js'; import {chunk} from '../libraries/chunk/chunk.js'; /** @@ -222,10 +221,6 @@ export const spec = { const mfKeywords = config.getConfig('mediafuseAuctionKeywords'); payload.keywords = getANKeywordParam(bidderRequest?.ortb2, mfKeywords); - if (config.getConfig('adpod.brandCategoryExclusion')) { - payload.brand_category_uniqueness = true; - } - if (debugObjParams.enabled) { payload.debug = debugObjParams; logInfo('MediaFuse Debug Auction Settings:\n\n' + JSON.stringify(debugObjParams, null, 4)); @@ -261,16 +256,6 @@ export const spec = { payload.referrer_detection = refererinfo; } - const hasAdPodBid = ((bidRequests) || []).find(hasAdPod); - if (hasAdPodBid) { - bidRequests.filter(hasAdPod).forEach(adPodBid => { - const adPodTags = createAdPodRequest(tags, adPodBid); - // don't need the original adpod placement because it's in adPodTags - const nonPodTags = payload.tags.filter(tag => tag.uuid !== adPodBid.bidId); - payload.tags = [...nonPodTags, ...adPodTags]; - }); - } - if (bidRequests[0].userIdAsEids?.length > 0) { const eids = []; bidRequests[0].userIdAsEids.forEach(eid => { @@ -578,7 +563,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { } if (rtbBid.rtb.video) { - // shared video properties used for all 3 contexts + // shared video properties used for both stream contexts Object.assign(bid, { width: rtbBid.rtb.video.player_width, height: rtbBid.rtb.video.player_height, @@ -588,17 +573,6 @@ function newBid(serverBid, rtbBid, bidderRequest) { const videoContext = deepAccess(bidRequest, 'mediaTypes.video.context'); switch (videoContext) { - case ADPOD: - const primaryCatId = (APPNEXUS_CATEGORY_MAPPING[rtbBid.brand_category_id]) ? APPNEXUS_CATEGORY_MAPPING[rtbBid.brand_category_id] : null; - bid.meta = Object.assign({}, bid.meta, { primaryCatId }); - const dealTier = rtbBid.deal_priority; - bid.video = { - context: ADPOD, - durationSeconds: Math.floor(rtbBid.rtb.video.duration_ms / 1000), - dealTier - }; - bid.vastUrl = rtbBid.rtb.video.asset_url; - break; case OUTSTREAM: bid.adResponse = serverBid; bid.adResponse.ad = bid.adResponse.ads[0]; @@ -755,11 +729,7 @@ function bidToTag(bid) { const videoMediaType = deepAccess(bid, `mediaTypes.${VIDEO}`); const context = deepAccess(bid, 'mediaTypes.video.context'); - if (videoMediaType && context === 'adpod') { - tag.hb_source = 7; - } else { - tag.hb_source = 1; - } + tag.hb_source = 1; if (bid.mediaType === VIDEO || videoMediaType) { tag.ad_types.push(VIDEO); } @@ -908,14 +878,6 @@ function hasDebug(bid) { return !!bid.debug } -function hasAdPod(bid) { - return ( - bid.mediaTypes && - bid.mediaTypes.video && - bid.mediaTypes.video.context === ADPOD - ); -} - function hasOmidSupport(bid) { let hasOmid = false; const bidderParams = bid.params; @@ -929,54 +891,6 @@ function hasOmidSupport(bid) { return hasOmid; } -/** - * Expand an adpod placement into a set of request objects according to the - * total adpod duration and the range of duration seconds. Sets minduration/ - * maxduration video property according to requireExactDuration configuration - */ -function createAdPodRequest(tags, adPodBid) { - const { durationRangeSec, requireExactDuration } = adPodBid.mediaTypes.video; - - const numberOfPlacements = getAdPodPlacementNumber(adPodBid.mediaTypes.video); - const maxDuration = Math.max(...durationRangeSec); - - const tagToDuplicate = tags.filter(tag => tag.uuid === adPodBid.bidId); - const request = fill(...tagToDuplicate, numberOfPlacements); - - if (requireExactDuration) { - const divider = Math.ceil(numberOfPlacements / durationRangeSec.length); - const chunked = chunk(request, divider); - - // each configured duration is set as min/maxduration for a subset of requests - durationRangeSec.forEach((duration, index) => { - chunked[index].forEach(tag => { - setVideoProperty(tag, 'minduration', duration); - setVideoProperty(tag, 'maxduration', duration); - }); - }); - } else { - // all maxdurations should be the same - request.forEach(tag => setVideoProperty(tag, 'maxduration', maxDuration)); - } - - return request; -} - -function getAdPodPlacementNumber(videoParams) { - const { adPodDurationSec, durationRangeSec, requireExactDuration } = videoParams; - const minAllowedDuration = Math.min(...durationRangeSec); - const numberOfPlacements = Math.floor(adPodDurationSec / minAllowedDuration); - - return requireExactDuration - ? Math.max(numberOfPlacements, durationRangeSec.length) - : numberOfPlacements; -} - -function setVideoProperty(tag, key, value) { - if (isEmpty(tag.video)) { tag.video = {}; } - tag.video[key] = value; -} - function getRtbBid(tag) { return tag && tag.ads && tag.ads.length && ((tag.ads) || []).find(ad => ad.rtb); } diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index f23665670e9..e0b61880fb7 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -1,6 +1,6 @@ import { logWarn, isStr, isArray, deepAccess, deepSetValue, isBoolean, isInteger, logInfo, logError, deepClone, uniques, generateUUID, isPlainObject, isFn, getWindowTop } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, VIDEO, NATIVE, ADPOD } from '../src/mediaTypes.js'; +import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { Renderer } from '../src/Renderer.js'; import { isViewabilityMeasurable, getViewability } from '../libraries/percentInView/percentInView.js'; @@ -142,12 +142,11 @@ const converter = ortbConverter({ if (mediaType === VIDEO) { if (!bidResponse.width) bidResponse.width = playerWidth; if (!bidResponse.height) bidResponse.height = playerHeight; - const { context, maxduration } = mediaTypes[mediaType]; + const { context } = mediaTypes[mediaType]; if (context === 'outstream' && params.outstreamAU && adUnitCode) { bidResponse.rendererCode = params.outstreamAU; bidResponse.renderer = BB_RENDERER.newRenderer(bidResponse.rendererCode, adUnitCode); } - assignDealTier(bidResponse, context, maxduration); } if (mediaType === NATIVE && bid.adm) { try { @@ -524,27 +523,6 @@ const addExtenstionParams = (req, bidderRequest) => { } } -/** - * In case of adpod video context, assign prebiddealpriority to the dealtier property of adpod-video bid, - * so that adpod module can set the hb_pb_cat_dur targetting key. - * @param {*} bid - * @param {*} context - * @param {*} maxduration - * @returns - */ -const assignDealTier = (bid, context, maxduration) => { - if (!bid?.ext?.prebiddealpriority || !FEATURES.VIDEO) return; - if (context !== ADPOD) return; - - const duration = bid?.ext?.video?.duration || maxduration; - // if (!duration) return; - bid.video = { - context: ADPOD, - durationSeconds: duration, - dealTier: bid.ext.prebiddealpriority - }; -} - const validateAllowedCategories = (acat) => { return [...new Set( acat diff --git a/modules/smaatoBidAdapter.js b/modules/smaatoBidAdapter.js index 03199e99d52..68ca0704d43 100644 --- a/modules/smaatoBidAdapter.js +++ b/modules/smaatoBidAdapter.js @@ -2,11 +2,9 @@ import {getDNT} from '../libraries/dnt/index.js'; import {deepAccess, deepSetValue, isEmpty, isNumber, logError, logInfo} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; -import {ADPOD, BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; +import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {NATIVE_IMAGE_TYPES} from '../src/constants.js'; import {getAdUnitSizes} from '../libraries/sizeUtils/sizeUtils.js'; -import {fill} from '../libraries/appnexusUtils/anUtils.js'; -import {chunk} from '../libraries/chunk/chunk.js'; import {ortbConverter} from '../libraries/ortbConverter/converter.js'; /** @@ -48,30 +46,14 @@ export const spec = { return false; } - if (deepAccess(bid, 'mediaTypes.video.context') === ADPOD) { - logInfo('[SMAATO] Verifying adpod bid request'); - - if (typeof bid.params.adbreakId !== 'string') { - logError('[SMAATO] Missing for adpod request mandatory adbreakId param'); - return false; - } - - if (bid.params.adspaceId) { - logError('[SMAATO] The adspaceId param is not allowed in an adpod bid request'); - return false; - } - } else { - logInfo('[SMAATO] Verifying a non adpod bid request'); - - if (typeof bid.params.adspaceId !== 'string') { - logError('[SMAATO] Missing mandatory adspaceId param'); - return false; - } + if (typeof bid.params.adspaceId !== 'string') { + logError('[SMAATO] Missing mandatory adspaceId param'); + return false; + } - if (bid.params.adbreakId) { - logError('[SMAATO] The adbreakId param is only allowed in an adpod bid request'); - return false; - } + if (bid.params.adbreakId) { + logError('[SMAATO] The adbreakId param is not supported'); + return false; } logInfo('[SMAATO] Verification done, all good'); @@ -147,39 +129,25 @@ export const spec = { } }; - const videoContext = deepAccess(JSON.parse(bidRequest.data).imp[0], 'video.ext.context'); - if (videoContext === ADPOD) { - resultingBid.vastXml = bid.adm; - resultingBid.mediaType = VIDEO; - if (config.getConfig('adpod.brandCategoryExclusion')) { - resultingBid.meta.primaryCatId = bid.cat[0]; - } - resultingBid.video = { - context: ADPOD, - durationSeconds: bid.ext.duration - }; - bids.push(resultingBid); - } else { - switch (smtAdType) { - case 'Img': - case 'Richmedia': - resultingBid.ad = createBannerAd(bid); - resultingBid.mediaType = BANNER; - bids.push(resultingBid); - break; - case 'Video': - resultingBid.vastXml = bid.adm; - resultingBid.mediaType = VIDEO; - bids.push(resultingBid); - break; - case 'Native': - resultingBid.native = createNativeAd(bid.adm); - resultingBid.mediaType = NATIVE; - bids.push(resultingBid); - break; - default: - logInfo('[SMAATO] Invalid ad type:', smtAdType); - } + switch (smtAdType) { + case 'Img': + case 'Richmedia': + resultingBid.ad = createBannerAd(bid); + resultingBid.mediaType = BANNER; + bids.push(resultingBid); + break; + case 'Video': + resultingBid.vastXml = bid.adm; + resultingBid.mediaType = VIDEO; + bids.push(resultingBid); + break; + case 'Native': + resultingBid.native = createNativeAd(bid.adm); + resultingBid.mediaType = NATIVE; + bids.push(resultingBid); + break; + default: + logInfo('[SMAATO] Invalid ad type:', smtAdType); } resultingBid.meta.mediaType = resultingBid.mediaType; }); @@ -247,15 +215,6 @@ const converter = ortbConverter({ const request = buildRequest(imps, bidderRequest, context); const bidRequest = context.bidRequests[0]; - let content; - const mediaType = context.mediaType; - if (mediaType === VIDEO) { - const videoParams = bidRequest.mediaTypes[VIDEO]; - if (videoParams.context === ADPOD) { - request.imp = createAdPodImp(request.imp[0], videoParams); - content = addOptionalAdpodParameters(videoParams); - } - } request.at = 1; @@ -275,15 +234,9 @@ const converter = ortbConverter({ if (request.site) { request.site.id = window.location.hostname - if (content) { - request.site.content = content; - } setPublisherId(request.site); } else if (request.dooh) { request.dooh.id = window.location.hostname - if (content) { - request.dooh.content = content; - } setPublisherId(request.dooh); } else { request.site = { @@ -291,7 +244,7 @@ const converter = ortbConverter({ domain: bidderRequest.refererInfo.domain || window.location.hostname, page: bidderRequest.refererInfo.page || window.location.href, ref: bidderRequest.refererInfo.ref, - content: content || null + content: null } setPublisherId(request.site); } @@ -362,7 +315,6 @@ const converter = ortbConverter({ imp: { banner(orig, imp, bidRequest, context) { const mediaType = context.mediaType; - if (mediaType === BANNER) { imp.bidfloor = getBidFloor(bidRequest, BANNER, getAdUnitSizes(bidRequest)); } @@ -375,11 +327,9 @@ const converter = ortbConverter({ if (mediaType === VIDEO) { const videoParams = bidRequest.mediaTypes[VIDEO]; imp.bidfloor = getBidFloor(bidRequest, VIDEO, videoParams.playerSize); - if (videoParams.context !== ADPOD) { - deepSetValue(imp, 'video.ext', { - rewarded: videoParams.ext && videoParams.ext.rewarded ? videoParams.ext.rewarded : 0 - }) - } + deepSetValue(imp, 'video.ext', { + rewarded: videoParams.ext && videoParams.ext.rewarded ? videoParams.ext.rewarded : 0 + }) } orig(imp, bidRequest, context); @@ -387,7 +337,6 @@ const converter = ortbConverter({ native(orig, imp, bidRequest, context) { const mediaType = context.mediaType; - if (mediaType === NATIVE) { imp.bidfloor = getBidFloor(bidRequest, NATIVE, getNativeMainImageSize(bidRequest.nativeOrtbRequest)); } @@ -431,81 +380,6 @@ function getNativeMainImageSize(nativeRequest) { return [] } -function createAdPodImp(imp, videoMediaType) { - const bce = config.getConfig('adpod.brandCategoryExclusion') - imp.video.ext = { - context: ADPOD, - brandcategoryexclusion: bce !== undefined && bce - }; - - const numberOfPlacements = getAdPodNumberOfPlacements(videoMediaType) - const imps = fill(imp, numberOfPlacements) - - const durationRangeSec = videoMediaType.durationRangeSec - if (videoMediaType.requireExactDuration) { - // equal distribution of numberOfPlacement over all available durations - const divider = Math.ceil(numberOfPlacements / durationRangeSec.length) - const chunked = chunk(imps, divider) - - // each configured duration is set as min/maxduration for a subset of requests - durationRangeSec.forEach((duration, index) => { - chunked[index].forEach(imp => { - const sequence = index + 1; - imp.video.minduration = duration - imp.video.maxduration = duration - imp.video.sequence = sequence - }); - }); - } else { - // all maxdurations should be the same - const maxDuration = Math.max(...durationRangeSec); - imps.forEach((imp, index) => { - const sequence = index + 1; - imp.video.maxduration = maxDuration - imp.video.sequence = sequence - }); - } - - return imps -} - -function getAdPodNumberOfPlacements(videoMediaType) { - const {adPodDurationSec, durationRangeSec, requireExactDuration} = videoMediaType - const minAllowedDuration = Math.min(...durationRangeSec) - const numberOfPlacements = Math.floor(adPodDurationSec / minAllowedDuration) - - return requireExactDuration - ? Math.max(numberOfPlacements, durationRangeSec.length) - : numberOfPlacements -} - -const addOptionalAdpodParameters = (videoMediaType) => { - const content = {} - - if (videoMediaType.tvSeriesName) { - content.series = videoMediaType.tvSeriesName - } - if (videoMediaType.tvEpisodeName) { - content.title = videoMediaType.tvEpisodeName - } - if (typeof videoMediaType.tvSeasonNumber === 'number') { - content.season = videoMediaType.tvSeasonNumber.toString() // conversion to string as in OpenRTB season is a string - } - if (typeof videoMediaType.tvEpisodeNumber === 'number') { - content.episode = videoMediaType.tvEpisodeNumber - } - if (typeof videoMediaType.contentLengthSec === 'number') { - content.len = videoMediaType.contentLengthSec - } - if (videoMediaType.contentMode && ['live', 'on-demand'].indexOf(videoMediaType.contentMode) >= 0) { - content.livestream = videoMediaType.contentMode === 'live' ? 1 : 0 - } - - if (!isEmpty(content)) { - return content - } -} - function getBidFloor(bidRequest, mediaType, sizes) { if (typeof bidRequest.getFloor === 'function') { const size = sizes.length === 1 ? sizes[0] : '*'; diff --git a/src/targeting.ts b/src/targeting.ts index 477ddaab7f0..49d72f7c023 100644 --- a/src/targeting.ts +++ b/src/targeting.ts @@ -5,7 +5,6 @@ import {config} from './config.js'; import {BID_STATUS, DEFAULT_TARGETING_KEYS, EVENTS, JSON_MAPPING, TARGETING_KEYS} from './constants.js'; import * as events from './events.js'; import {hook} from './hook.js'; -import {ADPOD} from './mediaTypes.js'; import { deepAccess, deepClone, @@ -663,7 +662,7 @@ export function newTargeting(auctionManager) { const cacheFilter = bidCacheEnabled || isBidFromLastAuction; const bidFilter = cacheFilter && filterFunctionResult; - if (bidFilter && bid?.video?.context !== ADPOD && isBidUsable(bid)) { + if (bidFilter && isBidUsable(bid)) { bid.latestTargetedAuctionId = latestAuctionForAdUnit[bid.adUnitCode]; bids.push(bid) } diff --git a/src/utils.js b/src/utils.js index ec30b934a49..973015336ba 100644 --- a/src/utils.js +++ b/src/utils.js @@ -760,7 +760,7 @@ export function groupBy(xs, key) { */ export function isValidMediaTypes(mediaTypes) { const SUPPORTED_MEDIA_TYPES = ['banner', 'native', 'video', 'audio']; - const SUPPORTED_STREAM_TYPES = ['instream', 'outstream', 'adpod']; + const SUPPORTED_STREAM_TYPES = ['instream', 'outstream']; const types = Object.keys(mediaTypes); diff --git a/test/spec/modules/adoceanBidAdapter_spec.js b/test/spec/modules/adoceanBidAdapter_spec.js index 53a82ec963d..c9e950abeec 100644 --- a/test/spec/modules/adoceanBidAdapter_spec.js +++ b/test/spec/modules/adoceanBidAdapter_spec.js @@ -63,38 +63,6 @@ describe('AdoceanAdapter', function () { expect(spec.isBidRequestValid(videoInscreenBid)).to.equal(true); }); - const videoAdpodBid = { - bidder: 'adocean', - params: { - masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', - slaveId: 'adoceanmyaozpniqismex', - emitter: 'myao.adocean.pl' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - video: { - context: 'adpod', - playerSize: [300, 250], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - requireExactDuration: false - } - }, - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - }; - - it('should return true for adpod video without requireExactDuration', function () { - expect(spec.isBidRequestValid(videoAdpodBid)).to.equal(true); - }); - - it('should return false for adpod video with requireExactDuration', function () { - const invalidBid = Object.assign({}, videoAdpodBid); - invalidBid.mediaTypes.video.requireExactDuration = true; - expect(spec.isBidRequestValid(invalidBid)).to.equal(false); - }); - const videoOutstreamBid = { bidder: 'adocean', params: { @@ -243,41 +211,6 @@ describe('AdoceanAdapter', function () { expect(request.url).to.include('maxdur=60'); expect(request.url).to.include('mindur=10'); }); - - const videoAdpodBidRequests = [ - { - bidder: 'adocean', - params: { - masterId: 'tmYF.DMl7ZBq.Nqt2Bq4FutQTJfTpxCOmtNPZoQUDcL.G7', - slaveId: 'adoceanmyaozpniqismex', - emitter: 'myao.adocean.pl' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - video: { - playerSize: [200, 200], - context: 'adpod', - adPodDurationSec: 300, - durationRangeSec: [15, 30], - requireExactDuration: false - } - }, - bidId: '30b31c1838de1h', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a476', - } - ]; - - it('should build correct video adpod request', function () { - const request = spec.buildRequests(videoAdpodBidRequests, bidderRequest)[0]; - expect(request).to.exist; - expect(request.url).to.include('id=' + videoAdpodBidRequests[0].params.masterId); - expect(request.url).to.include('slaves=zpniqismex'); - expect(request.url).to.include('spots=20'); // 300 / 15 = 20 - expect(request.url).to.include('dur=300'); - expect(request.url).to.include('maxdur=30'); - expect(request.url).to.not.include('mindur='); - }); }); describe('interpretResponseBanner', function () { diff --git a/test/spec/modules/adpod_spec.js b/test/spec/modules/adpod_spec.js deleted file mode 100644 index 6e94d98b488..00000000000 --- a/test/spec/modules/adpod_spec.js +++ /dev/null @@ -1,1238 +0,0 @@ -import * as utils from 'src/utils.js'; -import { config } from 'src/config.js'; -import * as videoCache from 'src/videoCache.js'; -import * as auction from 'src/auction.js'; -import { ADPOD } from 'src/mediaTypes.js'; - -import { callPrebidCacheHook, checkAdUnitSetupHook, checkVideoBidSetupHook, adpodSetConfig, sortByPricePerSecond } from 'modules/adpod.js'; - -const expect = require('chai').expect; - -describe('adpod.js', function () { - let logErrorStub; - let logWarnStub; - let logInfoStub; - - describe('callPrebidCacheHook', function () { - let callbackResult; - let clock; - let addBidToAuctionStub; - let doCallbacksIfTimedoutStub; - let storeStub; - let afterBidAddedSpy; - let auctionBids = []; - - const callbackFn = function() { - callbackResult = true; - }; - - const auctionInstance = { - getAuctionStatus: function() { - return auction.AUCTION_IN_PROGRESS; - } - } - - const fakeStoreFn = function(bids, callback) { - const payload = []; - bids.forEach(bid => payload.push({uuid: bid.customCacheKey})); - callback(null, payload); - }; - - beforeEach(function() { - callbackResult = null; - afterBidAddedSpy = sinon.spy(); - storeStub = sinon.stub(videoCache, 'store'); - logWarnStub = sinon.stub(utils, 'logWarn'); - logInfoStub = sinon.stub(utils, 'logInfo'); - addBidToAuctionStub = sinon.stub(auction, 'addBidToAuction').callsFake(function (auctionInstance, bid) { - auctionBids.push(bid); - }); - clock = sinon.useFakeTimers(); - config.setConfig({ - cache: { - url: 'https://test.cache.url/endpoint' - } - }); - }); - - afterEach(function() { - storeStub.restore(); - logWarnStub.restore(); - logInfoStub.restore(); - addBidToAuctionStub.restore(); - clock.restore(); - config.resetConfig(); - auctionBids = []; - }) - - it('should redirect back to the original function if bid is not an adpod video', function () { - const bid = { - adId: 'testAdId_123', - mediaType: 'video' - }; - - const videoMT = { - context: 'outstream' - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bid, function () {}, videoMT); - expect(callbackResult).to.equal(true); - }); - - it('should immediately add the adpod bid to auction if adpod.deferCaching in config is true', function() { - config.setConfig({ - adpod: { - deferCaching: true, - brandCategoryExclusion: true - } - }); - - const bidResponse1 = { - adId: 'adId01277', - auctionId: 'no_defer_123', - mediaType: 'video', - cpm: 5, - pbMg: '5.00', - adserverTargeting: { - hb_pb: '5.00' - }, - meta: { - adServerCatId: 'test' - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - } - }; - - const bidResponse2 = { - adId: 'adId46547', - auctionId: 'no_defer_123', - mediaType: 'video', - cpm: 12, - pbMg: '12.00', - adserverTargeting: { - hb_pb: '12.00' - }, - meta: { - adServerCatId: 'value' - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - } - }; - - const videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 300, - durationRangeSec: [15, 30, 45], - requireExactDuration: false - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); - - // check if bid adsereverTargeting is setup - expect(callbackResult).to.be.null; - expect(storeStub.called).to.equal(false); - expect(afterBidAddedSpy.calledTwice).to.equal(true); - expect(auctionBids.length).to.equal(2); - expect(auctionBids[0].adId).to.equal(bidResponse1.adId); - expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^5\.00_test_15s_.*/); - expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('5.00_test_15s'); - expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; - expect(auctionBids[0].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) - expect(auctionBids[1].adId).to.equal(bidResponse2.adId); - expect(auctionBids[1].customCacheKey).to.exist.and.to.match(/^12\.00_value_15s_.*/); - expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('12.00_value_15s'); - expect(auctionBids[1].adserverTargeting.hb_cache_id).to.exist; - expect(auctionBids[1].adserverTargeting.hb_cache_id).to.equal(auctionBids[0].adserverTargeting.hb_cache_id); - expect(auctionBids[1].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id); - }); - - it('should send prebid cache call once bid queue is full', function () { - storeStub.callsFake(fakeStoreFn); - - config.setConfig({ - adpod: { - bidQueueSizeLimit: 2, - deferCaching: false, - brandCategoryExclusion: true - } - }); - - const bidResponse1 = { - adId: 'adId123', - auctionId: 'full_abc123', - mediaType: 'video', - cpm: 10, - pbMg: '10.00', - adserverTargeting: { - hb_pb: '10.00' - }, - meta: { - adServerCatId: 'airline' - }, - video: { - context: ADPOD, - durationSeconds: 20, - durationBucket: 30 - } - }; - const bidResponse2 = { - adId: 'adId234', - auctionId: 'full_abc123', - mediaType: 'video', - cpm: 15, - pbMg: '15.00', - adserverTargeting: { - hb_pb: '15.00' - }, - meta: { - adServerCatId: 'airline' - }, - video: { - context: ADPOD, - durationSeconds: 25, - durationBucket: 30 - } - }; - const videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 120, - durationRangeSec: [15, 30], - requireExactDuration: false - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); - - expect(callbackResult).to.be.null; - expect(afterBidAddedSpy.calledTwice).to.equal(true); - expect(auctionBids.length).to.equal(2); - expect(auctionBids[0].adId).to.equal('adId123'); - expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^10\.00_airline_30s_.*/); - expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('10.00_airline_30s'); - expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; - expect(auctionBids[0].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) - expect(auctionBids[1].adId).to.equal('adId234'); - expect(auctionBids[1].customCacheKey).to.exist.and.to.match(/^15\.00_airline_30s_.*/); - expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_airline_30s'); - expect(auctionBids[1].adserverTargeting.hb_cache_id).to.exist; - expect(auctionBids[1].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) - }); - - it('should send prebid cache call after set period of time (even if queue is not full)', function () { - storeStub.callsFake(fakeStoreFn); - - config.setConfig({ - adpod: { - bidQueueSizeLimit: 2, - bidQueueTimeDelay: 30, - deferCaching: false, - brandCategoryExclusion: true - } - }); - - const bidResponse = { - adId: 'adId234', - auctionId: 'timer_abc234', - mediaType: 'video', - cpm: 15, - pbMg: '15.00', - adserverTargeting: { - hb_pb: '15.00' - }, - meta: { - adServerCatId: 'airline' - }, - video: { - context: ADPOD, - durationSeconds: 30, - durationBucket: 30 - } - }; - const videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 120, - durationRangeSec: [15, 30], - requireExactDuration: true - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse, afterBidAddedSpy, videoMT); - clock.tick(31); - - expect(callbackResult).to.be.null; - expect(afterBidAddedSpy.calledOnce).to.equal(true); - expect(auctionBids.length).to.equal(1); - expect(auctionBids[0].adId).to.equal('adId234'); - expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^15\.00_airline_30s_.*/); - expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_airline_30s'); - expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; - expect(auctionBids[0].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) - }); - - it('should execute multiple prebid cache calls when number of bids exceeds queue size', function () { - storeStub.callsFake(fakeStoreFn); - - config.setConfig({ - adpod: { - bidQueueSizeLimit: 2, - bidQueueTimeDelay: 30, - deferCaching: false, - brandCategoryExclusion: true - } - }); - - const bidResponse1 = { - adId: 'multi_ad1', - auctionId: 'multi_call_abc345', - mediaType: 'video', - cpm: 15, - pbMg: '15.00', - adserverTargeting: { - hb_pb: '15.00' - }, - meta: { - adServerCatId: 'airline' - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - } - }; - const bidResponse2 = { - adId: 'multi_ad2', - auctionId: 'multi_call_abc345', - mediaType: 'video', - cpm: 15, - pbMg: '15.00', - adserverTargeting: { - hb_pb: '15.00' - }, - meta: { - adServerCatId: 'news' - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - } - }; - const bidResponse3 = { - adId: 'multi_ad3', - auctionId: 'multi_call_abc345', - mediaType: 'video', - cpm: 10, - pbMg: '10.00', - adserverTargeting: { - hb_pb: '10.00' - }, - meta: { - adServerCatId: 'sports' - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - } - }; - - const videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 45, - durationRangeSec: [15, 30], - requireExactDuration: false - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse3, afterBidAddedSpy, videoMT); - clock.next(); - - expect(callbackResult).to.be.null; - expect(afterBidAddedSpy.calledThrice).to.equal(true); - expect(storeStub.calledTwice).to.equal(true); - expect(auctionBids.length).to.equal(3); - expect(auctionBids[0].adId).to.equal('multi_ad1'); - expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^15\.00_airline_15s_.*/); - expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_airline_15s'); - expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; - expect(auctionBids[0].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) - expect(auctionBids[1].adId).to.equal('multi_ad2'); - expect(auctionBids[1].customCacheKey).to.exist.and.to.match(/^15\.00_news_15s_.*/); - expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_news_15s'); - expect(auctionBids[1].adserverTargeting.hb_cache_id).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id); - expect(auctionBids[1].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) - expect(auctionBids[2].adId).to.equal('multi_ad3'); - expect(auctionBids[2].customCacheKey).to.exist.and.to.match(/^10\.00_sports_15s_.*/); - expect(auctionBids[2].adserverTargeting.hb_pb_cat_dur).to.equal('10.00_sports_15s'); - expect(auctionBids[2].adserverTargeting.hb_cache_id).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id); - expect(auctionBids[2].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) - }); - - it('should cache the bids with a shortened custom key when adpod.brandCategoryExclusion is false', function() { - storeStub.callsFake(fakeStoreFn); - - config.setConfig({ - adpod: { - bidQueueSizeLimit: 2, - bidQueueTimeDelay: 30, - deferCaching: false, - brandCategoryExclusion: false - } - }); - - const bidResponse1 = { - adId: 'nocat_ad1', - auctionId: 'no_category_abc345', - mediaType: 'video', - cpm: 10, - pbMg: '10.00', - adserverTargeting: { - hb_pb: '10.00' - }, - meta: { - adServerCatId: undefined - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - } - }; - const bidResponse2 = { - adId: 'nocat_ad2', - auctionId: 'no_category_abc345', - mediaType: 'video', - cpm: 15, - pbMg: '15.00', - adserverTargeting: { - hb_pb: '15.00' - }, - meta: { - adServerCatId: undefined - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - } - }; - - const videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 45, - durationRangeSec: [15, 30], - requireExactDuration: false - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); - - expect(callbackResult).to.be.null; - expect(afterBidAddedSpy.calledTwice).to.equal(true); - expect(storeStub.calledOnce).to.equal(true); - expect(auctionBids.length).to.equal(2); - expect(auctionBids[0].adId).to.equal('nocat_ad1'); - expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^10\.00_15s_.*/); - expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('10.00_15s'); - expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; - expect(auctionBids[0].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) - expect(auctionBids[1].adId).to.equal('nocat_ad2'); - expect(auctionBids[1].customCacheKey).to.exist.and.to.match(/^15\.00_15s_.*/); - expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_15s'); - expect(auctionBids[1].adserverTargeting.hb_cache_id).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id); - expect(auctionBids[1].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) - }); - - it('should not add bid to auction when config adpod.brandCategoryExclusion is true but bid is missing adServerCatId', function() { - storeStub.callsFake(fakeStoreFn); - - config.setConfig({ - adpod: { - bidQueueSizeLimit: 2, - bidQueueTimeDelay: 30, - deferCaching: false, - brandCategoryExclusion: true - } - }); - - const bidResponse1 = { - adId: 'missingCat_ad1', - auctionId: 'missing_category_abc345', - mediaType: 'video', - cpm: 10, - meta: { - adServerCatId: undefined - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - } - }; - - const videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 45, - durationRangeSec: [15, 30], - requireExactDuration: false - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - - expect(callbackResult).to.be.null; - expect(afterBidAddedSpy.calledOnce).to.equal(true); - expect(storeStub.called).to.equal(false); - expect(logWarnStub.calledOnce).to.equal(true); - expect(auctionBids.length).to.equal(0); - }); - - it('should not add bid to auction when Prebid Cache detects an existing key', function () { - storeStub.callsFake(function(bids, callback) { - const payload = []; - bids.forEach(bid => payload.push({uuid: bid.customCacheKey})); - - // fake a duplicate bid response from PBC (sets an empty string for the uuid) - payload[1].uuid = ''; - callback(null, payload); - }); - - config.setConfig({ - adpod: { - bidQueueSizeLimit: 2, - deferCaching: false, - brandCategoryExclusion: true - } - }); - - const bidResponse1 = { - adId: 'dup_ad_1', - auctionId: 'duplicate_def123', - mediaType: 'video', - cpm: 5, - pbMg: '5.00', - adserverTargeting: { - hb_pb: '5.00' - }, - meta: { - adServerCatId: 'tech' - }, - video: { - context: ADPOD, - durationSeconds: 45, - durationBucket: 45 - } - }; - const bidResponse2 = { - adId: 'dup_ad_2', - auctionId: 'duplicate_def123', - mediaType: 'video', - cpm: 5, - pbMg: '5.00', - adserverTargeting: { - hb_pb: '5.00' - }, - meta: { - adServerCatId: 'tech' - }, - video: { - context: ADPOD, - durationSeconds: 45, - durationBucket: 45 - } - }; - const videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 120, - durationRangeSec: [15, 30, 45], - requireExactDuration: false - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); - - expect(callbackResult).to.be.null; - expect(afterBidAddedSpy.calledTwice).to.equal(true); - expect(storeStub.calledOnce).to.equal(true); - expect(logInfoStub.calledOnce).to.equal(true); - expect(auctionBids.length).to.equal(1); - expect(auctionBids[0].adId).to.equal('dup_ad_1'); - expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^5\.00_tech_45s_.*/); - expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('5.00_tech_45s'); - expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; - expect(auctionBids[0].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) - }); - - it('should not add bids to auction if PBC returns an error', function() { - storeStub.callsFake(function(bids, callback) { - const payload = []; - const errmsg = 'invalid json'; - - callback(errmsg, payload); - }); - - config.setConfig({ - adpod: { - bidQueueSizeLimit: 2, - deferCaching: false, - brandCategoryExclusion: true - } - }); - - const bidResponse1 = { - adId: 'err_ad_1', - auctionId: 'error_xyz123', - mediaType: 'video', - cpm: 5, - meta: { - adServerCatId: 'tech' - }, - video: { - context: ADPOD, - durationSeconds: 30, - durationBucket: 30 - } - }; - const bidResponse2 = { - adId: 'err_ad_2', - auctionId: 'error_xyz123', - mediaType: 'video', - cpm: 5, - meta: { - adServerCatId: 'tech' - }, - video: { - context: ADPOD, - durationSeconds: 30, - durationBucket: 30 - } - }; - const videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 120, - durationRangeSec: [15, 30, 45], - requireExactDuration: false - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); - - expect(logWarnStub.calledOnce).to.equal(true); - expect(auctionBids.length).to.equal(0); - }); - - it('should use bid.adserverTargeting.hb_pb when custom price granularity is configured', function() { - storeStub.callsFake(fakeStoreFn); - - const customConfigObject = { - 'buckets': [{ - 'precision': 2, // default is 2 if omitted - means 2.1234 rounded to 2 decimal places = 2.12 - 'max': 5, - 'increment': 0.01 // from $0 to $5, 1-cent increments - }, - { - 'precision': 2, - 'max': 8, - 'increment': 0.05 // from $5 to $8, round down to the previous 5-cent increment - }, - { - 'precision': 2, - 'max': 40, - 'increment': 0.5 // from $8 to $40, round down to the previous 50-cent increment - }] - }; - config.setConfig({ - priceGranularity: customConfigObject, - adpod: { - brandCategoryExclusion: true - } - }); - - const bidResponse1 = { - adId: 'cat_ad1', - auctionId: 'test_category_abc345', - mediaType: 'video', - cpm: 15, - pbAg: '15.00', - pbCg: '15.00', - pbDg: '15.00', - pbHg: '15.00', - pbLg: '5.00', - pbMg: '15.00', - adserverTargeting: { - hb_pb: '15.00', - }, - meta: { - adServerCatId: 'test' - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - } - }; - - const videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 45, - durationRangeSec: [15, 30], - requireExactDuration: false - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - - expect(callbackResult).to.be.null; - expect(afterBidAddedSpy.calledOnce).to.equal(true); - expect(storeStub.called).to.equal(false); - expect(auctionBids.length).to.equal(1); - }); - - it('should set deal tier in place of cpm when prioritzeDeals is true', function() { - config.setConfig({ - adpod: { - deferCaching: true, - brandCategoryExclusion: true, - prioritizeDeals: true, - dealTier: { - 'appnexus': { - 'prefix': 'tier', - 'minDealTier': 5 - } - } - } - }); - - const bidResponse1 = { - adId: 'adId01277', - auctionId: 'no_defer_123', - mediaType: 'video', - bidderCode: 'appnexus', - cpm: 5, - pbMg: '5.00', - adserverTargeting: { - hb_pb: '5.00' - }, - meta: { - adServerCatId: 'test' - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15, - dealTier: 7 - } - }; - - const bidResponse2 = { - adId: 'adId46547', - auctionId: 'no_defer_123', - mediaType: 'video', - bidderCode: 'appnexus', - cpm: 12, - pbMg: '12.00', - adserverTargeting: { - hb_pb: '12.00' - }, - meta: { - adServerCatId: 'value' - }, - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - } - }; - - const videoMT = { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 300, - durationRangeSec: [15, 30, 45], - requireExactDuration: false - }; - - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, videoMT); - callPrebidCacheHook(callbackFn, auctionInstance, bidResponse2, afterBidAddedSpy, videoMT); - - expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('tier7_test_15s'); - expect(auctionBids[1].adserverTargeting.hb_pb_cat_dur).to.equal('12.00_value_15s'); - }) - }); - - describe('checkAdUnitSetupHook', function () { - let results; - const callbackFn = function (adUnits) { - results = adUnits; - }; - - beforeEach(function () { - logWarnStub = sinon.stub(utils, 'logWarn'); - results = null; - }); - - afterEach(function() { - utils.logWarn.restore(); - }); - - it('removes an incorrectly setup adpod adunit - required fields are missing', function() { - const adUnits = [{ - code: 'test1', - mediaTypes: { - video: { - context: ADPOD - } - } - }, { - code: 'test2', - mediaTypes: { - video: { - context: 'instream' - } - } - }]; - - checkAdUnitSetupHook(callbackFn, adUnits); - - expect(results).to.deep.equal([{ - code: 'test2', - mediaTypes: { - video: { - context: 'instream' - } - } - }]); - expect(logWarnStub.calledOnce).to.equal(true); - }); - - it('removes an incorrectly setup adpod adunit - required fields are using invalid values', function() { - const adUnits = [{ - code: 'test1', - mediaTypes: { - video: { - context: ADPOD, - durationRangeSec: [-5, 15, 30, 45], - adPodDurationSec: 300 - } - } - }]; - - checkAdUnitSetupHook(callbackFn, adUnits); - - expect(results).to.deep.equal([]); - expect(logWarnStub.calledOnce).to.equal(true); - - adUnits[0].mediaTypes.video.durationRangeSec = [15, 30, 45]; - adUnits[0].mediaTypes.video.adPodDurationSec = 0; - - checkAdUnitSetupHook(callbackFn, adUnits); - - expect(results).to.deep.equal([]); - expect(logWarnStub.calledTwice).to.equal(true); - }); - - it('removes an incorrectly setup adpod adunit - attempting to use multi-format adUnit', function() { - const adUnits = [{ - code: 'multi_test1', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - }, - video: { - context: 'adpod', - playerSize: [[300, 250]], - durationRangeSec: [15, 30, 45], - adPodDurationSec: 300 - } - } - }]; - - checkAdUnitSetupHook(callbackFn, adUnits); - - expect(results).to.deep.equal([]); - expect(logWarnStub.calledOnce).to.equal(true); - }); - - it('accepts mixed set of adunits', function() { - const adUnits = [{ - code: 'test3', - mediaTypes: { - video: { - context: ADPOD, - playerSize: [[300, 300]], - adPodDurationSec: 360, - durationRangeSec: [15, 30, 45], - requireExactDuration: true - } - } - }, { - code: 'test4', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - } - }]; - - checkAdUnitSetupHook(callbackFn, adUnits); - - expect(results).to.deep.equal(adUnits); - expect(logWarnStub.called).to.equal(false); - }); - }); - - describe('checkVideoBidSetupHook', function () { - let callbackResult; - let bailResult; - const callbackFn = { - call: function(context, bid) { - callbackResult = bid; - }, - bail: function(result) { - bailResult = result; - } - } - const adpodTestBid = { - video: { - context: ADPOD, - durationSeconds: 15, - durationBucket: 15 - }, - meta: { - primaryCatId: 'testCategory_123' - }, - vastXml: 'test XML here' - }; - const adUnitNoExact = { - mediaTypes: { - video: { - context: ADPOD, - playerSize: [[300, 400]], - durationRangeSec: [15, 45], - requireExactDuration: false, - adPodDurationSec: 300 - } - } - }; - const adUnitWithExact = { - mediaTypes: { - video: { - context: ADPOD, - playerSize: [[300, 400]], - durationRangeSec: [15, 30, 45, 60], - requireExactDuration: true, - adPodDurationSec: 300 - } - } - }; - - beforeEach(function() { - callbackResult = null; - bailResult = null; - config.setConfig({ - cache: { - url: 'https://test.cache.url/endpoint' - }, - adpod: { - brandCategoryExclusion: true - } - }); - logWarnStub = sinon.stub(utils, 'logWarn'); - logErrorStub = sinon.stub(utils, 'logError'); - }); - - afterEach(function() { - config.resetConfig(); - logWarnStub.restore(); - logErrorStub.restore(); - }) - - it('redirects to original function for non-adpod type video bids', function() { - const bannerTestBid = { - mediaType: 'video' - }; - checkVideoBidSetupHook(callbackFn, bannerTestBid, {}, {}, 'instream'); - expect(callbackResult).to.deep.equal(bannerTestBid); - expect(bailResult).to.be.null; - expect(logErrorStub.called).to.equal(false); - }); - - it('returns true when adpod bid is properly setup', function() { - config.setConfig({ - cache: { - url: 'https://test.cache.url/endpoint' - }, - adpod: { - brandCategoryExclusion: false - } - }); - - const goodBid = utils.deepClone(adpodTestBid); - goodBid.meta.primaryCatId = undefined; - checkVideoBidSetupHook(callbackFn, goodBid, adUnitNoExact, adUnitNoExact.mediaTypes.video, ADPOD); - expect(callbackResult).to.be.null; - expect(bailResult).to.equal(true); - expect(logErrorStub.called).to.equal(false); - }); - - it('returns true when adpod bid is missing iab category while brandCategoryExclusion in config is false', function() { - const goodBid = utils.deepClone(adpodTestBid); - checkVideoBidSetupHook(callbackFn, goodBid, adUnitNoExact, adUnitNoExact.mediaTypes.video, ADPOD); - expect(callbackResult).to.be.null; - expect(bailResult).to.equal(true); - expect(logErrorStub.called).to.equal(false); - }); - - it('returns false when a required property from an adpod bid is missing', function() { - function testInvalidAdpodBid(badTestBid, shouldErrorBeLogged) { - checkVideoBidSetupHook(callbackFn, badTestBid, adUnitNoExact, adUnitNoExact.mediaTypes.video, ADPOD); - expect(callbackResult).to.be.null; - expect(bailResult).to.equal(false); - expect(logErrorStub.called).to.equal(shouldErrorBeLogged); - } - - const noCatBid = utils.deepClone(adpodTestBid); - noCatBid.meta.primaryCatId = undefined; - testInvalidAdpodBid(noCatBid, false); - - const noContextBid = utils.deepClone(adpodTestBid); - delete noContextBid.video.context; - testInvalidAdpodBid(noContextBid, false); - - const wrongContextBid = utils.deepClone(adpodTestBid); - wrongContextBid.video.context = 'instream'; - testInvalidAdpodBid(wrongContextBid, false); - - const noDurationBid = utils.deepClone(adpodTestBid); - delete noDurationBid.video.durationSeconds; - testInvalidAdpodBid(noDurationBid, false); - - config.resetConfig(); - const noCacheUrlBid = utils.deepClone(adpodTestBid); - testInvalidAdpodBid(noCacheUrlBid, true); - }); - - describe('checkBidDuration', function() { - const basicBid = { - video: { - context: ADPOD, - durationSeconds: 30 - }, - meta: { - primaryCatId: 'testCategory_123' - }, - vastXml: '' - }; - - it('when requireExactDuration is true', function() { - const goodBid = utils.deepClone(basicBid); - checkVideoBidSetupHook(callbackFn, goodBid, adUnitWithExact, adUnitWithExact.mediaTypes.video, ADPOD); - - expect(callbackResult).to.be.null; - expect(goodBid.video.durationBucket).to.equal(30); - expect(bailResult).to.equal(true); - expect(logWarnStub.called).to.equal(false); - - const badBid = utils.deepClone(basicBid); - badBid.video.durationSeconds = 14; - checkVideoBidSetupHook(callbackFn, badBid, adUnitWithExact, adUnitWithExact.mediaTypes.video, ADPOD); - - expect(callbackResult).to.be.null; - expect(badBid.video.durationBucket).to.be.undefined; - expect(bailResult).to.equal(false); - expect(logWarnStub.calledOnce).to.equal(true); - }); - - it('when requireExactDuration is false and bids are bucketed properly', function() { - function testRoundingForGoodBId(bid, bucketValue) { - checkVideoBidSetupHook(callbackFn, bid, adUnitNoExact, adUnitNoExact.mediaTypes.video, ADPOD); - expect(callbackResult).to.be.null; - expect(bid.video.durationBucket).to.equal(bucketValue); - expect(bailResult).to.equal(true); - expect(logWarnStub.called).to.equal(false); - } - - const goodBid45 = utils.deepClone(basicBid); - goodBid45.video.durationSeconds = 45; - testRoundingForGoodBId(goodBid45, 45); - - const goodBid30 = utils.deepClone(basicBid); - goodBid30.video.durationSeconds = 30; - testRoundingForGoodBId(goodBid30, 45); - - const goodBid10 = utils.deepClone(basicBid); - goodBid10.video.durationSeconds = 10; - testRoundingForGoodBId(goodBid10, 15); - - const goodBid16 = utils.deepClone(basicBid); - goodBid16.video.durationSeconds = 16; - testRoundingForGoodBId(goodBid16, 15); - - const goodBid47 = utils.deepClone(basicBid); - goodBid47.video.durationSeconds = 47; - testRoundingForGoodBId(goodBid47, 45); - }); - - it('when requireExactDuration is false and bid duration exceeds listed buckets', function() { - function testRoundingForBadBid(bid) { - checkVideoBidSetupHook(callbackFn, bid, adUnitNoExact, adUnitNoExact.mediaTypes.video, ADPOD); - expect(callbackResult).to.be.null; - expect(bid.video.durationBucket).to.be.undefined; - expect(bailResult).to.equal(false); - expect(logWarnStub.called).to.equal(true); - } - - const badBid100 = utils.deepClone(basicBid); - badBid100.video.durationSeconds = 100; - testRoundingForBadBid(badBid100); - - const badBid48 = utils.deepClone(basicBid); - badBid48.video.durationSeconds = 48; - testRoundingForBadBid(badBid48); - }); - }); - }); - - describe('adpodSetConfig', function () { - let logWarnStub; - beforeEach(function() { - logWarnStub = sinon.stub(utils, 'logWarn'); - }); - - afterEach(function () { - logWarnStub.restore(); - }); - - it('should log a warning when values other than numbers are used in setConfig', function() { - adpodSetConfig({ - bidQueueSizeLimit: '2', - bidQueueTimeDelay: '50' - }); - expect(logWarnStub.calledTwice).to.equal(true); - }); - - it('should log a warning when numbers less than or equal to zero are used in setConfig', function() { - adpodSetConfig({ - bidQueueSizeLimit: 0, - bidQueueTimeDelay: -2 - }); - expect(logWarnStub.calledTwice).to.equal(true); - }); - - it('should not log any warning when using a valid config', function() { - adpodSetConfig({ - bidQueueSizeLimit: 10 - }); - expect(logWarnStub.called).to.equal(false); - - adpodSetConfig({ - bidQueueTimeDelay: 100, - bidQueueSizeLimit: 20 - }); - expect(logWarnStub.called).to.equal(false); - }) - }); - - describe('adpod utils', function() { - it('should sort bids array', function() { - const bids = [{ - cpm: 10.12345, - adserverTargeting: { - hb_pb: '10.00', - }, - video: { - durationBucket: 15 - } - }, { - cpm: 15, - adserverTargeting: { - hb_pb: '15.00', - }, - video: { - durationBucket: 15 - } - }, { - cpm: 15.00, - adserverTargeting: { - hb_pb: '15.00', - }, - video: { - durationBucket: 30 - } - }, { - cpm: 5.45, - adserverTargeting: { - hb_pb: '5.00', - }, - video: { - durationBucket: 5 - } - }, { - cpm: 20.1234567, - adserverTargeting: { - hb_pb: '20.10', - }, - video: { - durationBucket: 60 - } - }] - bids.sort(sortByPricePerSecond); - const sortedBids = [{ - cpm: 15, - adserverTargeting: { - hb_pb: '15.00', - }, - video: { - durationBucket: 15 - } - }, { - cpm: 5.45, - adserverTargeting: { - hb_pb: '5.00', - }, - video: { - durationBucket: 5 - } - }, { - cpm: 10.12345, - adserverTargeting: { - hb_pb: '10.00', - }, - video: { - durationBucket: 15 - } - }, { - cpm: 15.00, - adserverTargeting: { - hb_pb: '15.00', - }, - video: { - durationBucket: 30 - } - }, { - cpm: 20.1234567, - adserverTargeting: { - hb_pb: '20.10', - }, - video: { - durationBucket: 60 - } - }] - expect(bids).to.include.deep.ordered.members(sortedBids); - }); - }) -}); diff --git a/test/spec/modules/adtelligentBidAdapter_spec.js b/test/spec/modules/adtelligentBidAdapter_spec.js index bcce942f47f..eed27cdd57b 100644 --- a/test/spec/modules/adtelligentBidAdapter_spec.js +++ b/test/spec/modules/adtelligentBidAdapter_spec.js @@ -52,24 +52,6 @@ const VIDEO_REQUEST = { 'ortb2Imp': { 'ext': { 'gpid': '12345/adunit-code' } }, }; -const ADPOD_REQUEST = { - 'bidder': 'adtelligent', - 'mediaTypes': { - 'video': { - 'context': 'adpod', - 'playerSize': [[640, 480]], - 'anyField': 10 - } - }, - 'params': { - 'aid': 12345 - }, - 'bidderRequestId': '7101db09af0db2', - 'auctionId': '2e41f65424c87c', - 'adUnitCode': 'adunit-code', - 'bidId': '2e41f65424c87c' -}; - const SERVER_VIDEO_RESPONSE = { 'source': { 'aid': 12345, 'pubId': 54321 }, 'bids': [{ @@ -310,13 +292,6 @@ describe('adtelligentBidAdapter', () => { expect(displayRequest.every(comparator)).to.be.true; expect(videoAndDisplayRequests.every(comparator)).to.be.true; }); - it('forms correct ADPOD request', () => { - const pbBidReqData = spec.buildRequests([ADPOD_REQUEST], DEFAULT_ADATPER_REQ)[0].data; - const impRequest = pbBidReqData.BidRequests[0] - expect(impRequest.AdType).to.be.equal('video'); - expect(impRequest.Adpod).to.be.a('object'); - expect(impRequest.Adpod.anyField).to.be.equal(10); - }) it('sends correct video bid parameters', () => { const data = videoRequest[0].data; @@ -454,12 +429,6 @@ describe('adtelligentBidAdapter', () => { nobidServerResponseCheck(); }); - - it('forms correct ADPOD response', () => { - const videoBids = spec.interpretResponse({ body: SERVER_VIDEO_RESPONSE }, { adapterRequest: { bids: [ADPOD_REQUEST] } }); - expect(videoBids[0].video.durationSeconds).to.be.equal(30); - expect(videoBids[0].video.context).to.be.equal('adpod'); - }) describe('outstream setup', () => { const videoBids = spec.interpretResponse({ body: SERVER_OUSTREAM_VIDEO_RESPONSE }, { adapterRequest: outstreamVideoBidderRequest }); it('should return renderer with expected outstream params config', () => { diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index f4a00bfb264..826cc9e76ad 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -536,185 +536,6 @@ describe('AppNexusAdapter', function () { playback_method: 2 }); }); - - it('should duplicate adpod placements into batches and set correct maxduration', function () { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - - // 300 / 15 = 20 total - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(5); - - expect(payload1.tags[0]).to.deep.equal(payload1.tags[1]); - expect(payload1.tags[0].video.maxduration).to.equal(30); - - expect(payload2.tags[0]).to.deep.equal(payload1.tags[1]); - expect(payload2.tags[0].video.maxduration).to.equal(30); - }); - - it('should round down adpod placements when numbers are uneven', function () { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 123, - durationRangeSec: [45], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags.length).to.equal(2); - }); - - it('should duplicate adpod placements when requireExactDuration is set', function () { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - requireExactDuration: true, - } - } - } - ); - - // 20 total placements with 15 max impressions = 2 requests - const request = spec.buildRequests([bidRequest]); - expect(request.length).to.equal(2); - - // 20 spread over 2 requests = 15 in first request, 5 in second - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(5); - - // 10 placements should have max/min at 15 - // 10 placemenst should have max/min at 30 - const payload1tagsWith15 = payload1.tags.filter(tag => tag.video.maxduration === 15); - const payload1tagsWith30 = payload1.tags.filter(tag => tag.video.maxduration === 30); - expect(payload1tagsWith15.length).to.equal(10); - expect(payload1tagsWith30.length).to.equal(5); - - // 5 placemenst with min/max at 30 were in the first request - // so 5 remaining should be in the second - const payload2tagsWith30 = payload2.tags.filter(tag => tag.video.maxduration === 30); - expect(payload2tagsWith30.length).to.equal(5); - }); - - it('should set durations for placements when requireExactDuration is set and numbers are uneven', function () { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 105, - durationRangeSec: [15, 30, 60], - requireExactDuration: true, - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags.length).to.equal(7); - - const tagsWith15 = payload.tags.filter(tag => tag.video.maxduration === 15); - const tagsWith30 = payload.tags.filter(tag => tag.video.maxduration === 30); - const tagsWith60 = payload.tags.filter(tag => tag.video.maxduration === 60); - expect(tagsWith15.length).to.equal(3); - expect(tagsWith30.length).to.equal(3); - expect(tagsWith60.length).to.equal(1); - }); - - it('should break adpod request into batches', function () { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 225, - durationRangeSec: [5], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - const payload3 = JSON.parse(request[2].data); - - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(15); - expect(payload3.tags.length).to.equal(15); - }); - - it('should contain hb_source value for adpod', function () { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - } - } - } - ); - const request = spec.buildRequests([bidRequest])[0]; - const payload = JSON.parse(request.data); - expect(payload.tags[0].hb_source).to.deep.equal(7); - }); } // VIDEO it('sends bid request to ENDPOINT via POST', function () { @@ -817,21 +638,6 @@ describe('AppNexusAdapter', function () { expect(payload.tags[0].hb_source).to.deep.equal(1); }); - it('adds brand_category_exclusion to request when set', function () { - const bidRequest = Object.assign({}, bidRequests[0]); - sinon - .stub(config, 'getConfig') - .withArgs('adpod.brandCategoryExclusion') - .returns(true); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.brand_category_uniqueness).to.equal(true); - - config.getConfig.restore(); - }); - it('adds auction level keywords and ortb2 keywords to request when set', function () { const bidRequest = Object.assign({}, bidRequests[0]); sinon @@ -2024,46 +1830,6 @@ describe('AppNexusAdapter', function () { expect(result[0]).to.have.property('vastImpUrl'); expect(result[0]).to.have.property('mediaType', 'video'); }); - - it('handles adpod responses', function () { - const response = { - 'tags': [{ - 'uuid': '84ab500420319d', - 'ads': [{ - 'ad_type': 'video', - 'brand_category_id': 10, - 'cpm': 0.500000, - 'notify_url': 'imptracker.com', - 'rtb': { - 'video': { - 'asset_url': 'https://sample.vastURL.com/here/adpod', - 'duration_ms': 30000, - } - }, - 'viewability': { - 'config': '' - } - }] - }] - }; - - const bidderRequest = { - bids: [{ - bidId: '84ab500420319d', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'adpod' - } - } - }] - }; - - const result = spec.interpretResponse({ body: response }, { bidderRequest }); - expect(result[0]).to.have.property('vastUrl'); - expect(result[0].video.context).to.equal('adpod'); - expect(result[0].video.durationSeconds).to.equal(30); - }); } if (FEATURES.NATIVE) { @@ -2377,33 +2143,6 @@ describe('AppNexusAdapter', function () { bidderRequest.bids[0].renderer.options ); }); - - it('should add deal_priority and deal_code', function () { - const responseWithDeal = deepClone(response); - responseWithDeal.tags[0].ads[0].ad_type = 'video'; - responseWithDeal.tags[0].ads[0].deal_priority = 5; - responseWithDeal.tags[0].ads[0].deal_code = '123'; - responseWithDeal.tags[0].ads[0].rtb.video = { - duration_ms: 1500, - player_width: 640, - player_height: 340, - }; - - const bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'adpod' - } - } - }] - } - const result = spec.interpretResponse({ body: responseWithDeal }, { bidderRequest }); - expect(Object.keys(result[0].appnexus)).to.include.members(['buyerMemberId', 'dealPriority', 'dealCode']); - expect(result[0].video.dealTier).to.equal(5); - }); } it('should add advertiser id', function () { diff --git a/test/spec/modules/categoryTranslation_spec.js b/test/spec/modules/categoryTranslation_spec.js deleted file mode 100644 index 3aeca0fbf75..00000000000 --- a/test/spec/modules/categoryTranslation_spec.js +++ /dev/null @@ -1,109 +0,0 @@ -import { getAdserverCategoryHook, initTranslation, storage } from 'modules/categoryTranslation.js'; -import { config } from 'src/config.js'; -import * as utils from 'src/utils.js'; -import { expect } from 'chai'; -import {server} from '../../mocks/xhr.js'; - -describe('category translation', function () { - let getLocalStorageStub; - - beforeEach(function () { - getLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); - }); - - afterEach(function() { - getLocalStorageStub.restore(); - config.resetConfig(); - }); - - it('should translate iab category to adserver category', function () { - config.setConfig({ - 'adpod': { - 'brandCategoryExclusion': true - } - }); - getLocalStorageStub.returns(JSON.stringify({ - 'mapping': { - 'iab-1': { - 'id': 1, - 'name': 'sample' - } - } - })); - const bid = { - meta: { - primaryCatId: 'iab-1' - } - } - getAdserverCategoryHook(sinon.spy(), 'code', bid); - expect(bid.meta.adServerCatId).to.equal(1); - }); - - it('should set adserverCatId to undefined if not found in mapping file', function() { - config.setConfig({ - 'adpod': { - 'brandCategoryExclusion': true - } - }); - getLocalStorageStub.returns(JSON.stringify({ - 'mapping': { - 'iab-1': { - 'id': 1, - 'name': 'sample' - } - } - })); - const bid = { - meta: { - primaryCatId: 'iab-2' - } - } - getAdserverCategoryHook(sinon.spy(), 'code', bid); - expect(bid.meta.adServerCatId).to.equal(undefined); - }); - - it('should not make ajax call to update mapping file if data found in localstorage and is not expired', function () { - const clock = sinon.useFakeTimers(utils.timestamp()); - getLocalStorageStub.returns(JSON.stringify({ - lastUpdated: utils.timestamp(), - mapping: { - 'iab-1': '1' - } - })); - initTranslation(); - expect(server.requests.length).to.equal(0); - clock.restore(); - }); - - it('should make ajax call to update mapping file if data found in localstorage is expired', function () { - const clock = sinon.useFakeTimers(utils.timestamp()); - getLocalStorageStub.returns(JSON.stringify({ - lastUpdated: utils.timestamp() - 2 * 24 * 60 * 60 * 1000, - mapping: { - 'iab-1': '1' - } - })); - initTranslation(); - expect(server.requests.length).to.equal(1); - clock.restore(); - }); - - it('should use default mapping file if publisher has not defined in config', function () { - getLocalStorageStub.returns(null); - initTranslation('http://sample.com', 'somekey'); - expect(server.requests.length).to.equal(1); - expect(server.requests[0].url).to.equal('http://sample.com/'); - }); - - it('should use publisher defined mapping file', function () { - config.setConfig({ - 'brandCategoryTranslation': { - 'translationFile': 'http://sample.com' - } - }); - getLocalStorageStub.returns(null); - initTranslation('http://sample.com', 'somekey'); - expect(server.requests.length).to.equal(2); - expect(server.requests[0].url).to.equal('http://sample.com/'); - }); -}); diff --git a/test/spec/modules/freeWheelAdserverVideo_spec.js b/test/spec/modules/freeWheelAdserverVideo_spec.js deleted file mode 100644 index 3da5b411e37..00000000000 --- a/test/spec/modules/freeWheelAdserverVideo_spec.js +++ /dev/null @@ -1,350 +0,0 @@ -import { expect } from 'chai'; -import { adpodUtils } from 'modules/freeWheelAdserverVideo.js'; -import { auctionManager } from 'src/auctionManager.js'; -import { config } from 'src/config.js'; -import { server } from 'test/mocks/xhr.js'; - -describe('freeWheel adserver module', function() { - let amStub; - let amGetAdUnitsStub; - - before(function () { - const adUnits = [{ - code: 'preroll_1', - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 60, - durationRangeSec: [15, 30], - requireExactDuration: true - } - }, - bids: [ - { - bidder: 'appnexus', - params: { - placementId: 14542875, - } - } - ] - }, { - code: 'midroll_1', - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 60, - durationRangeSec: [15, 30], - requireExactDuration: true - } - }, - bids: [ - { - bidder: 'appnexus', - params: { - placementId: 14542875, - } - } - ] - }]; - - amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits'); - amGetAdUnitsStub.returns(adUnits); - amStub = sinon.stub(auctionManager, 'getBidsReceived'); - }); - - beforeEach(function () { - config.setConfig({ - adpod: { - brandCategoryExclusion: false, - deferCaching: false - } - }); - }) - - afterEach(function() { - config.resetConfig(); - }); - - after(function () { - amGetAdUnitsStub.restore(); - amStub.restore(); - }); - - it('should return targeting for all adunits', function() { - amStub.returns(getBidsReceived()); - let targeting; - adpodUtils.getTargeting({ - callback: function(errorMsg, targetingResult) { - targeting = targetingResult; - } - }); - - expect(targeting['preroll_1'].length).to.equal(3); - expect(targeting['midroll_1'].length).to.equal(3); - }); - - it('should return targeting for passed adunit code', function() { - amStub.returns(getBidsReceived()); - let targeting; - adpodUtils.getTargeting({ - codes: ['preroll_1'], - callback: function(errorMsg, targetingResult) { - targeting = targetingResult; - } - }); - - expect(targeting['preroll_1']).to.exist; - expect(targeting['midroll_1']).to.not.exist; - }); - - it('should only use adpod bids', function() { - const bannerBid = [{ - 'ad': 'creative', - 'cpm': '1.99', - 'width': 300, - 'height': 250, - 'requestId': '1', - 'creativeId': 'some-id', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 360, - 'bidderCode': 'appnexus', - 'statusMessage': 'Bid available', - 'adId': '28f24ced14586c', - 'adUnitCode': 'preroll_1' - }]; - amStub.returns(getBidsReceived().concat(bannerBid)); - let targeting; - adpodUtils.getTargeting({ - callback: function(errorMsg, targetingResult) { - targeting = targetingResult; - } - }); - - expect(targeting['preroll_1'].length).to.equal(3); - expect(targeting['midroll_1'].length).to.equal(3); - }); - - it('should return unique category bids when competitive exclusion is enabled', function() { - config.setConfig({ - adpod: { - brandCategoryExclusion: true, - deferCaching: false - } - }); - amStub.returns([ - createBid(10, 'preroll_1', 30, '10.00_395_30s', '123', '395'), - createBid(15, 'preroll_1', 30, '15.00_395_30s', '123', '395'), - createBid(15, 'midroll_1', 60, '15.00_406_60s', '123', '406'), - createBid(10, 'preroll_1', 30, '10.00_395_30s', '123', '395') - ]); - let targeting; - adpodUtils.getTargeting({ - callback: function(errorMsg, targetingResult) { - targeting = targetingResult; - } - }); - - expect(targeting['preroll_1'].length).to.equal(3); - expect(targeting['midroll_1'].length).to.equal(2); - }); - - it('should only select bids less than adpod duration', function() { - amStub.returns([ - createBid(10, 'preroll_1', 90, '10.00_395_90s', '123', '395'), - createBid(15, 'preroll_1', 90, '15.00_395_90s', '123', '395'), - createBid(15, 'midroll_1', 90, '15.00_406_90s', '123', '406') - ]); - let targeting; - adpodUtils.getTargeting({ - callback: function(errorMsg, targetingResult) { - targeting = targetingResult; - } - }); - - expect(targeting['preroll_1']).to.be.empty; - expect(targeting['midroll_1']).to.be.empty; - }); - - it('should select bids when deferCaching is enabled', function() { - config.setConfig({ - adpod: { - deferCaching: true - } - }); - amStub.returns(getBidsReceived()); - let targeting; - adpodUtils.getTargeting({ - callback: function(errorMsg, targetingResult) { - targeting = targetingResult; - } - }); - - server.requests[0].respond( - 200, - { 'Content-Type': 'text/plain' }, - JSON.stringify({'responses': getBidsReceived().slice(0, 4)}) - ); - - expect(targeting['preroll_1'].length).to.equal(3); - expect(targeting['midroll_1'].length).to.equal(3); - }); - - it('should prioritize bids with deal', function() { - config.setConfig({ - adpod: { - deferCaching: true, - prioritizeDeals: true - } - }); - - const tier6Bid = createBid(10, 'preroll_1', 15, 'tier6_395_15s', '123', '395'); - tier6Bid['video']['dealTier'] = 'tier6' - - const tier7Bid = createBid(11, 'preroll_1', 45, 'tier7_395_15s', '123', '395'); - tier7Bid['video']['dealTier'] = 'tier7' - - const bidsReceived = [ - tier6Bid, - tier7Bid, - createBid(15, 'preroll_1', 90, '15.00_395_90s', '123', '395'), - ] - amStub.returns(bidsReceived); - let targeting; - adpodUtils.getTargeting({ - callback: function(errorMsg, targetingResult) { - targeting = targetingResult; - } - }); - - server.requests[0].respond( - 200, - { 'Content-Type': 'text/plain' }, - JSON.stringify({'responses': bidsReceived.slice(1)}) - ); - - expect(targeting['preroll_1'].length).to.equal(3); - expect(targeting['preroll_1']).to.deep.include({'hb_pb_cat_dur': 'tier6_395_15s'}); - expect(targeting['preroll_1']).to.deep.include({'hb_pb_cat_dur': 'tier7_395_15s'}); - expect(targeting['preroll_1']).to.deep.include({'hb_cache_id': '123'}); - }); - - it('should apply minDealTier to bids if configured', function() { - config.setConfig({ - adpod: { - deferCaching: true, - prioritizeDeals: true, - dealTier: { - 'appnexus': { - prefix: 'tier', - minDealTier: 5 - } - } - } - }); - - const tier2Bid = createBid(10, 'preroll_1', 15, 'tier2_395_15s', '123', '395'); - tier2Bid['video']['dealTier'] = 2 - tier2Bid['adserverTargeting']['hb_pb'] = '10.00' - - const tier7Bid = createBid(11, 'preroll_1', 45, 'tier7_395_15s', '123', '395'); - tier7Bid['video']['dealTier'] = 7 - tier7Bid['adserverTargeting']['hb_pb'] = '11.00' - - const bid = createBid(15, 'preroll_1', 15, '15.00_395_90s', '123', '395'); - bid['adserverTargeting']['hb_pb'] = '15.00' - - const bidsReceived = [ - tier2Bid, - tier7Bid, - bid - ] - amStub.returns(bidsReceived); - let targeting; - adpodUtils.getTargeting({ - callback: function(errorMsg, targetingResult) { - targeting = targetingResult; - } - }); - - server.requests[0].respond( - 200, - { 'Content-Type': 'text/plain' }, - JSON.stringify({'responses': [tier7Bid, bid]}) - ); - - expect(targeting['preroll_1'].length).to.equal(3); - expect(targeting['preroll_1']).to.deep.include({'hb_pb_cat_dur': 'tier7_395_15s'}); - expect(targeting['preroll_1']).to.deep.include({'hb_pb_cat_dur': '15.00_395_90s'}); - expect(targeting['preroll_1']).to.not.include({'hb_pb_cat_dur': 'tier2_395_15s'}); - expect(targeting['preroll_1']).to.deep.include({'hb_cache_id': '123'}); - }) -}); - -function getBidsReceived() { - return [ - createBid(10, 'preroll_1', 15, '10.00_395_15s', '123', '395'), - createBid(15, 'preroll_1', 15, '15.00_395_15s', '123', '395'), - createBid(15, 'midroll_1', 30, '15.00_406_30s', '123', '406'), - createBid(5, 'midroll_1', 5, '5.00_406_5s', '123', '406'), - createBid(20, 'midroll_1', 60, '20.00_406_60s', '123', '406'), - ] -} - -function createBid(cpm, adUnitCode, durationBucket, priceIndustryDuration, uuid, industry) { - return { - 'bidderCode': 'appnexus', - 'width': 640, - 'height': 360, - 'statusMessage': 'Bid available', - 'adId': '28f24ced14586c', - 'mediaType': 'video', - 'source': 'client', - 'requestId': '28f24ced14586c', - 'cpm': cpm, - 'creativeId': 97517771, - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 3600, - 'adUnitCode': adUnitCode, - 'video': { - 'context': 'adpod', - 'durationBucket': durationBucket - }, - 'appnexus': { - 'buyerMemberId': 9325 - }, - 'vastUrl': 'http://some-vast-url.com', - 'vastImpUrl': 'http://some-vast-imp-url.com', - 'auctionId': 'ec266b31-d652-49c5-8295-e83fafe5532b', - 'responseTimestamp': 1548442460888, - 'requestTimestamp': 1548442460827, - 'bidder': 'appnexus', - 'timeToRespond': 61, - 'pbLg': '5.00', - 'pbMg': '5.00', - 'pbHg': '5.00', - 'pbAg': '5.00', - 'pbDg': '5.00', - 'pbCg': '', - 'size': '640x360', - 'adserverTargeting': { - 'hb_bidder': 'appnexus', - 'hb_adid': '28f24ced14586c', - 'hb_pb': '5.00', - 'hb_size': '640x360', - 'hb_source': 'client', - 'hb_format': 'video', - 'hb_pb_cat_dur': priceIndustryDuration, - 'hb_cache_id': uuid - }, - 'customCacheKey': `${priceIndustryDuration}_${uuid}`, - 'meta': { - 'primaryCatId': 'iab-1', - 'adServerCatId': industry - }, - 'videoCacheKey': '4cf395af-8fee-4960-af0e-88d44e399f14' - } -} diff --git a/test/spec/modules/gamAdpod_spec.js b/test/spec/modules/gamAdpod_spec.js deleted file mode 100644 index 31e142d11f8..00000000000 --- a/test/spec/modules/gamAdpod_spec.js +++ /dev/null @@ -1,257 +0,0 @@ -import {auctionManager} from '../../../src/auctionManager.js'; -import {config} from '../../../src/config.js'; -import {gdprDataHandler, uspDataHandler} from '../../../src/consentHandler.js'; -import parse from 'url-parse'; -import {buildAdpodVideoUrl} from '../../../modules/gamAdpod.js'; -import {expect} from 'chai/index.js'; -import * as utils from '../../../src/utils.js'; -import {server} from '../../mocks/xhr.js'; -import * as adpod from 'modules/adpod.js'; - -describe('gamAdpod', function () { - let amStub; - let amGetAdUnitsStub; - - before(function () { - const adUnits = [{ - code: 'adUnitCode-1', - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 60, - durationRangeSec: [15, 30], - requireExactDuration: true - } - }, - bids: [ - { - bidder: 'appnexus', - params: { - placementId: 14542875, - } - } - ] - }]; - - amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits'); - amGetAdUnitsStub.returns(adUnits); - amStub = sinon.stub(auctionManager, 'getBidsReceived'); - }); - - beforeEach(function () { - config.setConfig({ - adpod: { - brandCategoryExclusion: true, - deferCaching: false - } - }); - }) - - afterEach(function() { - config.resetConfig(); - }); - - after(function () { - amGetAdUnitsStub.restore(); - amStub.restore(); - }); - - function getBidsReceived() { - return [ - createBid(10, 'adUnitCode-1', 15, '10.00_395_15s', '123', '395', '10.00'), - createBid(15, 'adUnitCode-1', 15, '15.00_395_15s', '123', '395', '15.00'), - createBid(25, 'adUnitCode-1', 30, '15.00_406_30s', '123', '406', '25.00'), - ] - } - - function createBid(cpm, adUnitCode, durationBucket, priceIndustryDuration, uuid, label, hbpb) { - return { - 'bidderCode': 'appnexus', - 'width': 640, - 'height': 360, - 'statusMessage': 'Bid available', - 'adId': '28f24ced14586c', - 'mediaType': 'video', - 'source': 'client', - 'requestId': '28f24ced14586c', - 'cpm': cpm, - 'creativeId': 97517771, - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 3600, - 'adUnitCode': adUnitCode, - 'video': { - 'context': 'adpod', - 'durationBucket': durationBucket - }, - 'appnexus': { - 'buyerMemberId': 9325 - }, - 'vastUrl': 'http://some-vast-url.com', - 'vastImpUrl': 'http://some-vast-imp-url.com', - 'auctionId': 'ec266b31-d652-49c5-8295-e83fafe5532b', - 'responseTimestamp': 1548442460888, - 'requestTimestamp': 1548442460827, - 'bidder': 'appnexus', - 'timeToRespond': 61, - 'pbLg': '5.00', - 'pbMg': '5.00', - 'pbHg': '5.00', - 'pbAg': '5.00', - 'pbDg': '5.00', - 'pbCg': '', - 'size': '640x360', - 'adserverTargeting': { - 'hb_bidder': 'appnexus', - 'hb_adid': '28f24ced14586c', - 'hb_pb': hbpb, - 'hb_size': '640x360', - 'hb_source': 'client', - 'hb_format': 'video', - 'hb_pb_cat_dur': priceIndustryDuration, - 'hb_cache_id': uuid - }, - 'customCacheKey': `${priceIndustryDuration}_${uuid}`, - 'meta': { - 'primaryCatId': 'iab-1', - 'adServerCatId': label - }, - 'videoCacheKey': '4cf395af-8fee-4960-af0e-88d44e399f14' - } - } - - it('should return masterTag url', function() { - amStub.returns(getBidsReceived()); - const uspDataHandlerStub = sinon.stub(uspDataHandler, 'getConsentData'); - uspDataHandlerStub.returns('1YYY'); - const gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData'); - gdprDataHandlerStub.returns({ - gdprApplies: true, - consentString: 'consent', - addtlConsent: 'moreConsent' - }); - let url; - parse(buildAdpodVideoUrl({ - code: 'adUnitCode-1', - callback: handleResponse, - params: { - 'iu': 'my/adUnit', - 'description_url': 'someUrl.com', - } - })); - - function handleResponse(err, masterTag) { - if (err) { - return; - } - url = parse(masterTag); - - expect(url.protocol).to.equal('https:'); - expect(url.host).to.equal('securepubads.g.doubleclick.net'); - - const queryParams = utils.parseQS(url.query); - expect(queryParams).to.have.property('correlator'); - expect(queryParams).to.have.property('description_url', 'someUrl.com'); - expect(queryParams).to.have.property('env', 'vp'); - expect(queryParams).to.have.property('gdfp_req', '1'); - expect(queryParams).to.have.property('iu', 'my/adUnit'); - expect(queryParams).to.have.property('output', 'vast'); - expect(queryParams).to.have.property('sz', '640x480'); - expect(queryParams).to.have.property('unviewed_position_start', '1'); - expect(queryParams).to.have.property('url'); - expect(queryParams).to.have.property('cust_params'); - expect(queryParams).to.have.property('gdpr', '1'); - expect(queryParams).to.have.property('gdpr_consent', 'consent'); - expect(queryParams).to.have.property('addtl_consent', 'moreConsent'); - - const custParams = utils.parseQS(decodeURIComponent(queryParams.cust_params)); - expect(custParams).to.have.property('hb_cache_id', '123'); - expect(custParams).to.have.property('hb_pb_cat_dur', '15.00_395_15s,15.00_406_30s,10.00_395_15s'); - uspDataHandlerStub.restore(); - gdprDataHandlerStub.restore(); - } - }); - - it('should return masterTag url with correct custom params when brandCategoryExclusion is false', function() { - config.setConfig({ - adpod: { - brandCategoryExclusion: false, - } - }); - function getBids() { - const bids = [ - createBid(10, 'adUnitCode-1', 15, '10.00_15s', '123', '395', '10.00'), - createBid(15, 'adUnitCode-1', 15, '15.00_15s', '123', '395', '15.00'), - createBid(25, 'adUnitCode-1', 30, '15.00_30s', '123', '406', '25.00'), - ]; - bids.forEach((bid) => { - delete bid.meta; - }); - return bids; - } - amStub.returns(getBids()); - let url; - parse(buildAdpodVideoUrl({ - code: 'adUnitCode-1', - callback: handleResponse, - params: { - 'iu': 'my/adUnit', - 'description_url': 'someUrl.com', - } - })); - - function handleResponse(err, masterTag) { - if (err) { - return; - } - url = parse(masterTag); - expect(url.protocol).to.equal('https:'); - expect(url.host).to.equal('securepubads.g.doubleclick.net'); - - const queryParams = utils.parseQS(url.query); - expect(queryParams).to.have.property('correlator'); - expect(queryParams).to.have.property('description_url', 'someUrl.com'); - expect(queryParams).to.have.property('env', 'vp'); - expect(queryParams).to.have.property('gdfp_req', '1'); - expect(queryParams).to.have.property('iu', 'my/adUnit'); - expect(queryParams).to.have.property('output', 'xml_vast3'); - expect(queryParams).to.have.property('sz', '640x480'); - expect(queryParams).to.have.property('unviewed_position_start', '1'); - expect(queryParams).to.have.property('url'); - expect(queryParams).to.have.property('cust_params'); - - const custParams = utils.parseQS(decodeURIComponent(queryParams.cust_params)); - expect(custParams).to.have.property('hb_cache_id', '123'); - expect(custParams).to.have.property('hb_pb_cat_dur', '10.00_15s,15.00_15s,15.00_30s'); - } - }); - - it('should handle error when cache fails', function() { - config.setConfig({ - adpod: { - brandCategoryExclusion: true, - deferCaching: true - } - }); - amStub.returns(getBidsReceived()); - - parse(buildAdpodVideoUrl({ - code: 'adUnitCode-1', - callback: handleResponse, - params: { - 'iu': 'my/adUnit', - 'description_url': 'someUrl.com', - } - })); - - server.requests[0].respond(503, { - 'Content-Type': 'plain/text', - }, 'The server could not save anything at the moment.'); - - function handleResponse(err, masterTag) { - expect(masterTag).to.be.null; - expect(err).to.be.an('error'); - } - }); -}) diff --git a/test/spec/modules/mediafuseBidAdapter_spec.js b/test/spec/modules/mediafuseBidAdapter_spec.js index ff806d91f2c..d2142a5c14e 100644 --- a/test/spec/modules/mediafuseBidAdapter_spec.js +++ b/test/spec/modules/mediafuseBidAdapter_spec.js @@ -347,185 +347,6 @@ describe('MediaFuseAdapter', function () { expect(payload.tags[0].reserve).to.exist.and.to.equal(3); }); - it('should duplicate adpod placements into batches and set correct maxduration', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - - // 300 / 15 = 20 total - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(5); - - expect(payload1.tags[0]).to.deep.equal(payload1.tags[1]); - expect(payload1.tags[0].video.maxduration).to.equal(30); - - expect(payload2.tags[0]).to.deep.equal(payload1.tags[1]); - expect(payload2.tags[0].video.maxduration).to.equal(30); - }); - - it('should round down adpod placements when numbers are uneven', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 123, - durationRangeSec: [45], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags.length).to.equal(2); - }); - - it('should duplicate adpod placements when requireExactDuration is set', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - requireExactDuration: true, - } - } - } - ); - - // 20 total placements with 15 max impressions = 2 requests - const request = spec.buildRequests([bidRequest]); - expect(request.length).to.equal(2); - - // 20 spread over 2 requests = 15 in first request, 5 in second - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(5); - - // 10 placements should have max/min at 15 - // 10 placemenst should have max/min at 30 - const payload1tagsWith15 = payload1.tags.filter(tag => tag.video.maxduration === 15); - const payload1tagsWith30 = payload1.tags.filter(tag => tag.video.maxduration === 30); - expect(payload1tagsWith15.length).to.equal(10); - expect(payload1tagsWith30.length).to.equal(5); - - // 5 placemenst with min/max at 30 were in the first request - // so 5 remaining should be in the second - const payload2tagsWith30 = payload2.tags.filter(tag => tag.video.maxduration === 30); - expect(payload2tagsWith30.length).to.equal(5); - }); - - it('should set durations for placements when requireExactDuration is set and numbers are uneven', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 105, - durationRangeSec: [15, 30, 60], - requireExactDuration: true, - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags.length).to.equal(7); - - const tagsWith15 = payload.tags.filter(tag => tag.video.maxduration === 15); - const tagsWith30 = payload.tags.filter(tag => tag.video.maxduration === 30); - const tagsWith60 = payload.tags.filter(tag => tag.video.maxduration === 60); - expect(tagsWith15.length).to.equal(3); - expect(tagsWith30.length).to.equal(3); - expect(tagsWith60.length).to.equal(1); - }); - - it('should break adpod request into batches', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 225, - durationRangeSec: [5], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - const payload3 = JSON.parse(request[2].data); - - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(15); - expect(payload3.tags.length).to.equal(15); - }); - - it('should contain hb_source value for adpod', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - } - } - } - ); - const request = spec.buildRequests([bidRequest])[0]; - const payload = JSON.parse(request.data); - expect(payload.tags[0].hb_source).to.deep.equal(7); - }); - it('should contain hb_source value for other media', function() { const bidRequest = Object.assign({}, bidRequests[0], @@ -542,21 +363,6 @@ describe('MediaFuseAdapter', function () { expect(payload.tags[0].hb_source).to.deep.equal(1); }); - it('adds brand_category_exclusion to request when set', function() { - const bidRequest = Object.assign({}, bidRequests[0]); - sinon - .stub(config, 'getConfig') - .withArgs('adpod.brandCategoryExclusion') - .returns(true); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.brand_category_uniqueness).to.equal(true); - - config.getConfig.restore(); - }); - it('adds auction level keywords to request when set', function() { const bidRequest = Object.assign({}, bidRequests[0]); sinon @@ -1261,46 +1067,6 @@ describe('MediaFuseAdapter', function () { expect(result[0]).to.have.property('mediaType', 'video'); }); - it('handles adpod responses', function () { - const response = { - 'tags': [{ - 'uuid': '84ab500420319d', - 'ads': [{ - 'ad_type': 'video', - 'brand_category_id': 10, - 'cpm': 0.500000, - 'notify_url': 'imptracker.com', - 'rtb': { - 'video': { - 'asset_url': 'https://sample.vastURL.com/here/adpod', - 'duration_ms': 30000, - } - }, - 'viewability': { - 'config': '' - } - }] - }] - }; - - const bidderRequest = { - bids: [{ - bidId: '84ab500420319d', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'adpod' - } - } - }] - }; - - const result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(result[0]).to.have.property('vastUrl'); - expect(result[0].video.context).to.equal('adpod'); - expect(result[0].video.durationSeconds).to.equal(30); - }); - it('handles native responses', function () { const response1 = deepClone(response); response1.tags[0].ads[0].ad_type = 'native'; @@ -1378,33 +1144,6 @@ describe('MediaFuseAdapter', function () { ); }); - it('should add deal_priority and deal_code', function() { - const responseWithDeal = deepClone(response); - responseWithDeal.tags[0].ads[0].ad_type = 'video'; - responseWithDeal.tags[0].ads[0].deal_priority = 5; - responseWithDeal.tags[0].ads[0].deal_code = '123'; - responseWithDeal.tags[0].ads[0].rtb.video = { - duration_ms: 1500, - player_width: 640, - player_height: 340, - }; - - const bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'adpod' - } - } - }] - } - const result = spec.interpretResponse({ body: responseWithDeal }, {bidderRequest}); - expect(Object.keys(result[0].mediafuse)).to.include.members(['buyerMemberId', 'dealPriority', 'dealCode']); - expect(result[0].video.dealTier).to.equal(5); - }); - it('should add advertiser id', function() { const responseAdvertiserId = deepClone(response); responseAdvertiserId.tags[0].ads[0].advertiser_id = '123'; diff --git a/test/spec/modules/smaatoBidAdapter_spec.js b/test/spec/modules/smaatoBidAdapter_spec.js index f1bd464fbdd..8e7a21a92bb 100644 --- a/test/spec/modules/smaatoBidAdapter_spec.js +++ b/test/spec/modules/smaatoBidAdapter_spec.js @@ -79,29 +79,11 @@ describe('smaatoBidAdapterTest', () => { expect(spec.isBidRequestValid({params: {publisherId: 123}})).to.be.false; }); - describe('for ad pod / long form video requests', () => { - const ADPOD = {video: {context: 'adpod'}} - it('is invalid, when adbreakId is missing', () => { - expect(spec.isBidRequestValid({mediaTypes: ADPOD, params: {publisherId: '123'}})).to.be.false; - }); - - it('is invalid, when adbreakId is present but of wrong type', () => { - expect(spec.isBidRequestValid({mediaTypes: ADPOD, params: {publisherId: '123', adbreakId: 456}})).to.be.false; - }); - - it('is valid, when required params are present', () => { - expect(spec.isBidRequestValid({mediaTypes: ADPOD, params: {publisherId: '123', adbreakId: '456'}})).to.be.true; - }); - - it('is invalid, when forbidden adspaceId param is present', () => { - expect(spec.isBidRequestValid({ - mediaTypes: ADPOD, - params: {publisherId: '123', adbreakId: '456', adspaceId: '42'} - })).to.be.false; - }); + it('is invalid, when adbreakId param is present', () => { + expect(spec.isBidRequestValid({params: {publisherId: '123', adspaceId: '456', adbreakId: '42'}})).to.be.false; }); - describe('for non adpod requests', () => { + describe('for supported requests', () => { it('is invalid, when adspaceId is missing', () => { expect(spec.isBidRequestValid({params: {publisherId: '123'}})).to.be.false; }); @@ -672,299 +654,6 @@ describe('smaatoBidAdapterTest', () => { expect(JSON.parse(reqs[1].data).imp[0].banner).to.not.exist; expect(JSON.parse(reqs[1].data).imp[0].video).to.deep.equal(VIDEO_OUTSTREAM_OPENRTB_IMP); }); - - describe('ad pod / long form video', () => { - describe('required parameters with requireExactDuration false', () => { - const ADBREAK_ID = 'adbreakId'; - const ADPOD = 'adpod'; - const BID_ID = '4331'; - const W = 640; - const H = 480; - const ADPOD_DURATION = 300; - const DURATION_RANGE = [15, 30]; - const longFormVideoBidRequest = { - params: { - publisherId: 'publisherId', - adbreakId: ADBREAK_ID, - }, - mediaTypes: { - video: { - context: ADPOD, - playerSize: [[W, H]], - adPodDurationSec: ADPOD_DURATION, - durationRangeSec: DURATION_RANGE, - requireExactDuration: false - } - }, - bidId: BID_ID - }; - - it('sends required fields', () => { - const reqs = spec.buildRequests([longFormVideoBidRequest], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.id).to.exist; - expect(req.imp.length).to.be.equal(ADPOD_DURATION / DURATION_RANGE[0]); - expect(req.imp[0].id).to.be.equal(BID_ID); - expect(req.imp[0].tagid).to.be.equal(ADBREAK_ID); - expect(req.imp[0].bidfloor).to.be.undefined; - expect(req.imp[0].video.ext.context).to.be.equal(ADPOD); - expect(req.imp[0].video.w).to.be.equal(W); - expect(req.imp[0].video.h).to.be.equal(H); - expect(req.imp[0].video.maxduration).to.be.equal(DURATION_RANGE[1]); - expect(req.imp[0].video.sequence).to.be.equal(1); - expect(req.imp[1].id).to.be.equal(BID_ID); - expect(req.imp[1].tagid).to.be.equal(ADBREAK_ID); - expect(req.imp[1].bidfloor).to.be.undefined; - expect(req.imp[1].video.ext.context).to.be.equal(ADPOD); - expect(req.imp[1].video.w).to.be.equal(W); - expect(req.imp[1].video.h).to.be.equal(H); - expect(req.imp[1].video.maxduration).to.be.equal(DURATION_RANGE[1]); - expect(req.imp[1].video.sequence).to.be.equal(2); - }); - - it('sends instl if instl exists', () => { - const instl = {instl: 1}; - const bidRequestWithInstl = Object.assign({}, longFormVideoBidRequest, {ortb2Imp: instl}); - - const reqs = spec.buildRequests([bidRequestWithInstl], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.imp[0].instl).to.equal(1); - expect(req.imp[1].instl).to.equal(1); - }); - - it('sends bidfloor when configured', () => { - const longFormVideoBidRequestWithFloor = Object.assign({}, longFormVideoBidRequest); - longFormVideoBidRequestWithFloor.getFloor = function (arg) { - if (arg.currency === 'USD' && - arg.mediaType === 'video' && - JSON.stringify(arg.size) === JSON.stringify([640, 480])) { - return { - currency: 'USD', - floor: 0.789 - } - } - } - const reqs = spec.buildRequests([longFormVideoBidRequestWithFloor], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.imp[0].bidfloor).to.be.equal(0.789); - expect(req.imp[1].bidfloor).to.be.equal(0.789); - }); - - it('sends brand category exclusion as true when config is set to true', () => { - config.setConfig({adpod: {brandCategoryExclusion: true}}); - - const reqs = spec.buildRequests([longFormVideoBidRequest], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.imp[0].video.ext.brandcategoryexclusion).to.be.equal(true); - }); - - it('sends brand category exclusion as false when config is set to false', () => { - config.setConfig({adpod: {brandCategoryExclusion: false}}); - - const reqs = spec.buildRequests([longFormVideoBidRequest], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.imp[0].video.ext.brandcategoryexclusion).to.be.equal(false); - }); - - it('sends brand category exclusion as false when config is not set', () => { - const reqs = spec.buildRequests([longFormVideoBidRequest], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.imp[0].video.ext.brandcategoryexclusion).to.be.equal(false); - }); - }); - describe('required parameters with requireExactDuration true', () => { - const ADBREAK_ID = 'adbreakId'; - const ADPOD = 'adpod'; - const BID_ID = '4331'; - const W = 640; - const H = 480; - const ADPOD_DURATION = 5; - const DURATION_RANGE = [5, 15, 25]; - const longFormVideoBidRequest = { - params: { - publisherId: 'publisherId', - adbreakId: ADBREAK_ID, - }, - mediaTypes: { - video: { - context: ADPOD, - playerSize: [[W, H]], - adPodDurationSec: ADPOD_DURATION, - durationRangeSec: DURATION_RANGE, - requireExactDuration: true - } - }, - bidId: BID_ID - }; - - it('sends required fields', () => { - const reqs = spec.buildRequests([longFormVideoBidRequest], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.id).to.exist; - expect(req.imp.length).to.be.equal(DURATION_RANGE.length); - expect(req.imp[0].id).to.be.equal(BID_ID); - expect(req.imp[0].tagid).to.be.equal(ADBREAK_ID); - expect(req.imp[0].video.ext.context).to.be.equal(ADPOD); - expect(req.imp[0].video.w).to.be.equal(W); - expect(req.imp[0].video.h).to.be.equal(H); - expect(req.imp[0].video.minduration).to.be.equal(DURATION_RANGE[0]); - expect(req.imp[0].video.maxduration).to.be.equal(DURATION_RANGE[0]); - expect(req.imp[0].video.sequence).to.be.equal(1); - expect(req.imp[1].id).to.be.equal(BID_ID); - expect(req.imp[1].tagid).to.be.equal(ADBREAK_ID); - expect(req.imp[1].video.ext.context).to.be.equal(ADPOD); - expect(req.imp[1].video.w).to.be.equal(W); - expect(req.imp[1].video.h).to.be.equal(H); - expect(req.imp[1].video.minduration).to.be.equal(DURATION_RANGE[1]); - expect(req.imp[1].video.maxduration).to.be.equal(DURATION_RANGE[1]); - expect(req.imp[1].video.sequence).to.be.equal(2); - expect(req.imp[2].id).to.be.equal(BID_ID); - expect(req.imp[2].tagid).to.be.equal(ADBREAK_ID); - expect(req.imp[2].video.ext.context).to.be.equal(ADPOD); - expect(req.imp[2].video.w).to.be.equal(W); - expect(req.imp[2].video.h).to.be.equal(H); - expect(req.imp[2].video.minduration).to.be.equal(DURATION_RANGE[2]); - expect(req.imp[2].video.maxduration).to.be.equal(DURATION_RANGE[2]); - expect(req.imp[2].video.sequence).to.be.equal(3); - }); - }); - - describe('forwarding of optional parameters', () => { - const MIMES = ['video/mp4', 'video/quicktime', 'video/3gpp', 'video/x-m4v']; - const STARTDELAY = 0; - const LINEARITY = 1; - const SKIP = 1; - const PROTOCOLS = [7]; - const SKIPMIN = 5; - const API = [7]; - const validBasicAdpodBidRequest = { - params: { - publisherId: 'publisherId', - adbreakId: 'adbreakId', - }, - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - mimes: MIMES, - startdelay: STARTDELAY, - linearity: LINEARITY, - skip: SKIP, - protocols: PROTOCOLS, - skipmin: SKIPMIN, - api: API - } - }, - bidId: 'bidId' - }; - - it('sends general video fields when they are present', () => { - const reqs = spec.buildRequests([validBasicAdpodBidRequest], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.imp[0].video.mimes).to.eql(MIMES); - expect(req.imp[0].video.startdelay).to.be.equal(STARTDELAY); - expect(req.imp[0].video.linearity).to.be.equal(LINEARITY); - expect(req.imp[0].video.skip).to.be.equal(SKIP); - expect(req.imp[0].video.protocols).to.eql(PROTOCOLS); - expect(req.imp[0].video.skipmin).to.be.equal(SKIPMIN); - expect(req.imp[0].video.api).to.eql(API); - }); - - it('sends series name when parameter is present', () => { - const SERIES_NAME = 'foo' - const adpodRequestWithParameter = utils.deepClone(validBasicAdpodBidRequest); - adpodRequestWithParameter.mediaTypes.video.tvSeriesName = SERIES_NAME; - - const reqs = spec.buildRequests([adpodRequestWithParameter], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.site.content.series).to.be.equal(SERIES_NAME); - }); - - it('sends episode name when parameter is present', () => { - const EPISODE_NAME = 'foo' - const adpodRequestWithParameter = utils.deepClone(validBasicAdpodBidRequest); - adpodRequestWithParameter.mediaTypes.video.tvEpisodeName = EPISODE_NAME; - - const reqs = spec.buildRequests([adpodRequestWithParameter], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.site.content.title).to.be.equal(EPISODE_NAME); - }); - - it('sends season number as string when parameter is present', () => { - const SEASON_NUMBER_AS_NUMBER_IN_PREBID_REQUEST = 42 - const SEASON_NUMBER_AS_STRING_IN_OUTGOING_REQUEST = '42' - const adpodRequestWithParameter = utils.deepClone(validBasicAdpodBidRequest); - adpodRequestWithParameter.mediaTypes.video.tvSeasonNumber = SEASON_NUMBER_AS_NUMBER_IN_PREBID_REQUEST; - - const reqs = spec.buildRequests([adpodRequestWithParameter], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.site.content.season).to.be.equal(SEASON_NUMBER_AS_STRING_IN_OUTGOING_REQUEST); - }); - - it('sends episode number when parameter is present', () => { - const EPISODE_NUMBER = 42 - const adpodRequestWithParameter = utils.deepClone(validBasicAdpodBidRequest); - adpodRequestWithParameter.mediaTypes.video.tvEpisodeNumber = EPISODE_NUMBER; - - const reqs = spec.buildRequests([adpodRequestWithParameter], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.site.content.episode).to.be.equal(EPISODE_NUMBER); - }); - - it('sends content length when parameter is present', () => { - const LENGTH = 42 - const adpodRequestWithParameter = utils.deepClone(validBasicAdpodBidRequest); - adpodRequestWithParameter.mediaTypes.video.contentLengthSec = LENGTH; - - const reqs = spec.buildRequests([adpodRequestWithParameter], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.site.content.len).to.be.equal(LENGTH); - }); - - it('sends livestream as 1 when content mode parameter is live', () => { - const adpodRequestWithParameter = utils.deepClone(validBasicAdpodBidRequest); - adpodRequestWithParameter.mediaTypes.video.contentMode = 'live'; - - const reqs = spec.buildRequests([adpodRequestWithParameter], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.site.content.livestream).to.be.equal(1); - }); - - it('sends livestream as 0 when content mode parameter is on-demand', () => { - const adpodRequestWithParameter = utils.deepClone(validBasicAdpodBidRequest); - adpodRequestWithParameter.mediaTypes.video.contentMode = 'on-demand'; - - const reqs = spec.buildRequests([adpodRequestWithParameter], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.site.content.livestream).to.be.equal(0); - }); - - it('doesn\'t send any optional parameters when none are present', () => { - const reqs = spec.buildRequests([validBasicAdpodBidRequest], defaultBidderRequest); - - const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.imp[0].video.ext.requireExactDuration).to.not.exist; - expect(req.site.content).to.not.exist; - }); - }); - }); } }); @@ -1539,7 +1228,6 @@ describe('smaatoBidAdapterTest', () => { }); describe('ad pod', () => { - const bidRequestWithAdpodContext = buildBidRequest({imp: [{video: {ext: {context: 'adpod'}}}]}); const PRIMARY_CAT_ID = 1337 const serverResponse = { body: { @@ -1578,44 +1266,6 @@ describe('smaatoBidAdapterTest', () => { }, headers: {get: () => undefined} }; - - it('sets required values for adpod bid from server response', () => { - const bids = spec.interpretResponse(serverResponse, bidRequestWithAdpodContext); - - expect(bids).to.deep.equal([ - { - requestId: '226416e6e6bf41', - cpm: 0.01, - width: 350, - height: 50, - vastXml: '', - ttl: 300, - creativeId: 'CR69381', - dealId: '12345', - netRevenue: true, - currency: 'USD', - mediaType: 'video', - video: { - context: 'adpod', - durationSeconds: 42 - }, - meta: { - advertiserDomains: ['smaato.com'], - agencyId: 'CM6523', - networkName: 'smaato', - mediaType: 'video' - } - } - ]); - }); - - it('sets primary category id in case of enabled brand category exclusion', () => { - config.setConfig({adpod: {brandCategoryExclusion: true}}); - - const bids = spec.interpretResponse(serverResponse, bidRequestWithAdpodContext) - - expect(bids[0].meta.primaryCatId).to.be.equal(PRIMARY_CAT_ID) - }) }); it('uses correct TTL when expire header exists', () => { diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 3ce5db91ef2..344229346c5 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -1113,17 +1113,6 @@ describe('targeting tests', function () { expect(targeting[nativeAdUnitCode].hb_pb_dgads).to.exist.and.to.equal(nativeBid2.pbMg); }); } - - it('does not include adpod type bids in the getBidsReceived results', function () { - const adpodBid = utils.deepClone(bid1); - adpodBid.video = { context: 'adpod', durationSeconds: 15, durationBucket: 15 }; - adpodBid.cpm = 5; - bidsReceived.push(adpodBid); - - const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); - expect(targeting['/123456/header-bid-tag-0']).to.contain.keys('hb_deal', 'hb_adid', 'hb_bidder'); - expect(targeting['/123456/header-bid-tag-0']['hb_adid']).to.equal(bid1.adId); - }); }); // end getAllTargeting tests describe('getAllTargeting will work correctly when a hook raises has modified flag in getHighestCpmBidsFromBidPool', function () { diff --git a/test/test_deps.js b/test/test_deps.js index 5f0ab890035..a960d5f2d87 100644 --- a/test/test_deps.js +++ b/test/test_deps.js @@ -56,6 +56,5 @@ require('test/mocks/adloaderStub.js'); require('test/mocks/xhr.js'); require('test/mocks/analyticsStub.js'); require('test/mocks/ortbConverter.js') -require('modules/categoryTranslation.js'); require('modules/rtdModule/index.js'); require('modules/fpdModule/index.js'); From b077e17855d6a89ac0ee8f12ccfae08ebdc2d167 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 11 Feb 2026 14:02:24 -0500 Subject: [PATCH 20/48] Prebid 11: 33across id system: make compatible with storage control change (#14462) * 33across ID Adapter: stabilize hashed email cleanup test * 33across Id System: gate HEM persistence on storeFpid * Update 33acrossIdSystem.js --- test/spec/modules/33acrossIdSystem_spec.js | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/test/spec/modules/33acrossIdSystem_spec.js b/test/spec/modules/33acrossIdSystem_spec.js index 909fef4c6fa..5553d44b9a4 100644 --- a/test/spec/modules/33acrossIdSystem_spec.js +++ b/test/spec/modules/33acrossIdSystem_spec.js @@ -520,6 +520,40 @@ describe('33acrossIdSystem', () => { setDataInLocalStorage.restore(); }); + + it('should not store a publisher-provided hashed email in local storage', () => { + const completeCallback = () => {}; + + const { callback } = thirtyThreeAcrossIdSubmodule.getId({ + params: { + pid: '12345', + storeFpid: false, + hem: '33acrossIdHmValue+' + }, + enabledStorageTypes: [ 'html5' ], + storage: {} + }); + + callback(completeCallback); + + const [request] = server.requests; + + const setDataInLocalStorage = sinon.stub(storage, 'setDataInLocalStorage'); + + request.respond(200, { + 'Content-Type': 'application/json' + }, JSON.stringify({ + succeeded: true, + data: { + envelope: 'foo' + }, + expires: 1645667805067 + })); + + expect(setDataInLocalStorage.calledWithExactly('33acrossIdHm', '33acrossIdHmValue+')).to.be.false; + + setDataInLocalStorage.restore(); + }); }); }); @@ -1478,6 +1512,7 @@ describe('33acrossIdSystem', () => { const removeDataFromLocalStorage = sinon.stub(storage, 'removeDataFromLocalStorage'); const setCookie = sinon.stub(storage, 'setCookie'); + const cookiesAreEnabled = sinon.stub(storage, 'cookiesAreEnabled').returns(true); sinon.stub(domainUtils, 'domainOverride').returns('foo.com'); request.respond(200, { @@ -1495,8 +1530,42 @@ describe('33acrossIdSystem', () => { removeDataFromLocalStorage.restore(); setCookie.restore(); + cookiesAreEnabled.restore(); domainUtils.domainOverride.restore(); }); + + it('should not wipe any stored hashed email when first-party ID support is disabled', () => { + const completeCallback = () => {}; + + const { callback } = thirtyThreeAcrossIdSubmodule.getId({ + params: { + pid: '12345', + storeFpid: false + }, + enabledStorageTypes: [ 'html5' ], + storage: {} + }); + + callback(completeCallback); + + const [request] = server.requests; + + const removeDataFromLocalStorage = sinon.stub(storage, 'removeDataFromLocalStorage'); + + request.respond(200, { + 'Content-Type': 'application/json' + }, JSON.stringify({ + succeeded: true, + data: { + // no envelope field + }, + expires: 1645667805067 + })); + + expect(removeDataFromLocalStorage.calledWithExactly('33acrossIdHm')).to.be.false; + + removeDataFromLocalStorage.restore(); + }); }); context('when the server returns an error status code', () => { From 69ee641b67fb04e512edbba839e5c0429c8428c8 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 11 Feb 2026 11:39:59 -0800 Subject: [PATCH 21/48] remove unnecessary storageControl import --- test/spec/libraries/storageDisclosure_spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/spec/libraries/storageDisclosure_spec.js b/test/spec/libraries/storageDisclosure_spec.js index 1f848504ee2..8020b41a233 100644 --- a/test/spec/libraries/storageDisclosure_spec.js +++ b/test/spec/libraries/storageDisclosure_spec.js @@ -1,5 +1,4 @@ import {getStorageDisclosureSummary} from '../../../libraries/storageDisclosure/summary.js'; -import {dynamicDisclosureCollector} from '../../../modules/storageControl.js'; describe('storageDisclosure', () => { let moduleMeta; From 7cc3c7ee9ccebfd648aa16d7635188d089620251 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 11 Feb 2026 12:07:15 -0800 Subject: [PATCH 22/48] Prebid 11: turn off storageControl during testing (#14464) * Prebid 11: turn off storageControl during testing * remove unnecessary setConfig --- modules/storageControl.ts | 7 ++++++- test/spec/modules/storageControl_spec.js | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/modules/storageControl.ts b/modules/storageControl.ts index 0302ece3f4b..2b5f5db2cdd 100644 --- a/modules/storageControl.ts +++ b/modules/storageControl.ts @@ -125,7 +125,12 @@ export function storageControlRule(getEnforcement = () => enforcement, check = c } } -registerActivityControl(ACTIVITY_ACCESS_DEVICE, 'storageControl', storageControlRule()); +const rule = registerActivityControl(ACTIVITY_ACCESS_DEVICE, 'storageControl', storageControlRule()); + +export function deactivate() { + // turn off this module; should only be used in testing + rule(); +} export type StorageControlConfig = { /** diff --git a/test/spec/modules/storageControl_spec.js b/test/spec/modules/storageControl_spec.js index 9ac8a34a463..ff55f5a2c43 100644 --- a/test/spec/modules/storageControl_spec.js +++ b/test/spec/modules/storageControl_spec.js @@ -4,7 +4,8 @@ import { ENFORCE_OFF, ENFORCE_STRICT, getDisclosures, - storageControlRule + storageControlRule, + deactivate } from '../../../modules/storageControl.js'; import { ACTIVITY_PARAM_COMPONENT_NAME, @@ -14,6 +15,10 @@ import { import {MODULE_TYPE_BIDDER} from '../../../src/activities/modules.js'; import {STORAGE_TYPE_COOKIES} from '../../../src/storageManager.js'; +// since the module is on by default, importing it here turn it on for other tests +// that happen to run together with this suite - turn it off +deactivate(); + describe('storageControl', () => { describe('getDisclosures', () => { let metadata; From 76d8f08d17e7cc19cbbef9e9227b0194e910669d Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 11 Feb 2026 15:23:03 -0500 Subject: [PATCH 23/48] =?UTF-8?q?Revert=20"Core:=20remove=20null=20callbac?= =?UTF-8?q?k=20placeholders=20from=20storage=20manager=20reads/wr=E2=80=A6?= =?UTF-8?q?"=20(#14465)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 1794187c266838e230a04e70909a9f331342b4e7. --- libraries/vidazooUtils/bidderUtils.js | 6 +++--- modules/sirdataRtdProvider.js | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/vidazooUtils/bidderUtils.js b/libraries/vidazooUtils/bidderUtils.js index 60934c0ed88..98da155ed10 100644 --- a/libraries/vidazooUtils/bidderUtils.js +++ b/libraries/vidazooUtils/bidderUtils.js @@ -64,7 +64,7 @@ export function setStorageItem(storage, key, value, timestamp) { export function getStorageItem(storage, key) { try { - return tryParseJSON(storage.getDataFromLocalStorage(key)); + return tryParseJSON(storage.getDataFromLocalStorage(key, null)); } catch (e) { } @@ -72,10 +72,10 @@ export function getStorageItem(storage, key) { } export function getCacheOpt(storage, useKey) { - let data = storage.getDataFromLocalStorage(useKey); + let data = storage.getDataFromLocalStorage(useKey, null); if (!data) { data = String(Date.now()); - storage.setDataInLocalStorage(useKey, data); + storage.setDataInLocalStorage(useKey, data, null); } return data; diff --git a/modules/sirdataRtdProvider.js b/modules/sirdataRtdProvider.js index 9115c7dc542..77c6f939a95 100644 --- a/modules/sirdataRtdProvider.js +++ b/modules/sirdataRtdProvider.js @@ -107,7 +107,7 @@ export function setCookieOnTopDomain(key, value, hostname, deleteCookie) { try { STORAGE.setCookie(key, value, expTime.toUTCString(), 'Lax', '.' + domain); // Try to read the cookie to check if we wrote it - if (STORAGE.getCookie(key) === value) return true; // Check if the cookie was set, and if so top domain was found. If deletion with expire date -1 will parse until complete host + if (STORAGE.getCookie(key, null) === value) return true; // Check if the cookie was set, and if so top domain was found. If deletion with expire date -1 will parse until complete host } catch (e) { logError(LOG_PREFIX, e); } @@ -120,10 +120,10 @@ export function setCookieOnTopDomain(key, value, hostname, deleteCookie) { * @returns {Array|null} - Array of UID objects or null if no UID found */ export function getUidFromStorage() { - let cUid = STORAGE.getCookie(EUIDS_STORAGE_NAME); - const lsUid = STORAGE.getDataFromLocalStorage(EUIDS_STORAGE_NAME); + let cUid = STORAGE.getCookie(EUIDS_STORAGE_NAME, null); + const lsUid = STORAGE.getDataFromLocalStorage(EUIDS_STORAGE_NAME, null); if (cUid && (!lsUid || cUid !== lsUid)) { - STORAGE.setDataInLocalStorage(EUIDS_STORAGE_NAME, cUid); + STORAGE.setDataInLocalStorage(EUIDS_STORAGE_NAME, cUid, null); } else if (lsUid && !cUid) { setCookieOnTopDomain(EUIDS_STORAGE_NAME, lsUid, cookieDomain, false); cUid = lsUid; @@ -140,7 +140,7 @@ export function setUidInStorage(sddanId) { if (!sddanId) return false; sddanId = encodeURI(sddanId.toString()); setCookieOnTopDomain(EUIDS_STORAGE_NAME, sddanId, cookieDomain, false); - STORAGE.setDataInLocalStorage(EUIDS_STORAGE_NAME, sddanId); + STORAGE.setDataInLocalStorage(EUIDS_STORAGE_NAME, sddanId, null); return true; } From 46c23dfe2953c73a210da3785ad04cd1641b41c1 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 18 Feb 2026 11:00:02 -0500 Subject: [PATCH 24/48] Prebid 11: remove superfluous addAdUnits and seat_non_bid event emission (#14466) * Core: remove addAdUnits event emission * Core: remove analytics subscriptions for addAdUnits * Core: remove addAdUnits event constant * Core: remove seatNonBid event constant * 33across Analytics Adapter: handle seatnonbid via pbsAnalytics (#14471) * Update 33acrossAnalyticsAdapter.js * Update 33acrossAnalyticsAdapter_spec.js --- modules/33acrossAnalyticsAdapter.js | 3 +-- modules/AsteriobidPbmAnalyticsAdapter.js | 3 --- modules/asteriobidAnalyticsAdapter.js | 3 --- modules/growthCodeAnalyticsAdapter.js | 5 ---- modules/hadronAnalyticsAdapter.js | 5 ---- modules/invisiblyAnalyticsAdapter.js | 5 ---- modules/prebidServerBidAdapter/index.ts | 10 -------- src/auction.ts | 4 ++-- src/constants.ts | 2 -- src/prebid.ts | 11 +-------- test/spec/auctionmanager_spec.js | 2 +- .../growthCodeAnalyticsAdapter_spec.js | 1 - .../modules/hadronAnalyticsAdapter_spec.js | 2 +- .../modules/invisiblyAnalyticsAdapter_spec.js | 24 ------------------- .../modules/magniteAnalyticsAdapter_spec.js | 5 ++-- .../modules/prebidServerBidAdapter_spec.js | 19 +-------------- 16 files changed, 9 insertions(+), 95 deletions(-) diff --git a/modules/33acrossAnalyticsAdapter.js b/modules/33acrossAnalyticsAdapter.js index ad9b33d6762..6ee02b09d8c 100644 --- a/modules/33acrossAnalyticsAdapter.js +++ b/modules/33acrossAnalyticsAdapter.js @@ -401,8 +401,7 @@ function analyticEventHandler({ eventType, args }) { case EVENTS.BID_REJECTED: onBidRejected(args); break; - case EVENTS.NO_BID: - case EVENTS.SEAT_NON_BID: + case EVENTS.NO_BID: // todo: need to also consider pbsanalytics where nonbid is not null setCachedBidStatus(args.auctionId, args.bidId, BidStatus.NOBID); break; case EVENTS.BIDDER_ERROR: diff --git a/modules/AsteriobidPbmAnalyticsAdapter.js b/modules/AsteriobidPbmAnalyticsAdapter.js index 3783f6c3765..2a914824a94 100644 --- a/modules/AsteriobidPbmAnalyticsAdapter.js +++ b/modules/AsteriobidPbmAnalyticsAdapter.js @@ -231,9 +231,6 @@ function handleEvent(eventType, eventArgs) { case EVENTS.REQUEST_BIDS: { break; } - case EVENTS.ADD_AD_UNITS: { - break; - } case EVENTS.AD_RENDER_FAILED: { pmEvent.bid = eventArgs.bid; pmEvent.message = eventArgs.message; diff --git a/modules/asteriobidAnalyticsAdapter.js b/modules/asteriobidAnalyticsAdapter.js index e4f7ee2a767..83c994f5f77 100644 --- a/modules/asteriobidAnalyticsAdapter.js +++ b/modules/asteriobidAnalyticsAdapter.js @@ -229,9 +229,6 @@ function handleEvent(eventType, eventArgs) { case EVENTS.REQUEST_BIDS: { break } - case EVENTS.ADD_AD_UNITS: { - break - } case EVENTS.AD_RENDER_FAILED: { pmEvent.bid = eventArgs.bid pmEvent.message = eventArgs.message diff --git a/modules/growthCodeAnalyticsAdapter.js b/modules/growthCodeAnalyticsAdapter.js index 5c936767cdf..3677408db0e 100644 --- a/modules/growthCodeAnalyticsAdapter.js +++ b/modules/growthCodeAnalyticsAdapter.js @@ -93,11 +93,6 @@ const growthCodeAnalyticsAdapter = Object.assign(adapter({url: url, analyticsTyp break; } - case EVENTS.ADD_AD_UNITS: { - data = eventData; - break; - } - case EVENTS.NO_BID: { data = eventData break; diff --git a/modules/hadronAnalyticsAdapter.js b/modules/hadronAnalyticsAdapter.js index c01e33bc6a2..db6909b2036 100644 --- a/modules/hadronAnalyticsAdapter.js +++ b/modules/hadronAnalyticsAdapter.js @@ -111,11 +111,6 @@ const hadronAnalyticsAdapter = Object.assign(adapter({url: HADRON_ANALYTICS_URL, break; } - case EVENTS.ADD_AD_UNITS: { - data = args; - break; - } - case EVENTS.AD_RENDER_FAILED: { data = args; break; diff --git a/modules/invisiblyAnalyticsAdapter.js b/modules/invisiblyAnalyticsAdapter.js index d6b5fc3efef..e835df6ce47 100644 --- a/modules/invisiblyAnalyticsAdapter.js +++ b/modules/invisiblyAnalyticsAdapter.js @@ -27,7 +27,6 @@ const { BIDDER_DONE, SET_TARGETING, REQUEST_BIDS, - ADD_AD_UNITS, AD_RENDER_FAILED, } = EVENTS; @@ -187,10 +186,6 @@ function handleEvent(eventType, eventArgs) { invisiblyEvent = eventArgs; break; } - case ADD_AD_UNITS: { - invisiblyEvent = eventArgs; - break; - } case AD_RENDER_FAILED: { invisiblyEvent = eventArgs; break; diff --git a/modules/prebidServerBidAdapter/index.ts b/modules/prebidServerBidAdapter/index.ts index e518a16e258..e2dcaf8bd28 100644 --- a/modules/prebidServerBidAdapter/index.ts +++ b/modules/prebidServerBidAdapter/index.ts @@ -459,7 +459,6 @@ export type PbsAnalytics = SeatNonBid & { declare module '../../src/events' { interface Events { - [EVENTS.SEAT_NON_BID]: [SeatNonBid]; [EVENTS.PBS_ANALYTICS]: [PbsAnalytics]; [EVENTS.BEFORE_PBS_HTTP]: [PbsRequestData]; } @@ -497,15 +496,6 @@ export function PrebidServer() { bidRequests.forEach(bidderRequest => events.emit(EVENTS.BIDDER_DONE, bidderRequest)); } const { seatNonBidData, atagData } = getAnalyticsFlags(s2sBidRequest.s2sConfig, response) - if (seatNonBidData) { - events.emit(EVENTS.SEAT_NON_BID, { - seatnonbid: response.ext.seatnonbid, - auctionId: bidRequests[0].auctionId, - requestedBidders, - response, - adapterMetrics - }); - } // pbs analytics event if (seatNonBidData || atagData) { const data: PbsAnalytics = { diff --git a/src/auction.ts b/src/auction.ts index 5f2a1ad63c0..dff01d6421b 100644 --- a/src/auction.ts +++ b/src/auction.ts @@ -424,8 +424,8 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, a adapterManager.callSetTargetingBidder(bid.adapterCode || bid.bidder, bid); } - events.on(EVENTS.SEAT_NON_BID, (event) => { - if (event.auctionId === _auctionId) { + events.on(EVENTS.PBS_ANALYTICS, (event) => { + if (event.auctionId === _auctionId && event.seatnonbid != null) { addNonBids(event.seatnonbid) } }); diff --git a/src/constants.ts b/src/constants.ts index b9525e51e3a..5c4c0a6f00f 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -25,7 +25,6 @@ export const EVENTS = { BID_RESPONSE: 'bidResponse', BID_REJECTED: 'bidRejected', NO_BID: 'noBid', - SEAT_NON_BID: 'seatNonBid', BID_WON: 'bidWon', BIDDER_DONE: 'bidderDone', BIDDER_ERROR: 'bidderError', @@ -33,7 +32,6 @@ export const EVENTS = { BEFORE_REQUEST_BIDS: 'beforeRequestBids', BEFORE_BIDDER_HTTP: 'beforeBidderHttp', REQUEST_BIDS: 'requestBids', - ADD_AD_UNITS: 'addAdUnits', AD_RENDER_FAILED: 'adRenderFailed', AD_RENDER_SUCCEEDED: 'adRenderSucceeded', TCF2_ENFORCEMENT: 'tcf2Enforcement', diff --git a/src/prebid.ts b/src/prebid.ts index 34d6208970a..e662a0e178c 100644 --- a/src/prebid.ts +++ b/src/prebid.ts @@ -70,7 +70,7 @@ const pbjsInstance = getGlobal(); const { triggerUserSyncs } = userSync; /* private variables */ -const { ADD_AD_UNITS, REQUEST_BIDS, SET_TARGETING } = EVENTS; +const { REQUEST_BIDS, SET_TARGETING } = EVENTS; // initialize existing debugging sessions if present loadSession(); @@ -954,21 +954,12 @@ export function executeCallbacks(fn, reqBidsConfigObj) { // This hook will execute all storage callbacks which were registered before gdpr enforcement hook was added. Some bidders, user id modules use storage functions when module is parsed but gdpr enforcement hook is not added at that stage as setConfig callbacks are yet to be called. Hence for such calls we execute all the stored callbacks just before requestBids. At this hook point we will know for sure that tcfControl module is added or not requestBids.before(executeCallbacks, 49); -declare module './events' { - interface Events { - /** - * Fired when `.addAdUniuts` is called. - */ - [ADD_AD_UNITS]: []; - } -} /** * Add ad unit(s) * @param adUnits */ function addAdUnits(adUnits: AdUnitDefinition | AdUnitDefinition[]) { pbjsInstance.adUnits.push(...(Array.isArray(adUnits) ? adUnits : [adUnits])) - events.emit(ADD_AD_UNITS); } addApiMethod('addAdUnits', addAdUnits); diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 6ebb8666096..b3a10ede626 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -836,7 +836,7 @@ describe('auctionmanager.js', function () { } const auction = auctionManager.createAuction({adUnits, ortb2Fragments}); expect(auction.getNonBids()[0]).to.equal(undefined); - events.emit(EVENTS.SEAT_NON_BID, { + events.emit(EVENTS.PBS_ANALYTICS, { auctionId: auction.getAuctionId(), seatnonbid: ['test'] }); diff --git a/test/spec/modules/growthCodeAnalyticsAdapter_spec.js b/test/spec/modules/growthCodeAnalyticsAdapter_spec.js index 266bc104fd8..e871ec4c16d 100644 --- a/test/spec/modules/growthCodeAnalyticsAdapter_spec.js +++ b/test/spec/modules/growthCodeAnalyticsAdapter_spec.js @@ -22,7 +22,6 @@ describe('growthCode analytics adapter', () => { 'bidResponse', 'setTargeting', 'requestBids', - 'addAdUnits', 'noBid', 'bidWon', 'bidderDone'] diff --git a/test/spec/modules/hadronAnalyticsAdapter_spec.js b/test/spec/modules/hadronAnalyticsAdapter_spec.js index 68e5bc3aecb..ec1092fa441 100644 --- a/test/spec/modules/hadronAnalyticsAdapter_spec.js +++ b/test/spec/modules/hadronAnalyticsAdapter_spec.js @@ -12,7 +12,7 @@ describe('Hadron analytics adapter', () => { options: { partnerId: 12349, eventsToTrack: ['auctionInit', 'auctionEnd', 'bidWon', - 'bidderDone', 'requestBids', 'addAdUnits', 'setTargeting', 'adRenderFailed', + 'bidderDone', 'requestBids', 'setTargeting', 'adRenderFailed', 'bidResponse', 'bidTimeout', 'bidRequested', 'bidAdjustment', 'nonExistingEvent' ], } diff --git a/test/spec/modules/invisiblyAnalyticsAdapter_spec.js b/test/spec/modules/invisiblyAnalyticsAdapter_spec.js index 71182d146a0..76fda979811 100644 --- a/test/spec/modules/invisiblyAnalyticsAdapter_spec.js +++ b/test/spec/modules/invisiblyAnalyticsAdapter_spec.js @@ -161,7 +161,6 @@ describe('Invisibly Analytics Adapter test suite', function () { REQUEST_BIDS: { call: 'request', }, - ADD_AD_UNITS: { call: 'addAdUnits' }, AD_RENDER_FAILED: { call: 'adRenderFailed' }, INVALID_EVENT: { mockKey: 'this event should not emit', @@ -447,28 +446,6 @@ describe('Invisibly Analytics Adapter test suite', function () { sinon.assert.callCount(invisiblyAdapter.track, 1); }); - // spec for add ad units event - it('add ad units event', function () { - invisiblyAdapter.enableAnalytics(MOCK.config); - events.emit(EVENTS.ADD_AD_UNITS, MOCK.ADD_AD_UNITS); - invisiblyAdapter.flush(); - - const invisiblyEvents = JSON.parse( - requests[0].requestBody.substring(0) - ); - expect(requests.length).to.equal(1); - expect(requests[0].url).to.equal( - 'https://api.pymx5.com/v1/sites/events' - ); - expect(invisiblyEvents.event_data.pageViewId).to.exist; - expect(invisiblyEvents.event_data.ver).to.equal(1); - expect(invisiblyEvents.event_type).to.equal('PREBID_addAdUnits'); - expect(invisiblyEvents.event_data.call).to.equal( - MOCK.ADD_AD_UNITS.call - ); - sinon.assert.callCount(invisiblyAdapter.track, 1); - }); - // spec for ad render failed event it('ad render failed event', function () { invisiblyAdapter.enableAnalytics(MOCK.config); @@ -540,7 +517,6 @@ describe('Invisibly Analytics Adapter test suite', function () { EVENTS.BIDDER_DONE, EVENTS.SET_TARGETING, EVENTS.REQUEST_BIDS, - EVENTS.ADD_AD_UNITS, EVENTS.AD_RENDER_FAILED ]).to.beTrackedBy(invisiblyAdapter.track); }); diff --git a/test/spec/modules/magniteAnalyticsAdapter_spec.js b/test/spec/modules/magniteAnalyticsAdapter_spec.js index 83a5b83f774..6c293a3bb44 100644 --- a/test/spec/modules/magniteAnalyticsAdapter_spec.js +++ b/test/spec/modules/magniteAnalyticsAdapter_spec.js @@ -25,7 +25,6 @@ const { BID_WON, BID_TIMEOUT, BILLABLE_EVENT, - SEAT_NON_BID, PBS_ANALYTICS, BID_REJECTED } = EVENTS; @@ -169,7 +168,7 @@ const MOCK = { getStatusCode: () => 1, metrics }, - SEAT_NON_BID: { + PBS_ANALYTICS: { auctionId: '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d', seatnonbid: [{ seat: 'rubicon', @@ -2359,7 +2358,7 @@ describe('magnite analytics adapter', function () { accountId: 1001 } }); - seatnonbid = utils.deepClone(MOCK.SEAT_NON_BID); + seatnonbid = utils.deepClone(MOCK.PBS_ANALYTICS); }); it('adds seatnonbid info to bids array', () => { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index a6deca70a57..025ac9592b2 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -3311,23 +3311,6 @@ describe('S2S Adapter', function () { expect(response).to.have.property('ttl', 60); }); - it('handles seatnonbid responses and emits SEAT_NON_BID', function () { - const original = CONFIG; - CONFIG.extPrebid = { returnallbidstatus: true }; - const nonbidResponse = {...RESPONSE_OPENRTB, ext: {seatnonbid: [{}]}}; - config.setConfig({ CONFIG }); - CONFIG = original; - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); - const responding = deepClone(nonbidResponse); - Object.assign(responding.ext.seatnonbid, [{auctionId: 2}]) - server.requests[0].respond(200, {}, JSON.stringify(responding)); - const event = events.emit.thirdCall.args; - expect(event[0]).to.equal(EVENTS.SEAT_NON_BID); - expect(event[1].seatnonbid[0]).to.have.property('auctionId', 2); - expect(event[1].requestedBidders).to.deep.equal(['appnexus']); - expect(event[1].response).to.deep.equal(responding); - }); - it('emits the PBS_ANALYTICS event and captures seatnonbid responses', function () { const original = CONFIG; CONFIG.extPrebid = { returnallbidstatus: true }; @@ -3338,7 +3321,7 @@ describe('S2S Adapter', function () { const responding = deepClone(nonbidResponse); Object.assign(responding.ext.seatnonbid, [{auctionId: 2}]) server.requests[0].respond(200, {}, JSON.stringify(responding)); - const event = events.emit.getCall(3).args; + const event = events.emit.getCall(2).args; expect(event[0]).to.equal(EVENTS.PBS_ANALYTICS); expect(event[1].seatnonbid[0]).to.have.property('auctionId', 2); expect(event[1].requestedBidders).to.deep.equal(['appnexus']); From 23b196b58401574dbf8ac8b68921f37458494b77 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Thu, 19 Feb 2026 11:57:20 -0500 Subject: [PATCH 25/48] Prebid 11: remove deprecated DNT/DoNotTrack usage and force static dnt handling (#14448) * Fix data formatting in gmosspBidAdapter tests * Remove DNT signal handling from bid request Removed deprecated DNT signal handling from request. * Update video startdelay, skip, and bidfloor values * Update viewability checks to expect 0 instead of null * Update video startdelay and skip expectations * Update bidfloor and no bid response expectations * Remove dnt test case from rhythmoneBidAdapter_spec Removed test case for 'dnt is correctly set to 1' in rhythmoneBidAdapter_spec.js. * Update video startdelay and skip expectations * Update mileBidAdapter.ts * OpenX Adapter: restore getDNT usage for dnt field (#14472) * Core: restore getDNT payload mapping across adapters (#14474) * Update displayioBidAdapter.js * Update mediakeysBidAdapter.js * Update openxBidAdapter.js * Update yahooAdsBidAdapter.js * Update yieldmoBidAdapter.js * Update yieldmoBidAdapter_spec.js * Update enrichment.ts * Update openxBidAdapter.js * Update trafficgateBidAdapter_spec.js * Update trafficgateBidAdapter_spec.js * Update trafficgateBidAdapter_spec.js * Update trafficgateBidAdapter.js * Update trafficgateBidAdapter.js * Do not add DNT to adapters that don't care about it * linter --------- Co-authored-by: Demetrio Girardi --- eslint.config.js | 15 + libraries/advangUtils/index.js | 10 +- libraries/dnt/index.js | 16 +- libraries/riseUtils/index.js | 2 +- modules/adkernelBidAdapter.js | 6 +- modules/adtrgtmeBidAdapter.js | 3 +- modules/adtrueBidAdapter.js | 2 +- modules/alkimiBidAdapter.js | 2 +- modules/apacdexBidAdapter.js | 2 +- modules/apstreamBidAdapter.js | 2 +- modules/axonixBidAdapter.js | 2 +- modules/beachfrontBidAdapter.js | 7 +- modules/bmtmBidAdapter.js | 2 +- modules/cadent_aperture_mxBidAdapter.js | 2 +- modules/chtnwBidAdapter.js | 2 +- modules/cointrafficBidAdapter.js | 2 +- modules/connectadBidAdapter.js | 2 +- modules/deepintentBidAdapter.js | 2 +- modules/digitalMatterBidAdapter.js | 2 +- modules/distroscaleBidAdapter.js | 2 +- modules/empowerBidAdapter.js | 520 +++++++++--------- modules/gmosspBidAdapter.js | 3 - modules/gumgumBidAdapter.js | 3 +- modules/impactifyBidAdapter.js | 2 +- modules/jixieBidAdapter.js | 2 +- modules/jwplayerBidAdapter.js | 2 +- modules/lemmaDigitalBidAdapter.js | 2 +- modules/lkqdBidAdapter.js | 5 - modules/marsmediaBidAdapter.js | 2 +- modules/mediaforceBidAdapter.js | 2 +- modules/mediakeysBidAdapter.js | 2 +- modules/mgidBidAdapter.js | 2 +- modules/mileBidAdapter.ts | 2 +- modules/nexverseBidAdapter.js | 2 +- modules/openxBidAdapter.js | 4 +- modules/operaadsBidAdapter.js | 2 +- modules/panxoBidAdapter.js | 3 +- modules/pwbidBidAdapter.js | 2 +- modules/rhythmoneBidAdapter.js | 2 +- modules/scaliburBidAdapter.js | 3 +- modules/sharethroughBidAdapter.js | 2 +- modules/smaatoBidAdapter.js | 2 +- modules/smartxBidAdapter.js | 2 +- modules/snigelBidAdapter.js | 2 +- modules/tappxBidAdapter.js | 2 +- modules/theAdxBidAdapter.js | 2 +- modules/ttdBidAdapter.js | 2 +- modules/ucfunnelBidAdapter.js | 2 +- modules/yieldmoBidAdapter.js | 2 +- src/fpd/enrichment.ts | 2 - test/spec/libraries/dnt_spec.js | 34 -- test/spec/modules/adkernelBidAdapter_spec.js | 11 +- test/spec/modules/adtrgtmeBidAdapter_spec.js | 2 +- test/spec/modules/gmosspBidAdapter_spec.js | 4 +- test/spec/modules/marsmediaBidAdapter_spec.js | 10 +- .../spec/modules/mediaforceBidAdapter_spec.js | 3 +- test/spec/modules/mgidBidAdapter_spec.js | 3 +- test/spec/modules/openxBidAdapter_spec.js | 28 +- test/spec/modules/rhythmoneBidAdapter_spec.js | 32 -- .../modules/trafficgateBidAdapter_spec.js | 32 -- test/spec/modules/valuadBidAdapter_spec.js | 2 - 61 files changed, 341 insertions(+), 492 deletions(-) delete mode 100644 test/spec/libraries/dnt_spec.js diff --git a/eslint.config.js b/eslint.config.js index 46d0eb86da4..2d14584063a 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -209,6 +209,21 @@ module.exports = [ object: 'navigator', message: 'use ajax.js instead' }, + { + property: 'doNotTrack', + object: 'navigator', + message: 'DNT was deprecated by W3C; Prebid no longer supports DNT signals' + }, + { + property: 'msDoNotTrack', + object: 'navigator', + message: 'DNT was deprecated by W3C; Prebid no longer supports DNT signals' + }, + { + property: 'doNotTrack', + object: 'window', + message: 'DNT was deprecated by W3C; Prebid no longer supports DNT signals' + }, ...['outerText', 'innerText'].map(property => ({ property, message: 'use .textContent instead' diff --git a/libraries/advangUtils/index.js b/libraries/advangUtils/index.js index 7d869cef9e1..18c8aead27a 100644 --- a/libraries/advangUtils/index.js +++ b/libraries/advangUtils/index.js @@ -1,6 +1,6 @@ import { generateUUID, isFn, parseSizesInput, parseUrl } from '../../src/utils.js'; -import { getDNT as getNavigatorDNT } from '../dnt/index.js'; import { config } from '../../src/config.js'; +import {getDNT} from '../dnt/index.js'; export const DEFAULT_MIMES = ['video/mp4', 'application/javascript']; @@ -46,10 +46,6 @@ export function isConnectedTV() { return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent); } -export function getDoNotTrack(win = typeof window !== 'undefined' ? window : undefined) { - return getNavigatorDNT(win); -} - export function findAndFillParam(o, key, value) { try { if (typeof value === 'function') { @@ -145,7 +141,7 @@ export function createRequestData(bid, bidderRequest, isVideo, getBidParam, getS const o = { 'device': { 'langauge': (global.navigator.language).split('-')[0], - 'dnt': getDoNotTrack(global) ? 1 : 0, + 'dnt': getDNT() ? 1 : 0, 'devicetype': isMobile() ? 4 : isConnectedTV() ? 3 : 2, 'js': 1, 'os': getOsVersion() @@ -170,7 +166,7 @@ export function createRequestData(bid, bidderRequest, isVideo, getBidParam, getS o.site['ref'] = topReferrer; o.site['mobile'] = isMobile() ? 1 : 0; const secure = topLocation.protocol.indexOf('https') === 0 ? 1 : 0; - o.device['dnt'] = getDoNotTrack(global) ? 1 : 0; + o.device['dnt'] = getDNT() ? 1 : 0; findAndFillParam(o.site, 'name', function() { return global.top.document.title; diff --git a/libraries/dnt/index.js b/libraries/dnt/index.js index 1b03e848ca5..66aad467115 100644 --- a/libraries/dnt/index.js +++ b/libraries/dnt/index.js @@ -1,11 +1,7 @@ -function _getDNT(win) { - return win.navigator.doNotTrack === '1' || win.doNotTrack === '1' || win.navigator.msDoNotTrack === '1' || win.navigator.doNotTrack?.toLowerCase?.() === 'yes'; -} - -export function getDNT(win = window) { - try { - return _getDNT(win) || (win !== win.top && _getDNT(win.top)); - } catch (e) { - return false; - } +/** + * DNT was deprecated by W3C; Prebid no longer supports DNT signals. + * Keep this helper for backwards compatibility with adapters that still invoke getDNT(). + */ +export function getDNT() { + return false; } diff --git a/libraries/riseUtils/index.js b/libraries/riseUtils/index.js index 77ca87f0fca..aefba4b2014 100644 --- a/libraries/riseUtils/index.js +++ b/libraries/riseUtils/index.js @@ -12,10 +12,10 @@ import { } from '../../src/utils.js'; import {BANNER, NATIVE, VIDEO} from '../../src/mediaTypes.js'; import {config} from '../../src/config.js'; -import { getDNT } from '../dnt/index.js'; import {ADAPTER_VERSION, DEFAULT_CURRENCY, DEFAULT_TTL, SUPPORTED_AD_TYPES} from './constants.js'; import {getGlobalVarName} from '../../src/buildOptions.js'; +import {getDNT} from '../dnt/index.js'; export const makeBaseSpec = (baseUrl, modes) => { return { diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 81fa3501ea0..9092946d3c1 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { _each, contains, @@ -20,7 +19,7 @@ import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; import {getAdUnitSizes} from '../libraries/sizeUtils/sizeUtils.js'; -import {getBidFloor} from '../libraries/adkernelUtils/adkernelUtils.js' +import {getBidFloor} from '../libraries/adkernelUtils/adkernelUtils.js'; /** * In case you're AdKernel whitelable platform's client who needs branded adapter to @@ -416,9 +415,6 @@ function makeDevice(fpd) { 'js': 1, 'language': getLanguage() }, fpd.device || {}); - if (getDNT()) { - device.dnt = 1; - } return {device: device}; } diff --git a/modules/adtrgtmeBidAdapter.js b/modules/adtrgtmeBidAdapter.js index dc15dd2dc9f..5e2319b85df 100644 --- a/modules/adtrgtmeBidAdapter.js +++ b/modules/adtrgtmeBidAdapter.js @@ -11,6 +11,7 @@ import { } from '../src/utils.js'; import { config } from '../src/config.js'; import { hasPurpose1Consent } from '../src/utils/gdpr.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'adtrgtme'; const BIDDER_VERSION = '1.0.7'; @@ -71,7 +72,7 @@ function createORTB(bR, bid) { ...site, }, device: { - dnt: bid?.params?.dnt ? 1 : 0, + dnt: getDNT() ? 1 : 0, ua: bid?.params?.ua || navigator.userAgent, ip, }, diff --git a/modules/adtrueBidAdapter.js b/modules/adtrueBidAdapter.js index 2c4278b9fb8..d503f112d26 100644 --- a/modules/adtrueBidAdapter.js +++ b/modules/adtrueBidAdapter.js @@ -1,10 +1,10 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { logWarn, isArray, inIframe, isNumber, isStr, deepClone, deepSetValue, logError, deepAccess, isBoolean } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; import {getStorageManager} from '../src/storageManager.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'adtrue'; const storage = getStorageManager({bidderCode: BIDDER_CODE}); diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index 8e77e2507b7..8d923d26713 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -1,10 +1,10 @@ -import {getDNT} from '../libraries/dnt/index.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {deepAccess, deepClone, generateUUID, replaceAuctionPrice} from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import {getStorageManager} from '../src/storageManager.js'; import {VIDEO, BANNER} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'alkimi'; const GVLID = 1169; diff --git a/modules/apacdexBidAdapter.js b/modules/apacdexBidAdapter.js index cd433ef2c81..0e669a8fdbc 100644 --- a/modules/apacdexBidAdapter.js +++ b/modules/apacdexBidAdapter.js @@ -1,9 +1,9 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { deepAccess, isPlainObject, isArray, replaceAuctionPrice, isFn, logError, deepClone } from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import {hasPurpose1Consent} from '../src/utils/gdpr.js'; import {parseDomain} from '../src/refererDetection.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'apacdex'; const ENDPOINT = 'https://useast.quantumdex.io/auction/pbjs' const USERSYNC = 'https://sync.quantumdex.io/usersync/pbjs' diff --git a/modules/apstreamBidAdapter.js b/modules/apstreamBidAdapter.js index f432c85388f..64c91f60ab0 100644 --- a/modules/apstreamBidAdapter.js +++ b/modules/apstreamBidAdapter.js @@ -1,10 +1,10 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { generateUUID, deepAccess, createTrackPixelHtml } from '../src/utils.js'; import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRatio.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {getDNT} from '../libraries/dnt/index.js'; const CONSTANTS = { DSU_KEY: 'apr_dsu', diff --git a/modules/axonixBidAdapter.js b/modules/axonixBidAdapter.js index c0b3f334c40..e2177da2f4e 100644 --- a/modules/axonixBidAdapter.js +++ b/modules/axonixBidAdapter.js @@ -1,10 +1,10 @@ -import {getDNT} from '../libraries/dnt/index.js'; import {deepAccess, isArray, isEmpty, logError, replaceAuctionPrice, triggerPixel} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; import {ajax} from '../src/ajax.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'axonix'; const BIDDER_VERSION = '1.0.2'; diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index 3f627fe39e0..e6e8074df76 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -10,8 +10,9 @@ import { import {registerBidder} from '../src/adapters/bidderFactory.js'; import {Renderer} from '../src/Renderer.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import { getFirstSize, getOsVersion, getVideoSizes, getBannerSizes, isConnectedTV, getDoNotTrack, isMobile, isBannerBid, isVideoBid, getBannerBidFloor, getVideoBidFloor, getVideoTargetingParams, getTopWindowLocation } from '../libraries/advangUtils/index.js'; +import { getFirstSize, getOsVersion, getVideoSizes, getBannerSizes, isConnectedTV, isMobile, isBannerBid, isVideoBid, getBannerBidFloor, getVideoBidFloor, getVideoTargetingParams, getTopWindowLocation } from '../libraries/advangUtils/index.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; +import {getDNT} from '../libraries/dnt/index.js'; const ADAPTER_VERSION = '1.21'; const GVLID = 157; @@ -305,7 +306,7 @@ function createVideoRequestData(bid, bidderRequest) { ua: navigator.userAgent, language: navigator.language, devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2, - dnt: getDoNotTrack() ? 1 : 0, + dnt: getDNT() ? 1 : 0, js: 1, geo: {} }, @@ -371,7 +372,7 @@ function createBannerRequestData(bids, bidderRequest) { ua: navigator.userAgent, deviceOs: getOsVersion(), isMobile: isMobile() ? 1 : 0, - dnt: getDoNotTrack() ? 1 : 0, + dnt: getDNT() ? 1 : 0, adapterVersion: ADAPTER_VERSION, adapterName: ADAPTER_NAME }; diff --git a/modules/bmtmBidAdapter.js b/modules/bmtmBidAdapter.js index bc6a4415f97..a5af67e7512 100644 --- a/modules/bmtmBidAdapter.js +++ b/modules/bmtmBidAdapter.js @@ -1,8 +1,8 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { generateUUID, deepAccess, logWarn, deepSetValue, isPlainObject } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'bmtm'; const AD_URL = 'https://one.elitebidder.com/api/hb?sid='; diff --git a/modules/cadent_aperture_mxBidAdapter.js b/modules/cadent_aperture_mxBidAdapter.js index f13bda26102..4a16444553b 100644 --- a/modules/cadent_aperture_mxBidAdapter.js +++ b/modules/cadent_aperture_mxBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { _each, deepAccess, getBidIdParameter, @@ -13,6 +12,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {Renderer} from '../src/Renderer.js'; import {parseDomain} from '../src/refererDetection.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'cadent_aperture_mx'; const ENDPOINT = 'hb.emxdgt.com'; diff --git a/modules/chtnwBidAdapter.js b/modules/chtnwBidAdapter.js index 3aea0016679..4c904e79596 100644 --- a/modules/chtnwBidAdapter.js +++ b/modules/chtnwBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { generateUUID, _each, @@ -10,6 +9,7 @@ import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { getStorageManager } from '../src/storageManager.js'; import { ajax } from '../src/ajax.js'; import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js'; +import {getDNT} from '../libraries/dnt/index.js'; const ENDPOINT_URL = 'https://prebid.cht.hinet.net/api/v1'; const BIDDER_CODE = 'chtnw'; const COOKIE_NAME = '__htid'; diff --git a/modules/cointrafficBidAdapter.js b/modules/cointrafficBidAdapter.js index d9394253497..60a3ffdf7da 100644 --- a/modules/cointrafficBidAdapter.js +++ b/modules/cointrafficBidAdapter.js @@ -4,7 +4,7 @@ import { BANNER } from '../src/mediaTypes.js' import { config } from '../src/config.js' import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js'; import { getViewportSize } from '../libraries/viewport/viewport.js' -import { getDNT } from '../libraries/dnt/index.js' +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/connectadBidAdapter.js b/modules/connectadBidAdapter.js index 464499b5f7d..459c27ea756 100644 --- a/modules/connectadBidAdapter.js +++ b/modules/connectadBidAdapter.js @@ -1,9 +1,9 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { deepAccess, deepSetValue, mergeDeep, logWarn, generateUUID } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js' import {config} from '../src/config.js'; import {tryAppendQueryString} from '../libraries/urlUtils/urlUtils.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'connectad'; const BIDDER_CODE_ALIAS = 'connectadrealtime'; diff --git a/modules/deepintentBidAdapter.js b/modules/deepintentBidAdapter.js index c5acc942218..eabcc036cca 100644 --- a/modules/deepintentBidAdapter.js +++ b/modules/deepintentBidAdapter.js @@ -1,9 +1,9 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { generateUUID, deepSetValue, deepAccess, isArray, isFn, isPlainObject, logError, logWarn } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { COMMON_ORTB_VIDEO_PARAMS, formatResponse } from '../libraries/deepintentUtils/index.js'; import { addDealCustomTargetings, addPMPDeals } from '../libraries/dealUtils/dealUtils.js'; +import {getDNT} from '../libraries/dnt/index.js'; const LOG_WARN_PREFIX = 'DeepIntent: '; const BIDDER_CODE = 'deepintent'; diff --git a/modules/digitalMatterBidAdapter.js b/modules/digitalMatterBidAdapter.js index 37c01e6a9d9..c0f972d9a3b 100644 --- a/modules/digitalMatterBidAdapter.js +++ b/modules/digitalMatterBidAdapter.js @@ -1,9 +1,9 @@ -import {getDNT} from '../libraries/dnt/index.js'; import {deepAccess, deepSetValue, getWinDimensions, inIframe, logWarn, parseSizesInput} from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER} from '../src/mediaTypes.js'; import {hasPurpose1Consent} from '../src/utils/gdpr.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'digitalMatter'; const GVLID = 1345; diff --git a/modules/distroscaleBidAdapter.js b/modules/distroscaleBidAdapter.js index 4737c8bf969..cb7f5636fbd 100644 --- a/modules/distroscaleBidAdapter.js +++ b/modules/distroscaleBidAdapter.js @@ -1,8 +1,8 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { logWarn, isPlainObject, isStr, isArray, isFn, inIframe, mergeDeep, deepSetValue, logError, deepClone } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER } from '../src/mediaTypes.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'distroscale'; const SHORT_CODE = 'ds'; const LOG_WARN_PREFIX = 'DistroScale: '; diff --git a/modules/empowerBidAdapter.js b/modules/empowerBidAdapter.js index 14e8be2a82d..fb8d7d2b620 100644 --- a/modules/empowerBidAdapter.js +++ b/modules/empowerBidAdapter.js @@ -1,262 +1,258 @@ -import { - deepAccess, - mergeDeep, - logError, - replaceMacros, - triggerPixel, - deepSetValue, - isStr, - isArray, - getWinDimensions, -} from "../src/utils.js"; -import { registerBidder } from "../src/adapters/bidderFactory.js"; -import { config } from "../src/config.js"; -import { VIDEO, BANNER } from "../src/mediaTypes.js"; -import { getConnectionType } from "../libraries/connectionInfo/connectionUtils.js"; - -export const ENDPOINT = "https://bid.virgul.com/prebid"; - -const BIDDER_CODE = "empower"; -const GVLID = 1248; - -export const spec = { - code: BIDDER_CODE, - gvlid: GVLID, - supportedMediaTypes: [VIDEO, BANNER], - - isBidRequestValid: (bid) => - !!(bid && bid.params && bid.params.zone && bid.bidder === BIDDER_CODE), - - buildRequests: (bidRequests, bidderRequest) => { - const currencyObj = config.getConfig("currency"); - const currency = (currencyObj && currencyObj.adServerCurrency) || "USD"; - - const request = { - id: bidRequests[0].bidderRequestId, - at: 1, - imp: bidRequests.map((slot) => impression(slot, currency)), - site: { - page: bidderRequest.refererInfo.page, - domain: bidderRequest.refererInfo.domain, - ref: bidderRequest.refererInfo.ref, - publisher: { domain: bidderRequest.refererInfo.domain }, - }, - device: { - ua: navigator.userAgent, - js: 1, - dnt: - navigator.doNotTrack === "yes" || - navigator.doNotTrack === "1" || - navigator.msDoNotTrack === "1" - ? 1 - : 0, - h: screen.height, - w: screen.width, - language: navigator.language, - connectiontype: getConnectionType(), - }, - cur: [currency], - source: { - fd: 1, - tid: bidderRequest.ortb2?.source?.tid, - ext: { - prebid: "$prebid.version$", - }, - }, - user: {}, - regs: {}, - ext: {}, - }; - - if (bidderRequest.gdprConsent) { - request.user = { - ext: { - consent: bidderRequest.gdprConsent.consentString || "", - }, - }; - request.regs = { - ext: { - gdpr: - bidderRequest.gdprConsent.gdprApplies !== undefined - ? bidderRequest.gdprConsent.gdprApplies - : true, - }, - }; - } - - if (bidderRequest.ortb2?.source?.ext?.schain) { - request.schain = bidderRequest.ortb2.source.ext.schain; - } - - let bidUserIdAsEids = deepAccess(bidRequests, "0.userIdAsEids"); - if (isArray(bidUserIdAsEids) && bidUserIdAsEids.length > 0) { - deepSetValue(request, "user.eids", bidUserIdAsEids); - } - - const commonFpd = bidderRequest.ortb2 || {}; - const { user, device, site, bcat, badv } = commonFpd; - if (site) { - mergeDeep(request, { site: site }); - } - if (user) { - mergeDeep(request, { user: user }); - } - if (badv) { - mergeDeep(request, { badv: badv }); - } - if (bcat) { - mergeDeep(request, { bcat: bcat }); - } - - if (user?.geo && device?.geo) { - request.device.geo = { ...request.device.geo, ...device.geo }; - request.user.geo = { ...request.user.geo, ...user.geo }; - } else { - if (user?.geo || device?.geo) { - request.user.geo = request.device.geo = user?.geo - ? { ...request.user.geo, ...user.geo } - : { ...request.user.geo, ...device.geo }; - } - } - - if (bidderRequest.ortb2?.device) { - mergeDeep(request.device, bidderRequest.ortb2.device); - } - - return { - method: "POST", - url: ENDPOINT, - data: JSON.stringify(request), - }; - }, - - interpretResponse: (bidResponse, bidRequest) => { - const idToImpMap = {}; - const idToBidMap = {}; - - if (!bidResponse["body"]) { - return []; - } - if (!bidRequest.data) { - return []; - } - const requestImps = parse(bidRequest.data); - if (!requestImps) { - return []; - } - requestImps.imp.forEach((imp) => { - idToImpMap[imp.id] = imp; - }); - bidResponse = bidResponse.body; - if (bidResponse) { - bidResponse.seatbid.forEach((seatBid) => - seatBid.bid.forEach((bid) => { - idToBidMap[bid.impid] = bid; - }) - ); - } - const bids = []; - Object.keys(idToImpMap).forEach((id) => { - const imp = idToImpMap[id]; - const result = idToBidMap[id]; - - if (result) { - const bid = { - requestId: id, - cpm: result.price, - creativeId: result.crid, - ttl: 300, - netRevenue: true, - mediaType: imp.video ? VIDEO : BANNER, - currency: bidResponse.cur, - }; - if (imp.video) { - bid.vastXml = result.adm; - } else if (imp.banner) { - bid.ad = result.adm; - } - bid.width = result.w; - bid.height = result.h; - if (result.burl) bid.burl = result.burl; - if (result.nurl) bid.nurl = result.nurl; - if (result.adomain) { - bid.meta = { - advertiserDomains: result.adomain, - }; - } - bids.push(bid); - } - }); - return bids; - }, - - onBidWon: (bid) => { - if (bid.nurl && isStr(bid.nurl)) { - bid.nurl = replaceMacros(bid.nurl, { - AUCTION_PRICE: bid.cpm, - AUCTION_CURRENCY: bid.cur, - }); - triggerPixel(bid.nurl); - } - }, -}; - -function impression(slot, currency) { - let bidFloorFromModule; - if (typeof slot.getFloor === "function") { - const floorInfo = slot.getFloor({ - currency: "USD", - mediaType: "*", - size: "*", - }); - bidFloorFromModule = - floorInfo?.currency === "USD" ? floorInfo?.floor : undefined; - } - const imp = { - id: slot.bidId, - bidfloor: bidFloorFromModule || slot.params.bidfloor || 0, - bidfloorcur: - (bidFloorFromModule && "USD") || - slot.params.bidfloorcur || - currency || - "USD", - tagid: "" + (slot.params.zone || ""), - }; - - if (slot.mediaTypes.banner) { - imp.banner = bannerImpression(slot); - } else if (slot.mediaTypes.video) { - imp.video = deepAccess(slot, "mediaTypes.video"); - } - imp.ext = slot.params || {}; - const { innerWidth, innerHeight } = getWinDimensions(); - imp.ext.ww = innerWidth || ""; - imp.ext.wh = innerHeight || ""; - return imp; -} - -function bannerImpression(slot) { - const sizes = slot.mediaTypes.banner.sizes || slot.sizes; - return { - format: sizes.map((s) => ({ w: s[0], h: s[1] })), - w: sizes[0][0], - h: sizes[0][1], - }; -} - -function parse(rawResponse) { - try { - if (rawResponse) { - if (typeof rawResponse === "object") { - return rawResponse; - } else { - return JSON.parse(rawResponse); - } - } - } catch (ex) { - logError("empowerBidAdapter", "ERROR", ex); - } - return null; -} - -registerBidder(spec); +import { + deepAccess, + mergeDeep, + logError, + replaceMacros, + triggerPixel, + deepSetValue, + isStr, + isArray, + getWinDimensions, +} from "../src/utils.js"; +import { registerBidder } from "../src/adapters/bidderFactory.js"; +import { config } from "../src/config.js"; +import { VIDEO, BANNER } from "../src/mediaTypes.js"; +import { getConnectionType } from "../libraries/connectionInfo/connectionUtils.js"; +import {getDNT} from "../libraries/dnt/index.js"; + +export const ENDPOINT = "https://bid.virgul.com/prebid"; + +const BIDDER_CODE = "empower"; +const GVLID = 1248; + +export const spec = { + code: BIDDER_CODE, + gvlid: GVLID, + supportedMediaTypes: [VIDEO, BANNER], + + isBidRequestValid: (bid) => + !!(bid && bid.params && bid.params.zone && bid.bidder === BIDDER_CODE), + + buildRequests: (bidRequests, bidderRequest) => { + const currencyObj = config.getConfig("currency"); + const currency = (currencyObj && currencyObj.adServerCurrency) || "USD"; + + const request = { + id: bidRequests[0].bidderRequestId, + at: 1, + imp: bidRequests.map((slot) => impression(slot, currency)), + site: { + page: bidderRequest.refererInfo.page, + domain: bidderRequest.refererInfo.domain, + ref: bidderRequest.refererInfo.ref, + publisher: { domain: bidderRequest.refererInfo.domain }, + }, + device: { + ua: navigator.userAgent, + js: 1, + dnt: getDNT() ? 1 : 0, + h: screen.height, + w: screen.width, + language: navigator.language, + connectiontype: getConnectionType(), + }, + cur: [currency], + source: { + fd: 1, + tid: bidderRequest.ortb2?.source?.tid, + ext: { + prebid: "$prebid.version$", + }, + }, + user: {}, + regs: {}, + ext: {}, + }; + + if (bidderRequest.gdprConsent) { + request.user = { + ext: { + consent: bidderRequest.gdprConsent.consentString || "", + }, + }; + request.regs = { + ext: { + gdpr: + bidderRequest.gdprConsent.gdprApplies !== undefined + ? bidderRequest.gdprConsent.gdprApplies + : true, + }, + }; + } + + if (bidderRequest.ortb2?.source?.ext?.schain) { + request.schain = bidderRequest.ortb2.source.ext.schain; + } + + let bidUserIdAsEids = deepAccess(bidRequests, "0.userIdAsEids"); + if (isArray(bidUserIdAsEids) && bidUserIdAsEids.length > 0) { + deepSetValue(request, "user.eids", bidUserIdAsEids); + } + + const commonFpd = bidderRequest.ortb2 || {}; + const { user, device, site, bcat, badv } = commonFpd; + if (site) { + mergeDeep(request, { site: site }); + } + if (user) { + mergeDeep(request, { user: user }); + } + if (badv) { + mergeDeep(request, { badv: badv }); + } + if (bcat) { + mergeDeep(request, { bcat: bcat }); + } + + if (user?.geo && device?.geo) { + request.device.geo = { ...request.device.geo, ...device.geo }; + request.user.geo = { ...request.user.geo, ...user.geo }; + } else { + if (user?.geo || device?.geo) { + request.user.geo = request.device.geo = user?.geo + ? { ...request.user.geo, ...user.geo } + : { ...request.user.geo, ...device.geo }; + } + } + + if (bidderRequest.ortb2?.device) { + mergeDeep(request.device, bidderRequest.ortb2.device); + } + + return { + method: "POST", + url: ENDPOINT, + data: JSON.stringify(request), + }; + }, + + interpretResponse: (bidResponse, bidRequest) => { + const idToImpMap = {}; + const idToBidMap = {}; + + if (!bidResponse["body"]) { + return []; + } + if (!bidRequest.data) { + return []; + } + const requestImps = parse(bidRequest.data); + if (!requestImps) { + return []; + } + requestImps.imp.forEach((imp) => { + idToImpMap[imp.id] = imp; + }); + bidResponse = bidResponse.body; + if (bidResponse) { + bidResponse.seatbid.forEach((seatBid) => + seatBid.bid.forEach((bid) => { + idToBidMap[bid.impid] = bid; + }) + ); + } + const bids = []; + Object.keys(idToImpMap).forEach((id) => { + const imp = idToImpMap[id]; + const result = idToBidMap[id]; + + if (result) { + const bid = { + requestId: id, + cpm: result.price, + creativeId: result.crid, + ttl: 300, + netRevenue: true, + mediaType: imp.video ? VIDEO : BANNER, + currency: bidResponse.cur, + }; + if (imp.video) { + bid.vastXml = result.adm; + } else if (imp.banner) { + bid.ad = result.adm; + } + bid.width = result.w; + bid.height = result.h; + if (result.burl) bid.burl = result.burl; + if (result.nurl) bid.nurl = result.nurl; + if (result.adomain) { + bid.meta = { + advertiserDomains: result.adomain, + }; + } + bids.push(bid); + } + }); + return bids; + }, + + onBidWon: (bid) => { + if (bid.nurl && isStr(bid.nurl)) { + bid.nurl = replaceMacros(bid.nurl, { + AUCTION_PRICE: bid.cpm, + AUCTION_CURRENCY: bid.cur, + }); + triggerPixel(bid.nurl); + } + }, +}; + +function impression(slot, currency) { + let bidFloorFromModule; + if (typeof slot.getFloor === "function") { + const floorInfo = slot.getFloor({ + currency: "USD", + mediaType: "*", + size: "*", + }); + bidFloorFromModule = + floorInfo?.currency === "USD" ? floorInfo?.floor : undefined; + } + const imp = { + id: slot.bidId, + bidfloor: bidFloorFromModule || slot.params.bidfloor || 0, + bidfloorcur: + (bidFloorFromModule && "USD") || + slot.params.bidfloorcur || + currency || + "USD", + tagid: "" + (slot.params.zone || ""), + }; + + if (slot.mediaTypes.banner) { + imp.banner = bannerImpression(slot); + } else if (slot.mediaTypes.video) { + imp.video = deepAccess(slot, "mediaTypes.video"); + } + imp.ext = slot.params || {}; + const { innerWidth, innerHeight } = getWinDimensions(); + imp.ext.ww = innerWidth || ""; + imp.ext.wh = innerHeight || ""; + return imp; +} + +function bannerImpression(slot) { + const sizes = slot.mediaTypes.banner.sizes || slot.sizes; + return { + format: sizes.map((s) => ({ w: s[0], h: s[1] })), + w: sizes[0][0], + h: sizes[0][1], + }; +} + +function parse(rawResponse) { + try { + if (rawResponse) { + if (typeof rawResponse === "object") { + return rawResponse; + } else { + return JSON.parse(rawResponse); + } + } + } catch (ex) { + logError("empowerBidAdapter", "ERROR", ex); + } + return null; +} + +registerBidder(spec); diff --git a/modules/gmosspBidAdapter.js b/modules/gmosspBidAdapter.js index 7bff19bb2c0..28b2d7cb7b8 100644 --- a/modules/gmosspBidAdapter.js +++ b/modules/gmosspBidAdapter.js @@ -1,6 +1,5 @@ import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js'; import { tryAppendQueryString } from '../libraries/urlUtils/urlUtils.js'; -import {getDNT} from '../libraries/dnt/index.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { @@ -51,7 +50,6 @@ export const spec = { const urlInfo = getUrlInfo(bidderRequest.refererInfo); const cur = getCurrencyType(bidderRequest); - const dnt = getDNT() ? '1' : '0'; for (let i = 0; i < validBidRequests.length; i++) { let queryString = ''; @@ -76,7 +74,6 @@ export const spec = { queryString = tryAppendQueryString(queryString, 'meta_url', urlInfo.canonicalLink); queryString = tryAppendQueryString(queryString, 'ref', urlInfo.ref); queryString = tryAppendQueryString(queryString, 'cur', cur); - queryString = tryAppendQueryString(queryString, 'dnt', dnt); bidRequests.push({ method: 'GET', diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 46249591937..cb251230899 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -7,6 +7,7 @@ import {getStorageManager} from '../src/storageManager.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -280,7 +281,7 @@ function _getDeviceData(ortb2Data) { ipv6: _device.ipv6, ua: _device.ua, sua: _device.sua ? JSON.stringify(_device.sua) : undefined, - dnt: _device.dnt, + dnt: getDNT() ? 1 : 0, os: _device.os, osv: _device.osv, dt: _device.devicetype, diff --git a/modules/impactifyBidAdapter.js b/modules/impactifyBidAdapter.js index 49ffe99245d..3cc74429b50 100644 --- a/modules/impactifyBidAdapter.js +++ b/modules/impactifyBidAdapter.js @@ -1,11 +1,11 @@ 'use strict'; -import {getDNT} from '../libraries/dnt/index.js'; import { deepAccess, deepSetValue, generateUUID, getWinDimensions, isPlainObject } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { ajax } from '../src/ajax.js'; import { getStorageManager } from '../src/storageManager.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/jixieBidAdapter.js b/modules/jixieBidAdapter.js index 3a4df75762b..6fc6c86cfcc 100644 --- a/modules/jixieBidAdapter.js +++ b/modules/jixieBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import {deepAccess, isArray, logWarn, isFn, isPlainObject, logError, logInfo, getWinDimensions} from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; @@ -7,6 +6,7 @@ import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {ajax} from '../src/ajax.js'; import {getRefererInfo} from '../src/refererDetection.js'; import {Renderer} from '../src/Renderer.js'; +import {getDNT} from '../libraries/dnt/index.js'; const ADAPTER_VERSION = '2.1.0'; const PREBID_VERSION = '$prebid.version$'; diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 9ee7312bb84..7f2a3224819 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -1,9 +1,9 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { VIDEO } from '../src/mediaTypes.js'; import { isArray, isFn, deepAccess, deepSetValue, logError, logWarn } from '../src/utils.js'; import { config } from '../src/config.js'; import { hasPurpose1Consent } from '../src/utils/gdpr.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'jwplayer'; const BASE_URL = 'https://vpb-server.jwplayer.com/'; diff --git a/modules/lemmaDigitalBidAdapter.js b/modules/lemmaDigitalBidAdapter.js index 7447d893217..227499424be 100644 --- a/modules/lemmaDigitalBidAdapter.js +++ b/modules/lemmaDigitalBidAdapter.js @@ -1,8 +1,8 @@ import * as utils from '../src/utils.js'; -import { getDNT } from '../libraries/dnt/index.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/lkqdBidAdapter.js b/modules/lkqdBidAdapter.js index 535dbbf759b..a017b3c2eb3 100644 --- a/modules/lkqdBidAdapter.js +++ b/modules/lkqdBidAdapter.js @@ -46,7 +46,6 @@ export const spec = { const DOMAIN = bid.params.pageurl || REFERER; const GDPR = BIDDER_GDPR || bid.params.gdpr || null; const GDPRS = BIDDER_GDPRS || bid.params.gdprs || null; - const DNT = bid.params.dnt || null; const BID_FLOOR = 0; const VIDEO_BID = bid.video ? bid.video : {}; @@ -76,10 +75,6 @@ export const spec = { } }; - if (isSet(DNT)) { - requestData.device.dnt = DNT; - } - if (isSet(config.getConfig('coppa'))) { requestData.regs.coppa = config.getConfig('coppa') === true ? 1 : 0; } diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js index 3a7039d7899..0224c951374 100644 --- a/modules/marsmediaBidAdapter.js +++ b/modules/marsmediaBidAdapter.js @@ -1,11 +1,11 @@ 'use strict'; -import {getDNT} from '../libraries/dnt/index.js'; import { deepAccess, parseSizesInput, isArray, getWindowTop, deepSetValue, triggerPixel, getWindowSelf, isPlainObject } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import {config} from '../src/config.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; +import {getDNT} from '../libraries/dnt/index.js'; function MarsmediaAdapter() { this.code = 'marsmedia'; diff --git a/modules/mediaforceBidAdapter.js b/modules/mediaforceBidAdapter.js index a1d333ab0af..a5a87fc80a1 100644 --- a/modules/mediaforceBidAdapter.js +++ b/modules/mediaforceBidAdapter.js @@ -1,9 +1,9 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { deepAccess, isStr, replaceAuctionPrice, triggerPixel, parseGPTSingleSizeArrayToRtbSize } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { buildNativeRequest, parseNativeResponse } from '../libraries/nativeAssetsUtils.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/mediakeysBidAdapter.js b/modules/mediakeysBidAdapter.js index a4eeb591d90..34159385cc7 100644 --- a/modules/mediakeysBidAdapter.js +++ b/modules/mediakeysBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { cleanObj, deepAccess, @@ -21,6 +20,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; +import {getDNT} from '../libraries/dnt/index.js'; const AUCTION_TYPE = 1; const BIDDER_CODE = 'mediakeys'; diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index 8044768bdad..c74a3ba65b2 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { _each, deepAccess, @@ -25,6 +24,7 @@ import { getStorageManager } from '../src/storageManager.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js' +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/mileBidAdapter.ts b/modules/mileBidAdapter.ts index f24feb8b74b..7271d8b0370 100644 --- a/modules/mileBidAdapter.ts +++ b/modules/mileBidAdapter.ts @@ -1,8 +1,8 @@ import { type BidderSpec, registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { deepAccess, deepSetValue, generateUUID, logInfo, logError } from '../src/utils.js'; -import { getDNT } from '../libraries/dnt/index.js'; import { ajax } from '../src/ajax.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * Mile Bid Adapter diff --git a/modules/nexverseBidAdapter.js b/modules/nexverseBidAdapter.js index 25d52000a82..91e78b807bd 100644 --- a/modules/nexverseBidAdapter.js +++ b/modules/nexverseBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js'; import { isArray, generateUUID, getWinDimensions, isNumber } from '../src/utils.js'; @@ -9,6 +8,7 @@ import { getDeviceModel, buildEndpointUrl, isBidRequestValid, parseNativeRespons import {getStorageManager} from '../src/storageManager.js'; import {MODULE_TYPE_UID} from '../src/activities/modules.js'; import { config } from '../src/config.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'nexverse'; const BIDDER_ENDPOINT = 'https://rtb.nexverse.ai'; diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 2db74ecde60..c84414c9202 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -61,9 +61,7 @@ const converter = ortbConverter({ if (bid.params.coppa) { utils.deepSetValue(req, 'regs.coppa', 1); } - if (bid.params.doNotTrack) { - utils.deepSetValue(req, 'device.dnt', 1); - } + utils.deepSetValue(req, 'device.dnt', 0); if (bid.params.platform) { utils.deepSetValue(req, 'ext.platform', bid.params.platform); } diff --git a/modules/operaadsBidAdapter.js b/modules/operaadsBidAdapter.js index 8645196d07d..201ecfb8540 100644 --- a/modules/operaadsBidAdapter.js +++ b/modules/operaadsBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { deepAccess, deepSetValue, @@ -17,6 +16,7 @@ import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {Renderer} from '../src/Renderer.js'; import {OUTSTREAM} from '../src/video.js'; import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/panxoBidAdapter.js b/modules/panxoBidAdapter.js index 6f9eb80ae84..1a898b64887 100644 --- a/modules/panxoBidAdapter.js +++ b/modules/panxoBidAdapter.js @@ -8,6 +8,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { deepAccess, logWarn, isFn, isPlainObject } from '../src/utils.js'; import { getStorageManager } from '../src/storageManager.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'panxo'; const ENDPOINT_URL = 'https://panxo-sys.com/openrtb/2.5/bid'; @@ -112,7 +113,7 @@ function buildDevice() { ua: navigator.userAgent, language: navigator.language, js: 1, - dnt: navigator.doNotTrack === '1' ? 1 : 0 + dnt: getDNT() ? 1 : 0 }; if (typeof screen !== 'undefined') { diff --git a/modules/pwbidBidAdapter.js b/modules/pwbidBidAdapter.js index cb383fee630..854d56e4ae0 100644 --- a/modules/pwbidBidAdapter.js +++ b/modules/pwbidBidAdapter.js @@ -1,10 +1,10 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { _each, isBoolean, isNumber, isStr, deepClone, isArray, deepSetValue, inIframe, mergeDeep, deepAccess, logMessage, logInfo, logWarn, logError, isPlainObject } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { OUTSTREAM, INSTREAM } from '../src/video.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index e3d4b15aebc..173c8e0649f 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -1,9 +1,9 @@ 'use strict'; -import {getDNT} from '../libraries/dnt/index.js'; import { deepAccess, parseSizesInput, isArray } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import {getDNT} from '../libraries/dnt/index.js'; function RhythmOneBidAdapter() { this.code = 'rhythmone'; diff --git a/modules/scaliburBidAdapter.js b/modules/scaliburBidAdapter.js index b8b05c3ac61..7dce8ee319a 100644 --- a/modules/scaliburBidAdapter.js +++ b/modules/scaliburBidAdapter.js @@ -3,6 +3,7 @@ import {config} from '../src/config.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {getStorageManager} from '../src/storageManager.js'; import {sizesToSizeTuples} from "../src/utils.js"; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'scalibur'; const ENDPOINT_SERVER = new URLSearchParams(window.location.search).get('sclServer') || 'srv'; @@ -115,7 +116,7 @@ export const spec = { ua: ortb2Device.ua, language: ortb2Device.language, sua: ortb2Device.sua || {}, - dnt: ortb2Device.dnt ?? 0, + dnt: getDNT() ? 1 : 0, }, user: { eids, diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index c0bcd4e03c4..2f47729de09 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -1,4 +1,3 @@ -import { getDNT } from '../libraries/dnt/index.js'; import { handleCookieSync, PID_STORAGE_NAME, prepareSplitImps } from '../libraries/equativUtils/equativUtils.js'; import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; @@ -6,6 +5,7 @@ import { config } from '../src/config.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; import { deepAccess, generateUUID, inIframe, isPlainObject, logWarn, mergeDeep } from '../src/utils.js'; +import {getDNT} from '../libraries/dnt/index.js'; const VERSION = '4.3.0'; const BIDDER_CODE = 'sharethrough'; diff --git a/modules/smaatoBidAdapter.js b/modules/smaatoBidAdapter.js index 68ca0704d43..23c96a3292a 100644 --- a/modules/smaatoBidAdapter.js +++ b/modules/smaatoBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import {deepAccess, deepSetValue, isEmpty, isNumber, logError, logInfo} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {config} from '../src/config.js'; @@ -6,6 +5,7 @@ import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {NATIVE_IMAGE_TYPES} from '../src/constants.js'; import {getAdUnitSizes} from '../libraries/sizeUtils/sizeUtils.js'; import {ortbConverter} from '../libraries/ortbConverter/converter.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 00f8616a665..9c4460b108a 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { logError, deepAccess, @@ -21,6 +20,7 @@ import { import { VIDEO } from '../src/mediaTypes.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/snigelBidAdapter.js b/modules/snigelBidAdapter.js index 29534ae7318..3349ed737eb 100644 --- a/modules/snigelBidAdapter.js +++ b/modules/snigelBidAdapter.js @@ -1,10 +1,10 @@ -import {getDNT} from '../libraries/dnt/index.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER} from '../src/mediaTypes.js'; import {deepAccess, isArray, isFn, isPlainObject, inIframe, generateUUID} from '../src/utils.js'; import {getStorageManager} from '../src/storageManager.js'; import { getViewportSize } from '../libraries/viewport/viewport.js'; +import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'snigel'; const GVLID = 1076; diff --git a/modules/tappxBidAdapter.js b/modules/tappxBidAdapter.js index 6ca3adb4d54..561b02e6a9a 100644 --- a/modules/tappxBidAdapter.js +++ b/modules/tappxBidAdapter.js @@ -1,12 +1,12 @@ 'use strict'; -import {getDNT} from '../libraries/dnt/index.js'; import { logWarn, deepAccess, isFn, isPlainObject, isBoolean, isNumber, isStr, isArray } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { Renderer } from '../src/Renderer.js'; import { parseDomain } from '../src/refererDetection.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/theAdxBidAdapter.js b/modules/theAdxBidAdapter.js index d57e307c7e1..2e8b3549365 100644 --- a/modules/theAdxBidAdapter.js +++ b/modules/theAdxBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { logInfo, isEmpty, deepAccess, parseUrl, parseSizesInput, _map } from '../src/utils.js'; import { BANNER, @@ -10,6 +9,7 @@ import { } from '../src/adapters/bidderFactory.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/ttdBidAdapter.js b/modules/ttdBidAdapter.js index 4598c3b8a7a..a73baa4af1f 100644 --- a/modules/ttdBidAdapter.js +++ b/modules/ttdBidAdapter.js @@ -3,8 +3,8 @@ import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { isNumber } from '../src/utils.js'; -import { getDNT } from '../libraries/dnt/index.js'; import { getConnectionType } from '../libraries/connectionInfo/connectionUtils.js' +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index f73bd470b14..8eda650ee09 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -1,10 +1,10 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { generateUUID, _each, deepAccess } from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; import { config } from '../src/config.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 18926496258..f2934d32f10 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -1,4 +1,3 @@ -import {getDNT} from '../libraries/dnt/index.js'; import { deepAccess, deepSetValue, @@ -18,6 +17,7 @@ import { import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { Renderer } from '../src/Renderer.js'; +import {getDNT} from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/src/fpd/enrichment.ts b/src/fpd/enrichment.ts index 1ccaaaf6692..2780ba2d09d 100644 --- a/src/fpd/enrichment.ts +++ b/src/fpd/enrichment.ts @@ -12,7 +12,6 @@ import { mergeDeep, memoize } from '../utils.js'; -import { getDNT } from '../../libraries/dnt/index.js'; import {config} from '../config.js'; import {getHighEntropySUA, getLowEntropySUA} from './sua.js'; import {PbPromise} from '../utils/promise.js'; @@ -158,7 +157,6 @@ const ENRICHMENTS = { const device = { w, h, - dnt: getDNT() ? 1 : 0, ua: win.navigator.userAgent, language: win.navigator.language.split('-').shift(), ext: { diff --git a/test/spec/libraries/dnt_spec.js b/test/spec/libraries/dnt_spec.js deleted file mode 100644 index 177542dca31..00000000000 --- a/test/spec/libraries/dnt_spec.js +++ /dev/null @@ -1,34 +0,0 @@ -import {getDNT} from '../../../libraries/dnt/index.js'; - -describe('dnt helper', () => { - let win; - beforeEach(() => { - win = {}; - }); - - [ - 'top', - 'doNotTrack', - 'navigator', - 'navigator.doNotTrack', - 'top.doNotTrack', - 'top.navigator.doNotTrack' - ].forEach(path => { - it(`should not choke if ${path} throws`, () => { - path = path.split('.'); - path.reduce((parent, name, i) => { - if (i === path.length - 1) { - Object.defineProperty(parent, name, { - get() { - throw new Error(); - } - }) - } else { - parent = parent[name] = {}; - } - return parent; - }, win); - expect(getDNT(win)).to.be.false; - }) - }) -}) diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index b2ca5c622fe..ec2c3a5dc3c 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -1,7 +1,6 @@ import {expect} from 'chai'; import {spec} from 'modules/adkernelBidAdapter'; import * as utils from 'src/utils'; -import * as navigatorDnt from 'libraries/dnt/index.js'; import {NATIVE, BANNER, VIDEO} from 'src/mediaTypes'; import {config} from 'src/config'; import {parseDomain} from '../../../src/refererDetection.js'; @@ -342,11 +341,9 @@ describe('Adkernel adapter', function () { } const DEFAULT_BIDDER_REQUEST = buildBidderRequest(); - function buildRequest(bidRequests, bidderRequest = DEFAULT_BIDDER_REQUEST, dnt = true) { - const dntmock = sandbox.stub(navigatorDnt, 'getDNT').callsFake(() => dnt); + function buildRequest(bidRequests, bidderRequest = DEFAULT_BIDDER_REQUEST) { bidderRequest.bids = bidRequests; const pbRequests = spec.buildRequests(bidRequests, bidderRequest); - dntmock.restore(); const rtbRequests = pbRequests.map(r => JSON.parse(r.data)); return [pbRequests, rtbRequests]; } @@ -419,7 +416,6 @@ describe('Adkernel adapter', function () { expect(bidRequest.device).to.have.property('ip', 'caller'); expect(bidRequest.device).to.have.property('ipv6', 'caller'); expect(bidRequest.device).to.have.property('ua', 'caller'); - expect(bidRequest.device).to.have.property('dnt', 1); }); it('should copy FPD to imp.banner', function() { @@ -470,11 +466,6 @@ describe('Adkernel adapter', function () { expect(bidRequest).to.not.have.property('user'); }); - it('should\'t pass dnt if state is unknown', function () { - const [_, bidRequests] = buildRequest([bid1_zone1], DEFAULT_BIDDER_REQUEST, false); - expect(bidRequests[0].device).to.not.have.property('dnt'); - }); - it('should forward default bidder timeout', function() { const [_, bidRequests] = buildRequest([bid1_zone1]); expect(bidRequests[0]).to.have.property('tmax', 3000); diff --git a/test/spec/modules/adtrgtmeBidAdapter_spec.js b/test/spec/modules/adtrgtmeBidAdapter_spec.js index 702086c48a2..960028a379c 100644 --- a/test/spec/modules/adtrgtmeBidAdapter_spec.js +++ b/test/spec/modules/adtrgtmeBidAdapter_spec.js @@ -562,7 +562,7 @@ describe('Adtrgtme Bid Adapter:', () => { }); expect(data.device).to.deep.equal({ - dnt: 0, + dnt: 0, // DNT deprecated by W3C; Prebid no longer supports DNT ua: navigator.userAgent, ip: undefined }); diff --git a/test/spec/modules/gmosspBidAdapter_spec.js b/test/spec/modules/gmosspBidAdapter_spec.js index b3d0c20f3d4..e18ce39109a 100644 --- a/test/spec/modules/gmosspBidAdapter_spec.js +++ b/test/spec/modules/gmosspBidAdapter_spec.js @@ -72,7 +72,7 @@ describe('GmosspAdapter', 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&im_uid=h.0a4749e7ffe09fa6&shared_id=1111&idl_env=1111&url=https%3A%2F%2Fhoge.com' + '&ref=' + encodeURIComponent(document.referrer) + '&cur=JPY&dnt=0&'); + expect(requests[0].data).to.equal('tid=791e9d84-af92-4903-94da-24c7426d9d0c&bid=2b84475b5b636e&ver=$prebid.version$&sid=123456&im_uid=h.0a4749e7ffe09fa6&shared_id=1111&idl_env=1111&url=https%3A%2F%2Fhoge.com' + '&ref=' + encodeURIComponent(document.referrer) + '&cur=JPY&'); }); it('should use fallback if refererInfo.referer in bid request is empty and im_uid ,shared_id, idl_env cookie is empty', function () { @@ -86,7 +86,7 @@ describe('GmosspAdapter', function () { bidRequests[0].userId.idl_env = ''; const requests = spec.buildRequests(bidRequests, bidderRequest); - const result = 'tid=791e9d84-af92-4903-94da-24c7426d9d0c&bid=2b84475b5b636e&ver=$prebid.version$&sid=123456&ref=' + encodeURIComponent(document.referrer) + '&cur=JPY&dnt=0&'; + const result = 'tid=791e9d84-af92-4903-94da-24c7426d9d0c&bid=2b84475b5b636e&ver=$prebid.version$&sid=123456&ref=' + encodeURIComponent(document.referrer) + '&cur=JPY&'; expect(requests[0].data).to.equal(result); }); }); diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js index c8a0109a94b..cdfda655af3 100644 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -1,6 +1,5 @@ import { spec } from 'modules/marsmediaBidAdapter.js'; import * as utils from 'src/utils.js'; -import * as dnt from 'libraries/dnt/index.js'; import { config } from 'src/config.js'; import { internal, resetWinDimensions } from '../../../src/utils.js'; @@ -399,15 +398,10 @@ describe('marsmedia adapter tests', function () { expect(openrtbRequest.imp[0].banner.format.length).to.equal(1); }); - it('dnt is correctly set to 1', function () { - var dntStub = sinon.stub(dnt, 'getDNT').returns(1); - + it('dnt is always 0', function () { var bidRequest = marsAdapter.buildRequests(this.defaultBidRequestList, this.defaultBidderRequest); - - dntStub.restore(); - const openrtbRequest = JSON.parse(bidRequest.data); - expect(openrtbRequest.device.dnt).to.equal(1); + expect(openrtbRequest.device.dnt).to.equal(0); }); it('supports string video sizes', function () { diff --git a/test/spec/modules/mediaforceBidAdapter_spec.js b/test/spec/modules/mediaforceBidAdapter_spec.js index 6ae86dc0801..a0cb4b57a38 100644 --- a/test/spec/modules/mediaforceBidAdapter_spec.js +++ b/test/spec/modules/mediaforceBidAdapter_spec.js @@ -1,7 +1,6 @@ import {assert} from 'chai'; import {spec, resolveFloor} from 'modules/mediaforceBidAdapter.js'; import * as utils from '../../../src/utils.js'; -import { getDNT } from 'libraries/dnt/index.js'; import {BANNER, NATIVE, VIDEO} from '../../../src/mediaTypes.js'; describe('mediaforce bid adapter', function () { @@ -126,7 +125,7 @@ describe('mediaforce bid adapter', function () { ] }; - const dnt = getDNT() ? 1 : 0; + const dnt = 0; // DNT deprecated by W3C; Prebid no longer supports DNT const secure = window.location.protocol === 'https:' ? 1 : 0; const pageUrl = window.location.href; const timeout = 1500; diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index 3019cebe377..e6c5f752418 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -2,7 +2,6 @@ import {expect} from 'chai'; import { spec, storage } from 'modules/mgidBidAdapter.js'; import { version } from 'package.json'; import * as utils from '../../../src/utils.js'; -import { getDNT } from 'libraries/dnt/index.js'; import {USERSYNC_DEFAULT_CONFIG} from '../../../src/userSync.js'; import {config} from '../../../src/config.js'; @@ -23,7 +22,7 @@ describe('Mgid bid adapter', function () { }); const screenHeight = screen.height; const screenWidth = screen.width; - const dnt = getDNT() ? 1 : 0; + const dnt = 0; // DNT deprecated by W3C; Prebid no longer supports DNT const language = navigator.language ? 'language' : 'userLanguage'; let lang = navigator[language].split('-')[0]; if (lang.length !== 2 && lang.length !== 3) { diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 1ba5df02786..a0b5e841f85 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -4,7 +4,6 @@ import {newBidder} from 'src/adapters/bidderFactory.js'; import {BANNER, NATIVE, VIDEO} from 'src/mediaTypes.js'; import {config} from 'src/config.js'; import * as utils from 'src/utils.js'; -import * as dnt from 'libraries/dnt/index.js'; // load modules that register ORTB processors import 'src/prebid.js' import 'modules/currency.js'; @@ -1050,32 +1049,7 @@ describe('OpenxRtbAdapter', function () { }); context('do not track (DNT)', function() { - let doNotTrackStub; - - beforeEach(function () { - doNotTrackStub = sinon.stub(dnt, 'getDNT'); - }); - afterEach(function() { - doNotTrackStub.restore(); - }); - - it('when there is a do not track, should send a dnt', async function () { - doNotTrackStub.returns(1); - - const request = spec.buildRequests(bidRequestsWithMediaTypes, await addFPDToBidderRequest(mockBidderRequest)); - expect(request[0].data.device.dnt).to.equal(1); - }); - - it('when there is not do not track, don\'t send dnt', async function () { - doNotTrackStub.returns(0); - - const request = spec.buildRequests(bidRequestsWithMediaTypes, await addFPDToBidderRequest(mockBidderRequest)); - expect(request[0].data.device.dnt).to.equal(0); - }); - - it('when there is no defined do not track, don\'t send dnt', async function () { - doNotTrackStub.returns(null); - + it('always sends dnt as 0', async function () { const request = spec.buildRequests(bidRequestsWithMediaTypes, await addFPDToBidderRequest(mockBidderRequest)); expect(request[0].data.device.dnt).to.equal(0); }); diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index b9fa0cd37af..40506db90a1 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -1,6 +1,5 @@ import {spec} from '../../../modules/rhythmoneBidAdapter.js'; import * as utils from '../../../src/utils.js'; -import * as dnt from 'libraries/dnt/index.js'; import * as sinon from 'sinon'; var r1adapter = spec; @@ -414,37 +413,6 @@ describe('rhythmone adapter tests', function () { expect(openrtbRequest.imp[0].banner.format.length).to.equal(1); }); - it('dnt is correctly set to 1', function () { - var bidRequestList = [ - { - 'bidder': 'rhythmone', - 'params': { - 'placementId': 'myplacement', - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 600]] - } - }, - 'adUnitCode': 'div-gpt-ad-1438287399331-0', - 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', - 'bidderRequestId': '418b37f85e772c', - 'auctionId': '18fd8b8b0bd757', - 'bidRequestsCount': 1, - 'bidId': '51ef8751f9aead' - } - ]; - - var dntStub = sinon.stub(dnt, 'getDNT').returns(1); - - var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); - - dntStub.restore(); - - const openrtbRequest = JSON.parse(bidRequest.data); - expect(openrtbRequest.device.dnt).to.equal(1); - }); - it('sets floor to zero', function () { var bidRequestList = [ { diff --git a/test/spec/modules/trafficgateBidAdapter_spec.js b/test/spec/modules/trafficgateBidAdapter_spec.js index ded4f1c0aa0..c51e820947f 100644 --- a/test/spec/modules/trafficgateBidAdapter_spec.js +++ b/test/spec/modules/trafficgateBidAdapter_spec.js @@ -846,38 +846,6 @@ describe('TrafficgateOpenxRtbAdapter', function () { }); }); - context('do not track (DNT)', function() { - let doNotTrackStub; - - beforeEach(function () { - doNotTrackStub = sinon.stub(dnt, 'getDNT'); - }); - afterEach(function() { - doNotTrackStub.restore(); - }); - - it('when there is a do not track, should send a dnt', async function () { - doNotTrackStub.returns(1); - - const request = spec.buildRequests(bidRequestsWithMediaTypes, await addFPDToBidderRequest(mockBidderRequest)); - expect(request[0].data.device.dnt).to.equal(1); - }); - - it('when there is not do not track, don\'t send dnt', async function () { - doNotTrackStub.returns(0); - - const request = spec.buildRequests(bidRequestsWithMediaTypes, await addFPDToBidderRequest(mockBidderRequest)); - expect(request[0].data.device.dnt).to.equal(0); - }); - - it('when there is no defined do not track, don\'t send dnt', async function () { - doNotTrackStub.returns(null); - - const request = spec.buildRequests(bidRequestsWithMediaTypes, await addFPDToBidderRequest(mockBidderRequest)); - expect(request[0].data.device.dnt).to.equal(0); - }); - }); - context('supply chain (schain)', function () { let bidRequests; let schainConfig; diff --git a/test/spec/modules/valuadBidAdapter_spec.js b/test/spec/modules/valuadBidAdapter_spec.js index d2e05930619..4a27bbd32df 100644 --- a/test/spec/modules/valuadBidAdapter_spec.js +++ b/test/spec/modules/valuadBidAdapter_spec.js @@ -6,7 +6,6 @@ import { BANNER } from 'src/mediaTypes.js'; import { deepClone, generateUUID } from 'src/utils.js'; import { config } from 'src/config.js'; import * as utils from 'src/utils.js'; -import * as dnt from 'libraries/dnt/index.js'; import * as gptUtils from 'libraries/gptUtils/gptUtils.js'; import * as refererDetection from 'src/refererDetection.js'; import * as BoundingClientRect from 'libraries/boundingClientRect/boundingClientRect.js'; @@ -122,7 +121,6 @@ describe('ValuadAdapter', function () { }); sandbox.stub(utils, 'canAccessWindowTop').returns(true); - sandbox.stub(dnt, 'getDNT').returns(false); sandbox.stub(utils, 'generateUUID').returns('test-uuid'); sandbox.stub(refererDetection, 'parseDomain').returns('test.com'); From 6e425b353112d6dde6ba55c889059155e1ea752c Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Thu, 26 Feb 2026 07:41:41 -0800 Subject: [PATCH 26/48] Prebid 11: add `adUnit.element` option (#14467) * Core: add elementSelector property of ad units * core: use getAdUnitElement * various adapters: use getAdUnitElement * various modules: use getAdUnitElement * various adapters: use getAdUnitElement * use .element, not .elementSelector * lint * fix secureCreatives tests * Update ixBidAdapter.js * Remove TODO note; update type * lint * pubmaticBidAdapter: use getAdUnitElement * placement position: use getAdUnitElement --------- Co-authored-by: Patrick McCann --- .../placementPositionInfo.js | 4 +- modules/33acrossBidAdapter.js | 10 +-- modules/adagioBidAdapter.js | 3 +- modules/adagioRtdProvider.js | 1 + modules/adnuntiusAnalyticsAdapter.js | 3 +- modules/adotBidAdapter.js | 3 +- modules/adrelevantisBidAdapter.js | 8 +-- modules/appnexusBidAdapter.js | 15 ++-- modules/bidViewabilityIO.js | 3 +- modules/concertBidAdapter.js | 3 +- modules/connatixBidAdapter.js | 5 +- modules/contxtfulRtdProvider.js | 2 + modules/cwireBidAdapter.js | 3 +- modules/eplanningBidAdapter.js | 1 + modules/fanBidAdapter.js | 4 +- modules/gamoshiBidAdapter.js | 3 +- modules/h12mediaBidAdapter.js | 3 +- modules/hypelabBidAdapter.js | 7 +- modules/ixBidAdapter.js | 14 ++-- modules/livewrappedAnalyticsAdapter.js | 3 +- modules/marsmediaBidAdapter.js | 3 +- modules/mediafuseBidAdapter.js | 15 ++-- modules/medianetBidAdapter.js | 11 +-- modules/msftBidAdapter.js | 17 +++-- modules/nexverseBidAdapter.js | 3 +- modules/omsBidAdapter.js | 3 +- modules/onetagBidAdapter.js | 7 +- modules/onomagicBidAdapter.js | 3 +- modules/pubmaticBidAdapter.js | 11 +-- modules/rubiconBidAdapter.js | 3 +- modules/seedtagBidAdapter.js | 7 +- modules/sparteoBidAdapter.js | 1 + modules/stroeerCoreBidAdapter.js | 1 + modules/taboolaBidAdapter.js | 7 +- modules/underdogmediaBidAdapter.js | 9 +-- modules/undertoneBidAdapter.js | 7 +- modules/valuadBidAdapter.js | 3 +- modules/visxBidAdapter.js | 11 +-- modules/widespaceBidAdapter.js | 3 +- modules/yandexBidAdapter.js | 3 +- src/adUnits.ts | 5 ++ src/adapterManager.ts | 1 + src/auction.ts | 4 +- src/secureCreatives.js | 6 +- src/utils/adUnits.ts | 21 ++++++ test/spec/auctionmanager_spec.js | 6 ++ .../libraries/placementPositionInfo_spec.js | 9 +-- .../modules/adnuntiusAnalyticsAdapter_spec.js | 4 +- test/spec/modules/concertBidAdapter_spec.js | 3 +- test/spec/modules/connatixBidAdapter_spec.js | 11 +-- test/spec/modules/cwireBidAdapter_spec.js | 14 ++-- test/spec/modules/ixBidAdapter_spec.js | 8 +-- .../livewrappedAnalyticsAdapter_spec.js | 3 +- test/spec/modules/marsmediaBidAdapter_spec.js | 3 +- test/spec/modules/medianetBidAdapter_spec.js | 33 +++------ test/spec/modules/omsBidAdapter_spec.js | 3 +- test/spec/modules/onomagicBidAdapter_spec.js | 3 +- test/spec/modules/pubmaticBidAdapter_spec.js | 8 +-- test/spec/modules/seedtagBidAdapter_spec.js | 71 ++++++++++--------- test/spec/modules/undertoneBidAdapter_spec.js | 4 +- test/spec/modules/visxBidAdapter_spec.js | 11 ++- test/spec/unit/core/adapterManager_spec.js | 13 ++++ test/spec/unit/secureCreatives_spec.js | 1 + test/spec/utils/adUnits_spec.js | 40 +++++++++++ 64 files changed, 313 insertions(+), 198 deletions(-) create mode 100644 src/utils/adUnits.ts create mode 100644 test/spec/utils/adUnits_spec.js diff --git a/libraries/placementPositionInfo/placementPositionInfo.js b/libraries/placementPositionInfo/placementPositionInfo.js index 19014632a23..8cbb234d448 100644 --- a/libraries/placementPositionInfo/placementPositionInfo.js +++ b/libraries/placementPositionInfo/placementPositionInfo.js @@ -1,10 +1,10 @@ import {getBoundingClientRect} from '../boundingClientRect/boundingClientRect.js'; import {canAccessWindowTop, cleanObj, getWinDimensions, getWindowSelf, getWindowTop} from '../../src/utils.js'; import {getViewability, getViewportOffset} from '../percentInView/percentInView.js'; +import {getAdUnitElement} from '../../src/utils/adUnits.js'; export function getPlacementPositionUtils() { const topWin = canAccessWindowTop() ? getWindowTop() : getWindowSelf(); - const selfWin = getWindowSelf(); const getViewportHeight = () => { const dim = getWinDimensions(); @@ -49,7 +49,7 @@ export function getPlacementPositionUtils() { }; function getPlacementInfo(bidReq) { - const element = selfWin.document.getElementById(bidReq.adUnitCode); + const element = getAdUnitElement(bidReq); const frameOffset = getViewportOffset(); const {distanceToView, elementHeight} = getViewableDistance(element, frameOffset); diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 3c2c364fafd..3d72986230e 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -17,6 +17,7 @@ import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; import {isIframe} from '../libraries/omsUtils/index.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; // **************************** UTILS ************************** // const BIDDER_CODE = '33across'; @@ -373,7 +374,7 @@ function _getProduct(bidRequest) { // BUILD REQUESTS: BANNER function _buildBannerORTB(bidRequest) { const bannerAdUnit = deepAccess(bidRequest, 'mediaTypes.banner', {}); - const element = _getAdSlotHTMLElement(bidRequest.adUnitCode); + const element = _getAdSlotHTMLElement(bidRequest); const sizes = _transformSizes(bannerAdUnit.sizes); @@ -478,6 +479,7 @@ function _getViewability(element, topWin, { w, h } = {}) { : 0; } +// TODO use utils/adUnits once that's unified in 11 function _mapAdUnitPathToElementId(adUnitCode) { if (isGptPubadsDefined()) { // eslint-disable-next-line no-undef @@ -500,9 +502,9 @@ function _mapAdUnitPathToElementId(adUnitCode) { return null; } -function _getAdSlotHTMLElement(adUnitCode) { - return document.getElementById(adUnitCode) || - document.getElementById(_mapAdUnitPathToElementId(adUnitCode)); +function _getAdSlotHTMLElement(bidRequest) { + return getAdUnitElement(bidRequest) || + document.getElementById(_mapAdUnitPathToElementId(bidRequest.adUnitCode)); } /** diff --git a/modules/adagioBidAdapter.js b/modules/adagioBidAdapter.js index 9d04e166600..6de60552a22 100644 --- a/modules/adagioBidAdapter.js +++ b/modules/adagioBidAdapter.js @@ -25,6 +25,7 @@ import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { userSync } from '../src/userSync.js'; import { validateOrtbFields } from '../src/prebid.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'adagio'; const LOG_PREFIX = 'Adagio:'; @@ -466,7 +467,7 @@ const OUTSTREAM_RENDERER = { return; } - const el = document.getElementById(bid.adUnitCode); + const el = getAdUnitElement(bid); renderer.bootstrap(config, el, override); }, diff --git a/modules/adagioRtdProvider.js b/modules/adagioRtdProvider.js index dfc6361234e..201d6d0e5e2 100644 --- a/modules/adagioRtdProvider.js +++ b/modules/adagioRtdProvider.js @@ -495,6 +495,7 @@ function getElementFromTopWindow(element, currentWindow) { }; function getSlotPosition(divId) { + // TODO: this should use getAdUnitElement if (!isSafeFrameWindow() && !canAccessWindowTop()) { return ''; } diff --git a/modules/adnuntiusAnalyticsAdapter.js b/modules/adnuntiusAnalyticsAdapter.js index 6de06332e3e..1bfbdc1e68c 100644 --- a/modules/adnuntiusAnalyticsAdapter.js +++ b/modules/adnuntiusAnalyticsAdapter.js @@ -3,6 +3,7 @@ import {ajax} from '../src/ajax.js'; import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js'; import { EVENTS } from '../src/constants.js'; import adapterManager from '../src/adapterManager.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const URL = 'https://analytics.adnuntius.com/prebid'; const REQUEST_SENT = 1; @@ -36,7 +37,7 @@ const adnAnalyticsAdapter = Object.assign(adapter({url: '', analyticsType: 'endp cache.auctions[args.auctionId].gdprApplies = args.gdprConsent ? args.gdprConsent.gdprApplies : undefined; cache.auctions[args.auctionId].gdprConsent = args.gdprConsent ? args.gdprConsent.consentString : undefined; - const container = document.getElementById(bidReq.adUnitCode); + const container = getAdUnitElement(bidReq); const containerAttr = container ? container.getAttribute('data-adunitid') : undefined; const adUnitId = containerAttr || undefined; diff --git a/modules/adotBidAdapter.js b/modules/adotBidAdapter.js index 121c9960ade..052be840333 100644 --- a/modules/adotBidAdapter.js +++ b/modules/adotBidAdapter.js @@ -7,6 +7,7 @@ import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { isArray, isBoolean, isFn, isPlainObject, isStr, logError, replaceAuctionPrice } from '../src/utils.js'; import { OUTSTREAM } from '../src/video.js'; import { NATIVE_ASSETS_IDS as NATIVE_ID_MAPPING, NATIVE_ASSETS as NATIVE_PLACEMENTS } from '../libraries/braveUtils/nativeAssets.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -495,7 +496,7 @@ function buildRenderer(bid, mediaType) { ad.renderer.push(() => { const domContainer = container ? document.querySelector(container) - : document.getElementById(adUnitCode); + : getAdUnitElement(ad) const player = new window.VASTPlayer(domContainer); diff --git a/modules/adrelevantisBidAdapter.js b/modules/adrelevantisBidAdapter.js index 7f2d850a23a..5fb877f5110 100644 --- a/modules/adrelevantisBidAdapter.js +++ b/modules/adrelevantisBidAdapter.js @@ -21,6 +21,7 @@ import {getANKeywordParam} from '../libraries/appnexusUtils/anKeywords.js'; import {chunk} from '../libraries/chunk/chunk.js'; import {transformSizes} from '../libraries/sizeUtils/tranformSize.js'; import {hasUserInfo, hasAppDeviceInfo, hasAppId} from '../libraries/adrelevantisUtils/bidderUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -250,10 +251,9 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { /** * This function hides google div container for outstream bids to remove unwanted space on page. Appnexus renderer creates a new iframe outside of google iframe to render the outstream creative. - * @param {string} elementId element id */ -function hidedfpContainer(elementId) { - var el = document.getElementById(elementId).querySelectorAll("div[id^='google_ads']"); +function hidedfpContainer(bid) { + var el = getAdUnitElement(bid).querySelectorAll("div[id^='google_ads']"); if (el[0]) { el[0].style.setProperty('display', 'none'); } @@ -261,7 +261,7 @@ function hidedfpContainer(elementId) { function outstreamRender(bid) { // push to render queue because ANOutstreamVideo may not be loaded yet - hidedfpContainer(bid.adUnitCode); + hidedfpContainer(bid); bid.renderer.push(() => { window.ANOutstreamVideo.renderAd({ tagId: bid.adResponse.tag_id, diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index c710789640d..5eb2a8a483e 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -35,6 +35,7 @@ import { import {convertCamelToUnderscore, appnexusAliases} from '../libraries/appnexusUtils/anUtils.js'; import {convertTypes} from '../libraries/transformParamsUtils/convertTypes.js'; import {chunk} from '../libraries/chunk/chunk.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -1177,11 +1178,10 @@ function buildNativeRequest(params) { /** * This function hides google div container for outstream bids to remove unwanted space on page. Appnexus renderer creates a new iframe outside of google iframe to render the outstream creative. - * @param {string} elementId element id */ -function hidedfpContainer(elementId) { +function hidedfpContainer(container) { try { - const el = document.getElementById(elementId).querySelectorAll("div[id^='google_ads']"); + const el = container.querySelectorAll("div[id^='google_ads']"); if (el[0]) { el[0].style.setProperty('display', 'none'); } @@ -1190,10 +1190,10 @@ function hidedfpContainer(elementId) { } } -function hideSASIframe(elementId) { +function hideSASIframe(container) { try { // find script tag with id 'sas_script'. This ensures it only works if you're using Smart Ad Server. - const el = document.getElementById(elementId).querySelectorAll("script[id^='sas_script']"); + const el = container.querySelectorAll("script[id^='sas_script']"); if (el[0].nextSibling && el[0].nextSibling.localName === 'iframe') { el[0].nextSibling.style.setProperty('display', 'none'); } @@ -1203,8 +1203,9 @@ function hideSASIframe(elementId) { } function outstreamRender(bid, doc) { - hidedfpContainer(bid.adUnitCode); - hideSASIframe(bid.adUnitCode); + const container = getAdUnitElement(bid); + hidedfpContainer(container); + hideSASIframe(container); // push to render queue because ANOutstreamVideo may not be loaded yet bid.renderer.push(() => { const win = doc?.defaultView || window; diff --git a/modules/bidViewabilityIO.js b/modules/bidViewabilityIO.js index 195b551c85b..201a779bb32 100644 --- a/modules/bidViewabilityIO.js +++ b/modules/bidViewabilityIO.js @@ -2,6 +2,7 @@ import { logMessage } from '../src/utils.js'; import { config } from '../src/config.js'; import * as events from '../src/events.js'; import {EVENTS} from '../src/constants.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const MODULE_NAME = 'bidViewabilityIO'; const CONFIG_ENABLED = 'enabled'; @@ -80,7 +81,7 @@ export const init = () => { events.on(EVENTS.AD_RENDER_SUCCEEDED, ({doc, bid, id}) => { if (isSupportedMediaType(bid)) { const viewable = new IntersectionObserver(viewCallbackFactory(bid), getViewableOptions(bid)); - const element = document.getElementById(bid.adUnitCode); + const element = getAdUnitElement(bid); viewable.observe(element); } }); diff --git a/modules/concertBidAdapter.js b/modules/concertBidAdapter.js index a83c078ccef..0af69b71f32 100644 --- a/modules/concertBidAdapter.js +++ b/modules/concertBidAdapter.js @@ -4,6 +4,7 @@ import { getStorageManager } from '../src/storageManager.js'; import { hasPurpose1Consent } from '../src/utils/gdpr.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -70,7 +71,7 @@ export const spec = { payload.slots = validBidRequests.map((bidRequest) => { eids.push(...(bidRequest.userIdAsEids || [])); - const adUnitElement = document.getElementById(bidRequest.adUnitCode); + const adUnitElement = getAdUnitElement(bidRequest); const coordinates = getOffset(adUnitElement); const slot = { diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index 7b22de3aa1d..b5a749af56b 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -25,6 +25,7 @@ import { BANNER, VIDEO, } from '../src/mediaTypes.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'connatix'; @@ -111,7 +112,7 @@ export function _getViewability(element, topWin, { w, h } = {}) { } export function detectViewability(bid) { - const { params, adUnitCode } = bid; + const { params } = bid; const viewabilityContainerIdentifier = params.viewabilityContainerIdentifier; @@ -137,7 +138,7 @@ export function detectViewability(bid) { bidParamSizes = typeof bidParamSizes === 'undefined' && bid.mediaType && bid.mediaType.video && bid.mediaType.video.playerSize ? bid.mediaType.video.playerSize : bidParamSizes; bidParamSizes = typeof bidParamSizes === 'undefined' && bid.mediaType && bid.mediaType.video && isNumber(bid.mediaType.video.w) && isNumber(bid.mediaType.h) ? [bid.mediaType.video.w, bid.mediaType.video.h] : bidParamSizes; minSize = _getMinSize(bidParamSizes ?? []) - element = document.getElementById(adUnitCode); + element = getAdUnitElement(bid); } if (_isViewabilityMeasurable(element)) { diff --git a/modules/contxtfulRtdProvider.js b/modules/contxtfulRtdProvider.js index 4c319c9b48a..f711c300b8b 100644 --- a/modules/contxtfulRtdProvider.js +++ b/modules/contxtfulRtdProvider.js @@ -292,6 +292,7 @@ function getDivIdPosition(divId) { let domElement; + // TODO: this should use getAdUnitElement if (inIframe() === true) { const ws = getWindowSelf(); const currentElement = ws.document.getElementById(divId); @@ -335,6 +336,7 @@ function tryGetDivIdPosition(divIdMethod) { return undefined; } +// TODO unified adUnit/element association in 11 function tryMultipleDivIdPositions(adUnit) { const divMethods = [ // ortb2\ diff --git a/modules/cwireBidAdapter.js b/modules/cwireBidAdapter.js index 875dfdedf67..ccf6697987b 100644 --- a/modules/cwireBidAdapter.js +++ b/modules/cwireBidAdapter.js @@ -11,6 +11,7 @@ import { getBoundingClientRect } from "../libraries/boundingClientRect/boundingC import { hasPurpose1Consent } from "../src/utils/gdpr.js"; import { sendBeacon } from "../src/ajax.js"; import { isAutoplayEnabled } from "../libraries/autoplayDetection/autoplay.js"; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -35,7 +36,7 @@ export const storage = getStorageManager({ bidderCode: BIDDER_CODE }); */ function slotDimensions(bid) { const adUnitCode = bid.adUnitCode; - const slotEl = document.getElementById(adUnitCode); + const slotEl = getAdUnitElement(bid); if (slotEl) { logInfo(`Slot element found: ${adUnitCode}`); diff --git a/modules/eplanningBidAdapter.js b/modules/eplanningBidAdapter.js index 7ef55e31784..ab8c3ce5874 100644 --- a/modules/eplanningBidAdapter.js +++ b/modules/eplanningBidAdapter.js @@ -420,6 +420,7 @@ function _mapAdUnitPathToElementId(adUnitCode) { } function _getAdSlotHTMLElement(adUnitCode) { + // TODO: this should use getAdUnitElement return document.getElementById(adUnitCode) || document.getElementById(_mapAdUnitPathToElementId(adUnitCode)); } diff --git a/modules/fanBidAdapter.js b/modules/fanBidAdapter.js index 04247011751..266f121812c 100644 --- a/modules/fanBidAdapter.js +++ b/modules/fanBidAdapter.js @@ -6,6 +6,7 @@ import { getBidFloor } from '../libraries/currencyUtils/floor.js'; import { getStorageManager } from '../src/storageManager.js'; import { Renderer } from '../src/Renderer.js'; import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'freedomadnetwork'; const BIDDER_VERSION = '0.2.0'; @@ -349,8 +350,7 @@ function createRenderer(bid, videoPlayerUrl) { try { renderer.setRender(function (bidResponse) { - const divId = document.getElementById(bid.adUnitCode) ? bid.adUnitCode : getGptSlotInfoForAdUnitCode(bid.adUnitCode).divId; - const adUnit = document.getElementById(divId); + const adUnit = getAdUnitElement(bidResponse) ?? document.getElementById(getGptSlotInfoForAdUnitCode(bid.adUnitCode).divId) if (!window.createOutstreamPlayer) { logWarn('Renderer error: outstream player is not available'); diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index 66e74badf5e..d4d6c888057 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -16,6 +16,7 @@ import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {ortbConverter} from '../libraries/ortbConverter/converter.js'; import {ortb25Translator} from '../libraries/ortb2.5Translator/translator.js'; import {getCurrencyFromBidderRequest} from '../libraries/ortb2Utils/currency.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const ENDPOINTS = { 'gamoshi': 'https://rtb.gamoshi.io', 'cleanmedianet': 'https://bidder.cleanmediaads.com' @@ -250,7 +251,7 @@ function renderOutstream(bid) { window['GamoshiPlayer'].renderAd({ id: unitId, debug: window.location.href.indexOf('pbjsDebug') >= 0, - placement: document.getElementById(bid.adUnitCode), + placement: getAdUnitElement(bid), width: bid.width, height: bid.height, events: { diff --git a/modules/h12mediaBidAdapter.js b/modules/h12mediaBidAdapter.js index 963ae660e57..0b1a050a153 100644 --- a/modules/h12mediaBidAdapter.js +++ b/modules/h12mediaBidAdapter.js @@ -2,6 +2,7 @@ import { inIframe, logError, logMessage, deepAccess, getWinDimensions } from '.. import { registerBidder } from '../src/adapters/bidderFactory.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getViewportSize } from '../libraries/viewport/viewport.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'h12media'; const DEFAULT_URL = 'https://bidder.h12-media.com/prebid/'; const DEFAULT_CURRENCY = 'USD'; @@ -30,7 +31,7 @@ export const spec = { pubsubid = ''; } const pubcontainerid = bidderParams.pubcontainerid; - const adUnitElement = document.getElementById(pubcontainerid || bidRequest.adUnitCode); + const adUnitElement = pubcontainerid ? document.getElementById(pubcontainerid) : getAdUnitElement(bidRequest); const ishidden = !isVisible(adUnitElement); const framePos = getFramePos(); const coords = isiframe ? { diff --git a/modules/hypelabBidAdapter.js b/modules/hypelabBidAdapter.js index bc562b84cb3..8edd78232b3 100644 --- a/modules/hypelabBidAdapter.js +++ b/modules/hypelabBidAdapter.js @@ -5,6 +5,7 @@ import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRa import { ajax } from '../src/ajax.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getWalletPresence, getWalletProviderFlags } from '../libraries/hypelabUtils/hypelabUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; export const BIDDER_CODE = 'hypelab'; export const ENDPOINT_URL = 'https://api.hypelab.com'; @@ -55,7 +56,7 @@ function buildRequests(validBidRequests, bidderRequest) { winDimensions?.innerHeight || 0 ), ]; - const pp = getPosition(request.adUnitCode); + const pp = getPosition(request); const payload = { property_slug: request.params.property_slug, @@ -121,8 +122,8 @@ function getBidFloor(bid, sizes) { return floor; } -function getPosition(id) { - const element = document.getElementById(id); +function getPosition(bidRequest) { + const element = getAdUnitElement(bidRequest); if (!element) return null; const rect = getBoundingClientRect(element); return [rect.left, rect.top]; diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index da01c3daa07..eedccabac52 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -23,14 +23,16 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { INSTREAM, OUTSTREAM } from '../src/video.js'; import { Renderer } from '../src/Renderer.js'; import {getGptSlotInfoForAdUnitCode} from '../libraries/gptUtils/gptUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const divIdCache = {}; -export function getDivIdFromAdUnitCode(adUnitCode) { +export function getDivIdFromAdUnit(adUnitCode, target) { if (divIdCache[adUnitCode]) { return divIdCache[adUnitCode]; } - const divId = document.getElementById(adUnitCode) ? adUnitCode : getGptSlotInfoForAdUnitCode(adUnitCode).divId; + const element = getAdUnitElement(target); + const divId = element?.id ? element.id : getGptSlotInfoForAdUnitCode(adUnitCode).divId; divIdCache[adUnitCode] = divId; return divId; } @@ -1357,7 +1359,7 @@ function createNativeImps(validBidRequest, nativeImps) { nativeImps[validBidRequest.adUnitCode].tagId = deepAccess(validBidRequest, 'params.tagId'); const adUnitCode = validBidRequest.adUnitCode; - const divId = getDivIdFromAdUnitCode(adUnitCode); + const divId = getDivIdFromAdUnit(adUnitCode, validBidRequest); nativeImps[validBidRequest.adUnitCode].adUnitCode = adUnitCode; nativeImps[validBidRequest.adUnitCode].divId = divId; } @@ -1379,7 +1381,7 @@ function createVideoImps(validBidRequest, videoImps) { videoImps[validBidRequest.adUnitCode].tagId = deepAccess(validBidRequest, 'params.tagId'); const adUnitCode = validBidRequest.adUnitCode; - const divId = getDivIdFromAdUnitCode(adUnitCode); + const divId = getDivIdFromAdUnit(adUnitCode, validBidRequest); videoImps[validBidRequest.adUnitCode].adUnitCode = adUnitCode; videoImps[validBidRequest.adUnitCode].divId = divId; } @@ -1418,7 +1420,7 @@ function createBannerImps(validBidRequest, missingBannerSizes, bannerImps, bidde } const adUnitCode = validBidRequest.adUnitCode; - const divId = getDivIdFromAdUnitCode(adUnitCode); + const divId = getDivIdFromAdUnit(adUnitCode, validBidRequest); bannerImps[validBidRequest.adUnitCode].adUnitCode = adUnitCode; bannerImps[validBidRequest.adUnitCode].divId = divId; @@ -1486,7 +1488,7 @@ function createMissingBannerImp(bid, imp, newSize) { function outstreamRenderer(bid) { bid.renderer.push(function () { const adUnitCode = bid.adUnitCode; - const divId = getDivIdFromAdUnitCode(adUnitCode); + const divId = getDivIdFromAdUnit(adUnitCode, bid); if (!divId) { logWarn(`IX Bid Adapter: adUnitCode: ${divId} not found on page.`); return; diff --git a/modules/livewrappedAnalyticsAdapter.js b/modules/livewrappedAnalyticsAdapter.js index 37b73368fdc..515a88b9b53 100644 --- a/modules/livewrappedAnalyticsAdapter.js +++ b/modules/livewrappedAnalyticsAdapter.js @@ -4,6 +4,7 @@ import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js'; import { EVENTS } from '../src/constants.js'; import adapterManager from '../src/adapterManager.js'; import { getGlobal } from '../src/prebidGlobal.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const ANALYTICSTYPE = 'endpoint'; const URL = 'https://lwadm.com/analytics/10'; @@ -41,7 +42,7 @@ const livewrappedAnalyticsAdapter = Object.assign(adapter({EMPTYURL, ANALYTICSTY cache.auctions[args.auctionId].gdprApplies = args.gdprConsent ? args.gdprConsent.gdprApplies : undefined; cache.auctions[args.auctionId].gdprConsent = args.gdprConsent ? args.gdprConsent.consentString : undefined; let lwFloor; - const container = document.getElementById(bidRequest.adUnitCode); + const container = getAdUnitElement(bidRequest); let adUnitId = container ? container.getAttribute('data-adunitid') : undefined; adUnitId = adUnitId != null ? adUnitId : undefined; diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js index 0224c951374..1ed553a30d0 100644 --- a/modules/marsmediaBidAdapter.js +++ b/modules/marsmediaBidAdapter.js @@ -5,6 +5,7 @@ import { BANNER, VIDEO } from '../src/mediaTypes.js'; import {config} from '../src/config.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; import {getDNT} from '../libraries/dnt/index.js'; function MarsmediaAdapter() { @@ -167,7 +168,7 @@ function MarsmediaAdapter() { bidSizes = bidSizes.filter(size => isArray(size)); const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); - const element = document.getElementById(bid.adUnitCode); + const element = getAdUnitElement(bid); const minSize = getMinSize(processedSizes); const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, getWindowTop(), minSize) diff --git a/modules/mediafuseBidAdapter.js b/modules/mediafuseBidAdapter.js index a2922c6cd3e..9123f05c601 100644 --- a/modules/mediafuseBidAdapter.js +++ b/modules/mediafuseBidAdapter.js @@ -31,6 +31,7 @@ import { } from '../libraries/appnexusUtils/anKeywords.js'; import {convertCamelToUnderscore} from '../libraries/appnexusUtils/anUtils.js'; import {chunk} from '../libraries/chunk/chunk.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -933,19 +934,18 @@ function buildNativeRequest(params) { /** * This function hides google div container for outstream bids to remove unwanted space on page. Mediafuse renderer creates a new iframe outside of google iframe to render the outstream creative. - * @param {string} elementId element id */ -function hidedfpContainer(elementId) { - var el = document.getElementById(elementId).querySelectorAll("div[id^='google_ads']"); +function hidedfpContainer(container) { + var el = container.querySelectorAll("div[id^='google_ads']"); if (el[0]) { el[0].style.setProperty('display', 'none'); } } -function hideSASIframe(elementId) { +function hideSASIframe(container) { try { // find script tag with id 'sas_script'. This ensures it only works if you're using Smart Ad Server. - const el = document.getElementById(elementId).querySelectorAll("script[id^='sas_script']"); + const el = container.querySelectorAll("script[id^='sas_script']"); if (el[0].nextSibling && el[0].nextSibling.localName === 'iframe') { el[0].nextSibling.style.setProperty('display', 'none'); } @@ -955,8 +955,9 @@ function hideSASIframe(elementId) { } function outstreamRender(bid) { - hidedfpContainer(bid.adUnitCode); - hideSASIframe(bid.adUnitCode); + const container = getAdUnitElement(bid); + hidedfpContainer(container); + hideSASIframe(container); // push to render queue because ANOutstreamVideo may not be loaded bid.renderer.push(() => { window.ANOutstreamVideo.renderAd({ diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index 18a557c8617..6e6685ef737 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -23,6 +23,7 @@ import {GLOBAL_VENDOR_ID, MEDIANET} from '../libraries/medianetUtils/constants.j import {getGlobal} from '../src/prebidGlobal.js'; import {getBoundingClientRect} from '../libraries/boundingClientRect/boundingClientRect.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -133,11 +134,11 @@ function getWindowSize() { } } -function getCoordinates(adUnitCode) { - let element = document.getElementById(adUnitCode); - if (!element && adUnitCode.indexOf('/') !== -1) { +function getCoordinates(bidRequest) { + let element = getAdUnitElement(bidRequest); + if (!element && bidRequest.adUnitCode.indexOf('/') !== -1) { // now it means that adUnitCode is GAM AdUnitPath - const {divId} = getGptSlotInfoForAdUnitCode(adUnitCode); + const {divId} = getGptSlotInfoForAdUnitCode(bidRequest.adUnitCode); if (isStr(divId)) { element = document.getElementById(divId); } @@ -239,7 +240,7 @@ function slotParams(bidRequest, bidderRequests) { if (bidFloor) { params.bidfloor = bidFloor; } - const coordinates = getCoordinates(bidRequest.adUnitCode); + const coordinates = getCoordinates(bidRequest); if (coordinates && params.banner && params.banner.length !== 0) { const normCoordinates = normalizeCoordinates(coordinates); params.ext.coordinates = normCoordinates; diff --git a/modules/msftBidAdapter.js b/modules/msftBidAdapter.js index 6155b91e778..1416dcb89cf 100644 --- a/modules/msftBidAdapter.js +++ b/modules/msftBidAdapter.js @@ -31,6 +31,7 @@ import { logWarn, mergeDeep } from "../src/utils.js"; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = "msft"; const DEBUG_PARAMS = ['enabled', 'dongle', 'member_id', 'debug_timeout']; @@ -502,12 +503,10 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { /** * This function hides google div container for outstream bids to remove unwanted space on page. Appnexus renderer creates a new iframe outside of google iframe to render the outstream creative. - * @param {string} elementId element id */ -function hidedfpContainer(elementId) { +function hidedfpContainer(container) { try { - const el = document - .getElementById(elementId) + const el = container .querySelectorAll("div[id^='google_ads']"); if (el[0]) { el[0].style.setProperty("display", "none"); @@ -517,11 +516,10 @@ function hidedfpContainer(elementId) { } } -function hideSASIframe(elementId) { +function hideSASIframe(container) { try { // find script tag with id 'sas_script'. This ensures it only works if you're using Smart Ad Server. - const el = document - .getElementById(elementId) + const el = container .querySelectorAll("script[id^='sas_script']"); if (el[0]?.nextSibling?.localName === "iframe") { el[0].nextSibling.style.setProperty("display", "none"); @@ -539,8 +537,9 @@ function handleOutstreamRendererEvents(bid, id, eventName) { } function outstreamRender(bid, doc) { - hidedfpContainer(bid.adUnitCode); - hideSASIframe(bid.adUnitCode); + const container = getAdUnitElement(bid); + hidedfpContainer(container); + hideSASIframe(container); // push to render queue because ANOutstreamVideo may not be loaded yet bid.renderer.push(() => { const win = doc?.defaultView || window; diff --git a/modules/nexverseBidAdapter.js b/modules/nexverseBidAdapter.js index 91e78b807bd..6aef2b2d078 100644 --- a/modules/nexverseBidAdapter.js +++ b/modules/nexverseBidAdapter.js @@ -8,6 +8,7 @@ import { getDeviceModel, buildEndpointUrl, isBidRequestValid, parseNativeRespons import {getStorageManager} from '../src/storageManager.js'; import {MODULE_TYPE_UID} from '../src/activities/modules.js'; import { config } from '../src/config.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; import {getDNT} from '../libraries/dnt/index.js'; const BIDDER_CODE = 'nexverse'; @@ -191,7 +192,7 @@ function buildOpenRtbRequest(bid, bidderRequest) { const imps = []; // Calculate viewability percentage for the ad unit - const adUnitElement = document.getElementById(bid.adUnitCode); + const adUnitElement = getAdUnitElement(bid); let viewabilityPercentage = 0; if (adUnitElement) { const rect = getBoundingClientRect(adUnitElement); diff --git a/modules/omsBidAdapter.js b/modules/omsBidAdapter.js index 18f7c7aa12a..0be6d55aea5 100644 --- a/modules/omsBidAdapter.js +++ b/modules/omsBidAdapter.js @@ -17,6 +17,7 @@ import {percentInView} from '../libraries/percentInView/percentInView.js'; import {getUserSyncParams} from '../libraries/userSyncUtils/userSyncUtils.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; import {getBidFloor, isIframe} from '../libraries/omsUtils/index.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'oms'; const URL = 'https://rt.marphezis.com/hb'; @@ -44,7 +45,7 @@ function buildRequests(bidReqs, bidderRequest) { bidSizes = bidSizes.filter(size => isArray(size)); const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); - const element = document.getElementById(bid.adUnitCode); + const element = getAdUnitElement(bid); const minSize = getMinSize(processedSizes); const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, getWindowTop(), minSize) : 'na'; const viewabilityAmountRounded = isNaN(viewabilityAmount) ? viewabilityAmount : Math.round(viewabilityAmount); diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js index 827291f5407..8486a982050 100644 --- a/modules/onetagBidAdapter.js +++ b/modules/onetagBidAdapter.js @@ -9,6 +9,7 @@ import { deepClone, logError, deepAccess, getWinDimensions } from '../src/utils. import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { toOrtbNativeRequest } from '../src/native.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -358,14 +359,14 @@ function setGeneralInfo(bidRequest) { if (params.dealId) { this['dealId'] = params.dealId; } - const coords = getSpaceCoords(bidRequest.adUnitCode); + const coords = getSpaceCoords(bidRequest); if (coords) { this['coords'] = coords; } } -function getSpaceCoords(id) { - const space = document.getElementById(id); +function getSpaceCoords(bidRequest) { + const space = getAdUnitElement(bidRequest); try { const { top, left, width, height } = getBoundingClientRect(space); let window = space.ownerDocument.defaultView; diff --git a/modules/onomagicBidAdapter.js b/modules/onomagicBidAdapter.js index c3176d7abcc..7e380d540c0 100644 --- a/modules/onomagicBidAdapter.js +++ b/modules/onomagicBidAdapter.js @@ -12,6 +12,7 @@ import {BANNER} from '../src/mediaTypes.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; import {getBidFloor, isIframe} from '../libraries/omsUtils/index.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'onomagic'; const URL = 'https://bidder.onomagic.com/hb'; @@ -39,7 +40,7 @@ function buildRequests(bidReqs, bidderRequest) { bidSizes = bidSizes.filter(size => isArray(size)); const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); - const element = document.getElementById(bid.adUnitCode); + const element = getAdUnitElement(bid); const minSize = getMinSize(processedSizes); const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, getWindowTop(), minSize) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 57116ed4599..5f5844baa22 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -9,6 +9,7 @@ import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { NATIVE_ASSET_TYPES, NATIVE_IMAGE_TYPES, PREBID_NATIVE_DATA_KEYS_TO_ORTB, NATIVE_KEYS_THAT_ARE_NOT_ASSETS, NATIVE_KEYS } from '../src/constants.js'; import { addDealCustomTargetings, addPMPDeals } from '../libraries/dealUtils/dealUtils.js'; import { getConnectionType } from '../libraries/connectionInfo/connectionUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -95,7 +96,7 @@ const converter = ortbConverter({ if (imp.hasOwnProperty('banner')) updateBannerImp(imp.banner, adSlot); if (imp.hasOwnProperty('video')) updateVideoImp(mediaTypes?.video, adUnitCode, imp); if (imp.hasOwnProperty('native')) updateNativeImp(imp, mediaTypes?.native); - if (imp.hasOwnProperty('banner') || imp.hasOwnProperty('video')) addViewabilityToImp(imp, adUnitCode, bidRequest?.sizes); + if (imp.hasOwnProperty('banner') || imp.hasOwnProperty('video')) addViewabilityToImp(imp, bidRequest, bidRequest?.sizes); if (pmzoneid) imp.ext.pmZoneId = pmzoneid; setImpTagId(imp, adSlot.trim(), hashedKey); setImpFields(imp); @@ -599,7 +600,7 @@ const BB_RENDERER = { } const rendererId = BB_RENDERER.getRendererId(PUBLICATION, bid.rendererCode); - const ele = document.getElementById(bid.adUnitCode); // NB convention + const ele = getAdUnitElement(bid); const renderer = window.bluebillywig.renderers.find(r => r._id === rendererId); if (renderer) renderer.bootstrap(config, ele); @@ -701,10 +702,10 @@ function _getMinSize(sizes) { /** * Measures viewability for an element and adds it to the imp object at the ext level * @param {Object} imp - The impression object - * @param {string} adUnitCode - The ad unit code for element identification + * @param {Object} bidRequest - The bid request for element identification * @param {Object} sizes - Sizes object with width and height properties */ -export const addViewabilityToImp = (imp, adUnitCode, sizes) => { +export const addViewabilityToImp = (imp, bidRequest, sizes) => { let elementSize = { w: 0, h: 0 }; if (imp.video?.w > 0 && imp.video?.h > 0) { @@ -713,7 +714,7 @@ export const addViewabilityToImp = (imp, adUnitCode, sizes) => { } else { elementSize = _getMinSize(sizes); } - const element = document.getElementById(adUnitCode); + const element = getAdUnitElement(bidRequest); if (!element) return; const viewabilityAmount = isViewabilityMeasurable(element) diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 477da80d420..cb8101bbae7 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -23,6 +23,7 @@ import { } from '../src/utils.js'; import {getAllOrtbKeywords} from '../libraries/keywords/keywords.js'; import {getUserSyncParams} from '../libraries/userSyncUtils/userSyncUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -827,7 +828,7 @@ function hideSmartAdServerIframe(adUnit) { function renderBid(bid) { // hide existing ad units - const adUnitElement = document.getElementById(bid.adUnitCode); + const adUnitElement = getAdUnitElement(bid); hideGoogleAdsDiv(adUnitElement); hideSmartAdServerIframe(adUnitElement); diff --git a/modules/seedtagBidAdapter.js b/modules/seedtagBidAdapter.js index f93ed814a0a..2e9ca96f6f7 100644 --- a/modules/seedtagBidAdapter.js +++ b/modules/seedtagBidAdapter.js @@ -5,6 +5,7 @@ import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { _map, getWinDimensions, isArray, triggerPixel } from '../src/utils.js'; import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -123,7 +124,7 @@ function buildBidRequest(validBidRequest) { supplyTypes: mediaTypes, adUnitId: params.adUnitId, adUnitCode: validBidRequest.adUnitCode, - geom: geom(validBidRequest.adUnitCode), + geom: geom(validBidRequest), placement: params.placement, requestCount: validBidRequest.bidderRequestsCount || 1, }; @@ -217,8 +218,8 @@ function ttfb() { return ttfb >= 0 && ttfb <= performance.now() ? ttfb : 0; } -function geom(adunitCode) { - const slot = document.getElementById(adunitCode); +function geom(bidRequest) { + const slot = getAdUnitElement(bidRequest); if (slot) { const { top, left, width, height } = getBoundingClientRect(slot); const viewport = { diff --git a/modules/sparteoBidAdapter.js b/modules/sparteoBidAdapter.js index 13cb0198594..350c3109984 100644 --- a/modules/sparteoBidAdapter.js +++ b/modules/sparteoBidAdapter.js @@ -91,6 +91,7 @@ function createRenderer(rendererConfig) { } function outstreamRender(bid) { + // TODO this should use getAdUnitElement if (!document.getElementById(bid.adUnitCode)) { logError(`Sparteo Bid Adapter: Video renderer did not started. bidResponse.adUnitCode is probably not a DOM element : ${bid.adUnitCode}`); return; diff --git a/modules/stroeerCoreBidAdapter.js b/modules/stroeerCoreBidAdapter.js index aa9f656aa24..ec29df5a045 100644 --- a/modules/stroeerCoreBidAdapter.js +++ b/modules/stroeerCoreBidAdapter.js @@ -156,6 +156,7 @@ const isMainPageAccessible = () => { } const elementInView = (elementId) => { + // TODO this should use getAdUnitElement const resolveElement = (elId) => { const win = getWindowSelf(); diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 3b39dd3db03..276fd335e7b 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -11,6 +11,7 @@ import {getConnectionType} from '../libraries/connectionInfo/connectionUtils.js' import {getViewportCoordinates} from '../libraries/viewport/viewport.js'; import {percentInView} from '../libraries/percentInView/percentInView.js'; import {getBoundingClientRect} from '../libraries/boundingClientRect/boundingClientRect.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'taboola'; const GVLID = 42; @@ -139,9 +140,9 @@ export function getDeviceExtSignals(existingExt = {}) { }; } -export function getElementSignals(adUnitCode) { +export function getElementSignals(bidRequest) { try { - const element = document.getElementById(adUnitCode); + const element = getAdUnitElement(bidRequest); if (!element) return null; const rect = getBoundingClientRect(element); @@ -419,7 +420,7 @@ function fillTaboolaImpData(bid, imp) { deepSetValue(imp, 'ext.prebid.bidderRequestsCount', bid.bidderRequestsCount); deepSetValue(imp, 'ext.prebid.bidderWinsCount', bid.bidderWinsCount); - const elementSignals = getElementSignals(bid.adUnitCode); + const elementSignals = getElementSignals(bid); if (elementSignals) { if (elementSignals.viewability !== undefined) { deepSetValue(imp, 'ext.viewability', elementSignals.viewability); diff --git a/modules/underdogmediaBidAdapter.js b/modules/underdogmediaBidAdapter.js index 45bac54e64c..f0fec36df1e 100644 --- a/modules/underdogmediaBidAdapter.js +++ b/modules/underdogmediaBidAdapter.js @@ -13,6 +13,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import {isSlotMatchingAdUnitCode} from '../libraries/gptUtils/gptUtils.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; import {isIframe} from '../libraries/omsUtils/index.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'underdogmedia'; const UDM_ADAPTER_VERSION = '7.30V'; @@ -109,7 +110,7 @@ export const spec = { sizes = flatten(sizes, parseSizesInput(bidParamSizes)); siteId = +bidParam.params.siteId; const adUnitCode = bidParam.adUnitCode - const element = _getAdSlotHTMLElement(adUnitCode) + const element = _getAdSlotHTMLElement(bidParam) const minSize = _getMinSize(bidParamSizes) placementObject.sizes = parseSizesInput(bidParamSizes) @@ -234,9 +235,9 @@ function _getMinSize(bidParamSizes) { return bidParamSizes.reduce((min, size) => size.h * size.w < min.h * min.w ? size : min) } -function _getAdSlotHTMLElement(adUnitCode) { - return document.getElementById(adUnitCode) || - document.getElementById(_mapAdUnitPathToElementId(adUnitCode)); +function _getAdSlotHTMLElement(bidRequest) { + return getAdUnitElement(bidRequest) || + document.getElementById(_mapAdUnitPathToElementId(bidRequest.adUnitCode)); } function _mapAdUnitPathToElementId(adUnitCode) { diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index badc0911270..01b8760d085 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -7,6 +7,7 @@ import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingC import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'undertone'; const URL = 'https://hb.undertone.com/hb'; @@ -38,8 +39,8 @@ function getGdprQueryParams(gdprConsent) { return `gdpr=${gdpr}&gdprstr=${gdprstr}`; } -function getBannerCoords(id) { - const element = document.getElementById(id); +function getBannerCoords(bidRequest) { + const element = getAdUnitElement(bidRequest); if (element) { const {left, top} = getBoundingClientRect(element); const viewport = getViewportCoordinates(); @@ -109,7 +110,7 @@ export const spec = { validBidRequests.forEach(bidReq => { const bid = { bidRequestId: bidReq.bidId, - coordinates: getBannerCoords(bidReq.adUnitCode), + coordinates: getBannerCoords(bidReq), hbadaptor: 'prebid', url: pageUrl, domain: domain, diff --git a/modules/valuadBidAdapter.js b/modules/valuadBidAdapter.js index 6a32d80b806..d6af61d8077 100644 --- a/modules/valuadBidAdapter.js +++ b/modules/valuadBidAdapter.js @@ -12,6 +12,7 @@ import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; import { config } from '../src/config.js'; import { getBoundingBox, percentInView } from '../libraries/percentInView/percentInView.js'; import {isIframe} from '../libraries/omsUtils/index.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'valuad'; const GVL_ID = 1478; @@ -106,7 +107,7 @@ const converter = ortbConverter({ const size = {w: adSize[0], h: adSize[1]}; - const element = document.getElementById(bid.adUnitCode) || document.getElementById(getGptSlotInfoForAdUnitCode(bid.adUnitCode)?.divId); + const element = getAdUnitElement(bid) || document.getElementById(getGptSlotInfoForAdUnitCode(bid.adUnitCode)?.divId); const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, getWindowTop(), size) : 0; const rect = element && getBoundingBox(element, size); diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 801c68acc2d..5b09faa41dd 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -7,6 +7,7 @@ import {getStorageManager} from '../src/storageManager.js'; import {getGptSlotInfoForAdUnitCode} from '../libraries/gptUtils/gptUtils.js'; import { getBidFromResponse } from '../libraries/processResponse/index.js'; import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'visx'; const GVLID = 154; @@ -295,7 +296,7 @@ function makeVideo(videoParams = {}) { } function buildImpObject(bid) { - const { params: { uid }, bidId, mediaTypes, sizes, adUnitCode } = bid; + const { params: { uid }, bidId, mediaTypes, sizes } = bid; const video = mediaTypes && _isVideoBid(bid) && _isValidVideoBid(bid) && makeVideo(mediaTypes.video); const banner = makeBanner((mediaTypes && mediaTypes.banner) || (!video && { sizes })); const impObject = { @@ -308,7 +309,7 @@ function buildImpObject(bid) { }; if (impObject.banner) { - impObject.ext.bidder.adslotExists = _isAdSlotExists(adUnitCode); + impObject.ext.bidder.adslotExists = _isAdSlotExists(bid); } if (bid.ortb2Imp?.ext?.gpid) { @@ -410,12 +411,12 @@ function _isValidVideoBid(bid, logErrors = false) { return result; } -function _isAdSlotExists(adUnitCode) { - if (document.getElementById(adUnitCode)) { +function _isAdSlotExists(bidRequest) { + if (getAdUnitElement(bidRequest)) { return true; } - const gptAdSlot = getGptSlotInfoForAdUnitCode(adUnitCode); + const gptAdSlot = getGptSlotInfoForAdUnitCode(bidRequest.adUnitCode); if (gptAdSlot.divId && document.getElementById(gptAdSlot.divId)) { return true; } diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js index 7a8dec47a28..aa4327bdf8f 100644 --- a/modules/widespaceBidAdapter.js +++ b/modules/widespaceBidAdapter.js @@ -4,6 +4,7 @@ import {deepClone, parseQueryStringParameters, parseSizesInput} from '../src/uti import {getStorageManager} from '../src/storageManager.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; const BIDDER_CODE = 'widespace'; const WS_ADAPTER_VERSION = '2.0.1'; @@ -53,7 +54,7 @@ export const spec = { 'inFrame': 1, 'sid': bid.params.sid, 'lcuid': LC_UID, - 'vol': isInHostileIframe ? '' : visibleOnLoad(document.getElementById(bid.adUnitCode)), + 'vol': isInHostileIframe ? '' : visibleOnLoad(getAdUnitElement(bid)), 'gdprCmp': bidderRequest && bidderRequest.gdprConsent ? 1 : 0, 'hb': '1', 'hb.cd': CUST_DATA ? encodedParamValue(CUST_DATA) : '', diff --git a/modules/yandexBidAdapter.js b/modules/yandexBidAdapter.js index 901bbcf29de..ef7b8910c7d 100644 --- a/modules/yandexBidAdapter.js +++ b/modules/yandexBidAdapter.js @@ -7,6 +7,7 @@ import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingC import { ajax } from '../src/ajax.js'; import { config as pbjsConfig } from '../src/config.js'; import { isWebdriverEnabled } from '../libraries/webdriver/webdriver.js'; +import {getAdUnitElement} from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid @@ -183,7 +184,7 @@ export const spec = { queryParams['tcf-consent'] = consentString; } - const adUnitElement = document.getElementById(bidRequest.params.pubcontainerid || bidRequest.adUnitCode); + const adUnitElement = bidRequest.params.pubcontainerid ? document.getElementById(bidRequest.params.pubcontainerid) : getAdUnitElement(bidRequest); const windowContext = getContext(adUnitElement); const isIframe = inIframe(); const coords = isIframe ? getFramePosition() : { diff --git a/src/adUnits.ts b/src/adUnits.ts index 2cb94f788e3..644ced4df47 100644 --- a/src/adUnits.ts +++ b/src/adUnits.ts @@ -88,6 +88,11 @@ export interface AdUnitDefinition { * Used by setTargetingForGPTAsync() to match which auction is for which ad slot. */ code: AdUnitCode; + /** + * A DOM element corresponding to this ad unit. + * By default, this is `document.getElementById(adUnit.code)`. + */ + element?: HTMLElement; /** * Bid requests representing demand partners and associated parameters. */ diff --git a/src/adapterManager.ts b/src/adapterManager.ts index 7c0faf40d1d..d569bbf0a2c 100644 --- a/src/adapterManager.ts +++ b/src/adapterManager.ts @@ -214,6 +214,7 @@ const ADUNIT_BID_PROPERTIES = [ 'nativeParams', 'nativeOrtbRequest', 'renderer', + 'element', ] as const; type GetBidsOptions = { diff --git a/src/auction.ts b/src/auction.ts index dff01d6421b..a6aa0c85665 100644 --- a/src/auction.ts +++ b/src/auction.ts @@ -33,7 +33,7 @@ import {getMinBidCacheTTL, onMinBidCacheTTLChange} from './bidTTL.js'; import type {Bid, BidResponse} from "./bidfactory.ts"; import type {AdUnitCode, BidderCode, Identifier, ORTBFragments} from './types/common.d.ts'; import type {TargetingMap} from "./targeting.ts"; -import type {AdUnit} from "./adUnits.ts"; +import type {AdUnit, AdUnitDefinition} from "./adUnits.ts"; import type {MediaType} from "./mediaTypes.ts"; import type {VideoContext} from "./video.ts"; import { isActivityAllowed } from './activities/rules.js'; @@ -661,6 +661,7 @@ declare module './bidfactory' { } interface BaseBid { + element?: AdUnitDefinition['element']; /** * true if this bid is for an interstitial slot. */ @@ -770,6 +771,7 @@ function getPreparedBidForAuction(bid: Partial, {index = auctionManager.ind const adUnit = index.getAdUnit(bid); bid.instl = adUnit?.ortb2Imp?.instl === 1; + bid.element = adUnit?.element; // a publisher-defined renderer can be used to render bids const bidRenderer = index.getBidRequest(bid)?.renderer || adUnit.renderer; diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 9979b25da9c..0c609b66608 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -15,6 +15,7 @@ import { } from './adRendering.js'; import {getCreativeRendererSource, PUC_MIN_VERSION} from './creativeRenderers.js'; import {PbPromise} from './utils/promise.js'; +import {getAdUnitElement} from './utils/adUnits.js'; import {auctionManager} from './auctionManager.js'; const { REQUEST, RESPONSE, NATIVE, EVENT } = MESSAGES; @@ -165,7 +166,7 @@ export function resizeAnchor(ins, width, height) { }) } -export function resizeRemoteCreative({instl, adId, adUnitCode, width, height}) { +export function resizeRemoteCreative({instl, element, adId, adUnitCode, width, height}) { // do not resize interstitials - the creative frame takes the full screen and sizing of the ad should // be handled within it. if (instl) return; @@ -188,7 +189,7 @@ export function resizeRemoteCreative({instl, adId, adUnitCode, width, height}) { function getElementByAdUnit(elmType) { const id = getElementIdBasedOnAdServer(adId, adUnitCode); - const parentDivEle = document.getElementById(id); + const parentDivEle = id == null ? getAdUnitElement({element, adUnitCode}) : document.getElementById(id); return parentDivEle && parentDivEle.querySelector(elmType); } @@ -205,7 +206,6 @@ export function resizeRemoteCreative({instl, adId, adUnitCode, width, height}) { return apnId; } } - return adUnitCode; } function getDfpElementId(adId) { diff --git a/src/utils/adUnits.ts b/src/utils/adUnits.ts new file mode 100644 index 00000000000..96e412910ab --- /dev/null +++ b/src/utils/adUnits.ts @@ -0,0 +1,21 @@ +import type {AdUnitDefinition} from "../adUnits.ts"; +import type {BidRequest} from "../adapterManager.ts"; +import type {Bid} from "../bidfactory.ts"; + +export function getAdUnitElement(bidRequest: BidRequest): HTMLElement +export function getAdUnitElement(bidResponse: Bid): HTMLElement +export function getAdUnitElement(adUnit: AdUnitDefinition): HTMLElement +export function getAdUnitElement(target: { + code?: string, + adUnitCode?: string, + element?: HTMLElement +}): HTMLElement | null { + if (target.element != null) { + return target.element; + } + const id = target.adUnitCode ?? target.code; + if (id) { + return document.getElementById(id); + } + return null; +} diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index b3a10ede626..5f1a05afd12 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -1278,6 +1278,12 @@ describe('auctionmanager.js', function () { expect(auction.getBidsReceived()[0].ttlBuffer).to.eql(0); }); + it('sets bidResponse.element from adUnit.element', () => { + adUnits[0].element = 'test'; + auction.callBids(); + expect(auction.getBidsReceived()[0].element).to.equal('test'); + }); + [ { request: 1, diff --git a/test/spec/libraries/placementPositionInfo_spec.js b/test/spec/libraries/placementPositionInfo_spec.js index 9d8a57f4db4..56991fd2430 100644 --- a/test/spec/libraries/placementPositionInfo_spec.js +++ b/test/spec/libraries/placementPositionInfo_spec.js @@ -3,6 +3,7 @@ import * as utils from '../../../src/utils.js'; import * as boundingClientRectLib from '../../../libraries/boundingClientRect/boundingClientRect.js'; import * as percentInViewLib from '../../../libraries/percentInView/percentInView.js'; import * as winDimensions from 'src/utils/winDimensions.js'; +import * as adUnits from 'src/utils/adUnits'; import assert from 'assert'; import sinon from 'sinon'; @@ -80,7 +81,7 @@ describe('placementPositionInfo', function () { beforeEach(function () { mockElement = { id: 'test-ad-unit' }; - mockDocument.getElementById.returns(mockElement); + sandbox.stub(adUnits, 'getAdUnitElement').returns(mockElement); getBoundingClientRectStub.returns({ top: 100, @@ -162,7 +163,7 @@ describe('placementPositionInfo', function () { }); it('should handle null element gracefully', function () { - mockDocument.getElementById.returns(null); + adUnits.getAdUnitElement.returns(null); const bidReq = { adUnitCode: 'non-existent-unit', @@ -177,7 +178,7 @@ describe('placementPositionInfo', function () { }); it('should not call getViewability when element is null', function () { - mockDocument.getElementById.returns(null); + adUnits.getAdUnitElement.returns(null); const bidReq = { adUnitCode: 'non-existent-unit', @@ -400,7 +401,7 @@ describe('placementPositionInfo', function () { describe('iframe coordinate translation', function () { beforeEach(() => { - mockDocument.getElementById = sandbox.stub().returns({id: 'test'}); + sandbox.stub(adUnits, 'getAdUnitElement').returns({id: 'test'}) mockWindow.innerHeight = 1000; mockDocument.body = { scrollHeight: 2000, offsetHeight: 1800 diff --git a/test/spec/modules/adnuntiusAnalyticsAdapter_spec.js b/test/spec/modules/adnuntiusAnalyticsAdapter_spec.js index 55cddbb0dd2..0fc8c700aff 100644 --- a/test/spec/modules/adnuntiusAnalyticsAdapter_spec.js +++ b/test/spec/modules/adnuntiusAnalyticsAdapter_spec.js @@ -2,7 +2,7 @@ import adnAnalyticsAdapter, { BID_WON_TIMEOUT } from 'modules/adnuntiusAnalytics import { AD_RENDER_FAILED_REASON, EVENTS, STATUS } from 'src/constants.js'; import { config } from 'src/config.js'; import { server } from 'test/mocks/xhr.js'; -import { setConfig } from 'modules/currency.js'; +import * as adUnits from 'src/utils/adUnits'; const events = require('src/events'); const utils = require('src/utils'); @@ -301,7 +301,7 @@ describe('Adnuntius analytics adapter', function () { } sandbox.stub(events, 'getEvents').returns([]); sandbox.stub(utils, 'timestamp').returns(1519149562416); - sandbox.stub(document, 'getElementById').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); clock = sandbox.useFakeTimers(1519767013781); }); diff --git a/test/spec/modules/concertBidAdapter_spec.js b/test/spec/modules/concertBidAdapter_spec.js index 6c842e58d37..cf22b23e9ae 100644 --- a/test/spec/modules/concertBidAdapter_spec.js +++ b/test/spec/modules/concertBidAdapter_spec.js @@ -3,6 +3,7 @@ import sinon from 'sinon'; import { spec, storage } from 'modules/concertBidAdapter.js'; import { hook } from 'src/hook.js'; import {getGlobal} from '../../../src/prebidGlobal.js'; +import * as adUnits from 'src/utils/adUnits'; describe('ConcertAdapter', function () { let bidRequests; @@ -86,7 +87,7 @@ describe('ConcertAdapter', function () { } sandbox = sinon.createSandbox(); - sandbox.stub(document, 'getElementById').withArgs('desktop_leaderboard_variable').returns(element) + sandbox.stub(adUnits, 'getAdUnitElement').returns(element) }); afterEach(function () { diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js index aa9bdac75bd..e8a88775a5f 100644 --- a/test/spec/modules/connatixBidAdapter_spec.js +++ b/test/spec/modules/connatixBidAdapter_spec.js @@ -19,6 +19,7 @@ import adapterManager from '../../../src/adapterManager.js'; import * as ajax from '../../../src/ajax.js'; import { ADPOD, BANNER, VIDEO } from '../../../src/mediaTypes.js'; import * as winDimensions from '../../../src/utils/winDimensions.js'; +import * as adUnits from 'src/utils/adUnits'; const BIDDER_CODE = 'connatix'; @@ -220,7 +221,7 @@ describe('connatixBidAdapter', function () { let getBoundingClientRectStub; let topWinMock; let querySelectorStub; - let getElementByIdStub; + let getElementStub; let sandbox; beforeEach(() => { @@ -237,7 +238,7 @@ describe('connatixBidAdapter', function () { }; querySelectorStub = sandbox.stub(window.top.document, 'querySelector'); - getElementByIdStub = sandbox.stub(document, 'getElementById'); + getElementStub = sandbox.stub(adUnits, 'getAdUnitElement'); sandbox.stub(winDimensions, 'getWinDimensions').callsFake(() => ( { document: { @@ -272,7 +273,7 @@ describe('connatixBidAdapter', function () { }); querySelectorStub.withArgs('#validElement').returns(element); - getElementByIdStub.returns(null); + getElementStub.returns(null); const result = connatixDetectViewability(bid); @@ -298,7 +299,7 @@ describe('connatixBidAdapter', function () { }); querySelectorStub.withArgs('#invalidElement').returns(null); - getElementByIdStub.withArgs('adUnitCode123').returns(element); + getElementStub.returns(element); const result = connatixDetectViewability(bid); @@ -325,7 +326,7 @@ describe('connatixBidAdapter', function () { }); // The fallback should use the adUnitCode to find the element - getElementByIdStub.withArgs('adUnitCode123').returns(element); + getElementStub.returns(element); const result = connatixDetectViewability(bid); diff --git a/test/spec/modules/cwireBidAdapter_spec.js b/test/spec/modules/cwireBidAdapter_spec.js index 1a514d33155..6943618cf51 100644 --- a/test/spec/modules/cwireBidAdapter_spec.js +++ b/test/spec/modules/cwireBidAdapter_spec.js @@ -6,6 +6,7 @@ import * as utils from "src/utils.js"; import sinon, { stub } from "sinon"; import { config } from "../../../src/config.js"; import * as autoplayLib from "../../../libraries/autoplayDetection/autoplay.js"; +import * as adUnits from 'src/utils/adUnits'; describe("C-WIRE bid adapter", () => { config.setConfig({ debug: true }); @@ -101,8 +102,8 @@ describe("C-WIRE bid adapter", () => { describe("buildRequests reads adUnit offsetWidth and offsetHeight", function () { beforeEach(function () { - const documentStub = sandbox.stub(document, "getElementById"); - documentStub.withArgs(`${bidRequests[0].adUnitCode}`).returns({ + const documentStub = sandbox.stub(adUnits, "getAdUnitElement"); + documentStub.returns({ offsetWidth: 200, offsetHeight: 250, getBoundingClientRect() { @@ -115,11 +116,9 @@ describe("C-WIRE bid adapter", () => { const request = spec.buildRequests([bidRequest], bidderRequest); const payload = JSON.parse(request.data); - const el = document.getElementById(`${bidRequest.adUnitCode}`); logInfo(JSON.stringify(payload)); - expect(el).to.exist; expect(payload.slots[0].cwExt.dimensions.width).to.equal(200); expect(payload.slots[0].cwExt.dimensions.height).to.equal(250); expect(payload.slots[0].cwExt.style.maxHeight).to.not.exist; @@ -131,8 +130,8 @@ describe("C-WIRE bid adapter", () => { }); describe("buildRequests reads style attributes", function () { beforeEach(function () { - const documentStub = sandbox.stub(document, "getElementById"); - documentStub.withArgs(`${bidRequests[0].adUnitCode}`).returns({ + const documentStub = sandbox.stub(adUnits, "getAdUnitElement"); + documentStub.returns({ style: { maxWidth: "400px", maxHeight: "350px", @@ -147,11 +146,8 @@ describe("C-WIRE bid adapter", () => { const request = spec.buildRequests([bidRequest], bidderRequest); const payload = JSON.parse(request.data); - const el = document.getElementById(`${bidRequest.adUnitCode}`); - logInfo(JSON.stringify(payload)); - expect(el).to.exist; expect(payload.slots[0].cwExt.style.maxWidth).to.eq("400px"); expect(payload.slots[0].cwExt.style.maxHeight).to.eq("350px"); }); diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 1a5bd0f1c01..39a9321fca9 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -2,7 +2,7 @@ import * as utils from 'src/utils.js'; import { config } from 'src/config.js'; import { expect } from 'chai'; import { newBidder } from 'src/adapters/bidderFactory.js'; -import { spec, storage, FEATURE_TOGGLES, LOCAL_STORAGE_FEATURE_TOGGLES_KEY, REQUESTED_FEATURE_TOGGLES, combineImps, bidToVideoImp, bidToNativeImp, deduplicateImpExtFields, removeSiteIDs, addDeviceInfo, getDivIdFromAdUnitCode } from '../../../modules/ixBidAdapter.js'; +import { spec, storage, FEATURE_TOGGLES, LOCAL_STORAGE_FEATURE_TOGGLES_KEY, REQUESTED_FEATURE_TOGGLES, combineImps, bidToVideoImp, bidToNativeImp, deduplicateImpExtFields, removeSiteIDs, addDeviceInfo, getDivIdFromAdUnit } from '../../../modules/ixBidAdapter.js'; import { deepAccess, deepClone } from '../../../src/utils.js'; import * as ajaxLib from 'src/ajax.js'; import * as gptUtils from '../../../libraries/gptUtils/gptUtils.js'; @@ -5217,15 +5217,15 @@ describe('IndexexchangeAdapter', function () { const el = document.createElement('div'); el.id = adUnitCode; document.body.appendChild(el); - expect(getDivIdFromAdUnitCode(adUnitCode)).to.equal(adUnitCode); + expect(getDivIdFromAdUnit(adUnitCode, {code: adUnitCode})).to.equal(adUnitCode); document.body.removeChild(el); }); it('retrieves divId from GPT once and caches result', () => { const adUnitCode = 'div-ad2'; const stub = sinon.stub(gptUtils, 'getGptSlotInfoForAdUnitCode').returns({divId: 'gpt-div'}); - const first = getDivIdFromAdUnitCode(adUnitCode); - const second = getDivIdFromAdUnitCode(adUnitCode); + const first = getDivIdFromAdUnit(adUnitCode, {}); + const second = getDivIdFromAdUnit(adUnitCode, {}); expect(first).to.equal('gpt-div'); expect(second).to.equal('gpt-div'); expect(stub.calledOnce).to.be.true; diff --git a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js index f84d4ace1ff..d0fadf377a1 100644 --- a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +++ b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js @@ -3,6 +3,7 @@ import { AD_RENDER_FAILED_REASON, EVENTS, STATUS } from 'src/constants.js'; import { config } from 'src/config.js'; import { server } from 'test/mocks/xhr.js'; import { setConfig } from 'modules/currency.js'; +import * as adUnits from 'src/utils/adUnits'; const events = require('src/events'); const utils = require('src/utils'); @@ -323,7 +324,7 @@ describe('Livewrapped analytics adapter', function () { } sandbox.stub(events, 'getEvents').returns([]); sandbox.stub(utils, 'timestamp').returns(1519149562416); - sandbox.stub(document, 'getElementById').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); clock = sandbox.useFakeTimers(1519767013781); setConfig({ diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js index cdfda655af3..d0ab86d90ec 100644 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -2,6 +2,7 @@ import { spec } from 'modules/marsmediaBidAdapter.js'; import * as utils from 'src/utils.js'; import { config } from 'src/config.js'; import { internal, resetWinDimensions } from '../../../src/utils.js'; +import * as adUnits from 'src/utils/adUnits'; var marsAdapter = spec; @@ -72,7 +73,7 @@ describe('marsmedia adapter tests', function () { ]; sandbox = sinon.createSandbox(); - sandbox.stub(document, 'getElementById').withArgs('Unit-Code').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); sandbox.stub(utils, 'getWindowTop').returns(win); sandbox.stub(utils, 'getWindowSelf').returns(win); }); diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index 728c68c20b1..d20206895f4 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -6,6 +6,7 @@ import { config } from '../../../src/config.js'; import {server} from '../../mocks/xhr.js'; import {resetWinDimensions} from '../../../src/utils.js'; import {getGlobal} from '../../../src/prebidGlobal.js'; +import * as adUnits from 'src/utils/adUnits'; getGlobal().version = getGlobal().version || 'version'; const VALID_BID_REQUEST = [{ @@ -1979,17 +1980,13 @@ describe('Media.net bid adapter', function () { beforeEach(function () { getGlobal().medianetGlobals = {}; - const documentStub = sandbox.stub(document, 'getElementById'); const boundingRect = { top: 50, left: 50, bottom: 100, right: 100 }; - documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ - getBoundingClientRect: () => boundingRect - }); - documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + sandbox.stub(adUnits, 'getAdUnitElement').returns({ getBoundingClientRect: () => boundingRect }); const windowSizeStub = sandbox.stub(spec, 'getWindowSize'); @@ -2089,14 +2086,14 @@ describe('Media.net bid adapter', function () { }); describe('slot visibility', function () { - let documentStub; + let elementStub; beforeEach(function () { const windowSizeStub = sandbox.stub(spec, 'getWindowSize'); windowSizeStub.returns({ w: 1000, h: 1000 }); - documentStub = sandbox.stub(document, 'getElementById'); + elementStub = sandbox.stub(adUnits, 'getAdUnitElement'); }); it('slot visibility should be 2 and ratio 0 when ad unit is BTF', function () { const boundingRect = { @@ -2105,10 +2102,7 @@ describe('Media.net bid adapter', function () { bottom: 1050, right: 1050 }; - documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ - getBoundingClientRect: () => boundingRect - }); - documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + elementStub.returns({ getBoundingClientRect: () => boundingRect }); @@ -2124,10 +2118,7 @@ describe('Media.net bid adapter', function () { bottom: 1050, right: 1050 }; - documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ - getBoundingClientRect: () => boundingRect - }); - documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + elementStub.returns({ getBoundingClientRect: () => boundingRect }); const bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); @@ -2142,10 +2133,7 @@ describe('Media.net bid adapter', function () { bottom: 1050, right: 1050 }; - documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ - getBoundingClientRect: () => boundingRect - }); - documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + elementStub.returns({ getBoundingClientRect: () => boundingRect }); const bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); @@ -2170,12 +2158,9 @@ describe('Media.net bid adapter', function () { bottom: 1050, right: 1050 }; - documentStub.withArgs(divId).returns({ + elementStub.returns({ getBoundingClientRect: () => boundingRect - }); - documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ - getBoundingClientRect: () => boundingRect - }); + }) const bidRequest = [{...VALID_BID_REQUEST[0], adUnitCode: code}] const bidReq = spec.buildRequests(bidRequest, VALID_AUCTIONDATA); diff --git a/test/spec/modules/omsBidAdapter_spec.js b/test/spec/modules/omsBidAdapter_spec.js index da9c21e7ae3..3a346b2bb99 100644 --- a/test/spec/modules/omsBidAdapter_spec.js +++ b/test/spec/modules/omsBidAdapter_spec.js @@ -3,6 +3,7 @@ import * as utils from 'src/utils.js'; import {spec} from 'modules/omsBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory.js'; import * as winDimensions from 'src/utils/winDimensions.js'; +import * as adUnits from 'src/utils/adUnits'; const URL = 'https://rt.marphezis.com/hb'; @@ -83,7 +84,7 @@ describe('omsBidAdapter', function () { }]; sandbox = sinon.createSandbox(); - sandbox.stub(document, 'getElementById').withArgs('adunit-code').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); sandbox.stub(winDimensions, 'getWinDimensions').returns(win); sandbox.stub(utils, 'getWindowTop').returns(win); sandbox.stub(utils, 'getWindowSelf').returns(win); diff --git a/test/spec/modules/onomagicBidAdapter_spec.js b/test/spec/modules/onomagicBidAdapter_spec.js index d043363b34d..ab44d280797 100644 --- a/test/spec/modules/onomagicBidAdapter_spec.js +++ b/test/spec/modules/onomagicBidAdapter_spec.js @@ -3,6 +3,7 @@ import * as utils from 'src/utils.js'; import { spec } from 'modules/onomagicBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import * as winDimensions from 'src/utils/winDimensions.js'; +import * as adUnits from 'src/utils/adUnits'; const URL = 'https://bidder.onomagic.com/hb'; @@ -61,7 +62,7 @@ describe('onomagicBidAdapter', function() { sandbox = sinon.createSandbox(); sandbox.stub(winDimensions, 'getWinDimensions').returns(win); - sandbox.stub(document, 'getElementById').withArgs('adunit-code').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); sandbox.stub(utils, 'getWindowTop').returns(win); sandbox.stub(utils, 'getWindowSelf').returns(win); }); diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 2ed65dd7311..763827dbcbe 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1856,13 +1856,13 @@ describe('addViewabilityToImp', () => { }); it('should add viewability to imp.ext when measurable', () => { - addViewabilityToImp(imp, 'Div1', { w: 300, h: 250 }); + addViewabilityToImp(imp, {adUnitCode: 'Div1'}, { w: 300, h: 250 }); expect(imp.ext).to.have.property('viewability'); }); it('should set viewability amount to "na" if not measurable (e.g., in iframe)', () => { const isIframeStub = sandbox.stub(utils, 'inIframe').returns(true); - addViewabilityToImp(imp, 'Div1', { w: 300, h: 250 }); + addViewabilityToImp(imp, {adUnitCode: 'Div1'}, { w: 300, h: 250 }); expect(imp.ext).to.have.property('viewability'); expect(imp.ext.viewability.amount).to.equal('na'); }); @@ -1870,13 +1870,13 @@ describe('addViewabilityToImp', () => { it('should not add viewability if element is not found', () => { document.getElementById.restore(); sandbox.stub(document, 'getElementById').returns(null); - addViewabilityToImp(imp, 'Div1', { w: 300, h: 250 }); + addViewabilityToImp(imp, {adUnitCode: 'Div1'}, { w: 300, h: 250 }); expect(imp.ext).to.not.have.property('viewability'); }); it('should create imp.ext if not present', () => { imp = {}; - addViewabilityToImp(imp, 'Div1', { w: 300, h: 250 }); + addViewabilityToImp(imp, {adUnitCode: 'Div1'}, { w: 300, h: 250 }); expect(imp.ext).to.exist; expect(imp.ext).to.have.property('viewability'); }); diff --git a/test/spec/modules/seedtagBidAdapter_spec.js b/test/spec/modules/seedtagBidAdapter_spec.js index 3a448c90d78..f80a95fc9ff 100644 --- a/test/spec/modules/seedtagBidAdapter_spec.js +++ b/test/spec/modules/seedtagBidAdapter_spec.js @@ -4,23 +4,13 @@ import * as utils from 'src/utils.js'; import * as mockGpt from 'test/spec/integration/faker/googletag.js'; import { config } from '../../../src/config.js'; import { BIDFLOOR_CURRENCY } from '../../../modules/seedtagBidAdapter.js'; +import * as adUnits from 'src/utils/adUnits'; const PUBLISHER_ID = '0000-0000-01'; const ADUNIT_ID = '000000'; const adUnitCode = '/19968336/header-bid-tag-0' -// create a default adunit -const slot = document.createElement('div'); -slot.id = adUnitCode; -slot.style.width = '300px' -slot.style.height = '250px' -slot.style.position = 'absolute' -slot.style.top = '10px' -slot.style.left = '20px' - -document.body.appendChild(slot); - function getSlotConfigs(mediaTypes, params) { return { params: params, @@ -60,12 +50,25 @@ const createBannerSlotConfig = (mediatypes) => { }; describe('Seedtag Adapter', function () { + let sandbox; beforeEach(function () { mockGpt.reset(); + sandbox = sinon.createSandbox(); + sandbox.stub(adUnits, 'getAdUnitElement').returns({ + getBoundingClientRect() { + return { + top: 10, + left: 20, + width: 300, + height: 250 + } + } + }); }); afterEach(function () { mockGpt.enable(); + sandbox.restore(); }); describe('isBidRequestValid method', function () { describe('returns true', function () { @@ -328,9 +331,13 @@ describe('Seedtag Adapter', function () { }); describe('BidRequests params', function () { - const request = spec.buildRequests(validBidRequests, bidderRequest); - const data = JSON.parse(request.data); - const bidRequests = data.bidRequests; + let request, data, bidRequests; + beforeEach(() => { + request = spec.buildRequests(validBidRequests, bidderRequest); + data = JSON.parse(request.data); + bidRequests = data.bidRequests; + }); + it('should request a Banner', function () { const bannerBid = bidRequests[0]; expect(bannerBid.id).to.equal('30b31c1838de1e'); @@ -369,27 +376,21 @@ describe('Seedtag Adapter', function () { const bidRequests = data.bidRequests; const bannerBid = bidRequests[0]; - // on some CI, the DOM is not initialized, so we need to check if the slot is available - const slot = document.getElementById(adUnitCode) - if (slot) { - expect(bannerBid).to.have.property('geom') - - const params = [['width', 300], ['height', 250], ['top', 10], ['left', 20], ['scrollY', 0]] - params.forEach(([param, value]) => { - expect(bannerBid.geom).to.have.property(param) - expect(bannerBid.geom[param]).to.be.a('number') - expect(bannerBid.geom[param]).to.be.equal(value) - }) - - expect(bannerBid.geom).to.have.property('viewport') - const viewportParams = ['width', 'height'] - viewportParams.forEach(param => { - expect(bannerBid.geom.viewport).to.have.property(param) - expect(bannerBid.geom.viewport[param]).to.be.a('number') - }) - } else { - expect(bannerBid).to.not.have.property('geom') - } + expect(bannerBid).to.have.property('geom') + + const params = [['width', 300], ['height', 250], ['top', 10], ['left', 20], ['scrollY', 0]] + params.forEach(([param, value]) => { + expect(bannerBid.geom).to.have.property(param) + expect(bannerBid.geom[param]).to.be.a('number') + expect(bannerBid.geom[param]).to.be.equal(value) + }) + + expect(bannerBid.geom).to.have.property('viewport') + const viewportParams = ['width', 'height'] + viewportParams.forEach(param => { + expect(bannerBid.geom.viewport).to.have.property(param) + expect(bannerBid.geom.viewport[param]).to.be.a('number') + }) }) it('should have bidfloor parameter if available', function () { diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index ed531371af7..b7ad994dc96 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -2,6 +2,8 @@ import {expect} from 'chai'; import {spec} from 'modules/undertoneBidAdapter.js'; import {BANNER, VIDEO} from '../../../src/mediaTypes.js'; import {deepClone, getWinDimensions} from '../../../src/utils.js'; +import * as adUnits from 'src/utils/adUnits'; +import {getAdUnitElement} from 'src/utils/adUnits'; const URL = 'https://hb.undertone.com/hb'; const BIDDER_CODE = 'undertone'; @@ -314,7 +316,7 @@ describe('Undertone Adapter', () => { }; sandbox = sinon.createSandbox(); - sandbox.stub(document, 'getElementById').withArgs('div-gpt-ad-1460505748561-0').returns(element); + sandbox.stub(adUnits, 'getAdUnitElement').returns(element); }); afterEach(function() { diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index a24f537625e..db7c01d7067 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -8,6 +8,7 @@ import { mergeDeep } from '../../../src/utils.js'; import { setConfig as setCurrencyConfig } from '../../../modules/currency.js'; import { addFPDToBidderRequest } from '../../helpers/fpd.js'; import {getGlobal} from '../../../src/prebidGlobal.js'; +import * as adUnits from 'src/utils/adUnits'; describe('VisxAdapter', function () { const adapter = newBidder(spec); @@ -1069,13 +1070,9 @@ describe('VisxAdapter', function () { before(function() { sandbox = sinon.createSandbox(); - documentStub = sandbox.stub(document, 'getElementById'); - documentStub.withArgs('visx-adunit-code-1').returns({ - id: 'visx-adunit-code-1' - }); - documentStub.withArgs('visx-adunit-element-2').returns({ - id: 'visx-adunit-element-2' - }); + sandbox.stub(adUnits, 'getAdUnitElement').callsFake(({adUnitCode}) => { + return ['visx-adunit-code-1', 'visx-adunit-code-2'].includes(adUnitCode); + }) getGlobal().bidderSettings = { visx: { diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 0be07704ed2..f3481950db4 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -32,6 +32,7 @@ import { TRACKER_METHOD_IMG, TRACKER_METHOD_JS } from '../../../../src/eventTrackers.js'; +import 'src/prebid.js'; var events = require('../../../../src/events.js'); const CONFIG = { @@ -1814,6 +1815,18 @@ describe('adapterManager tests', function () { expect(sizes1).not.to.deep.equal(sizes2); }); + it('should transfer element from ad unit', () => { + adUnits[0].element = 'test'; + const requests = makeBidRequests(); + requests.flatMap(req => req.bids).forEach(bidRequest => { + if (bidRequest.adUnitCode === adUnits[0].code) { + expect(bidRequest.element).to.equal('test'); + } else { + expect(bidRequest.element).to.not.exist; + } + }); + }) + it('should transfer deferBilling from ad unit', () => { adUnits[0].deferBilling = true; const requests = makeBidRequests(); diff --git a/test/spec/unit/secureCreatives_spec.js b/test/spec/unit/secureCreatives_spec.js index f7a209400ca..5be5bca5f39 100644 --- a/test/spec/unit/secureCreatives_spec.js +++ b/test/spec/unit/secureCreatives_spec.js @@ -10,6 +10,7 @@ import {config as configObj} from 'src/config.js'; import * as creativeRenderers from 'src/creativeRenderers.js'; import 'src/prebid.js'; import 'modules/nativeRendering.js'; +import * as adUnits from 'src/utils/adUnits'; import {expect} from 'chai'; diff --git a/test/spec/utils/adUnits_spec.js b/test/spec/utils/adUnits_spec.js new file mode 100644 index 00000000000..89e11232359 --- /dev/null +++ b/test/spec/utils/adUnits_spec.js @@ -0,0 +1,40 @@ +import {getAdUnitElement} from '../../../src/utils/adUnits.js'; + +describe('ad unit utils', () => { + let sandbox; + beforeEach(() => { + sandbox = sinon.createSandbox(); + }); + afterEach(() => { + sandbox.restore(); + }); + describe('getAdUnitElement', () => { + beforeEach(() => { + sandbox.stub(document, 'getElementById').callsFake((id) => ({id})); + }); + it('should return null on invalid input', () => { + expect(getAdUnitElement({})).to.eql(null); + }); + it('should prefer element', () => { + expect(getAdUnitElement({ + element: 'explicit', + code: 'ignored', + adUnitCode: 'ignored' + })).to.eql('explicit'); + }); + it('should fallback to code as id', () => { + expect(getAdUnitElement({ + code: 'au' + })).to.eql({ + id: 'au' + }); + }); + it('should fallback to adUnitCode as id', () => { + expect(getAdUnitElement({ + adUnitCode: 'au' + })).to.eql({ + id: 'au' + }) + }) + }); +}); From f861ef481b37be7a6cf4a7e88ba926e8fbab0449 Mon Sep 17 00:00:00 2001 From: mkomorski Date: Thu, 26 Feb 2026 17:19:25 +0100 Subject: [PATCH 27/48] Prebid 11: native event trackers handling (#14524) * Prebid 11: native event trackers handling * field name fix --- src/eventTrackers.js | 1 + src/native.ts | 23 +++++++-- test/spec/native_spec.js | 106 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 124 insertions(+), 6 deletions(-) diff --git a/src/eventTrackers.js b/src/eventTrackers.js index b0c06cf0f1b..a502f0d0a4d 100644 --- a/src/eventTrackers.js +++ b/src/eventTrackers.js @@ -2,6 +2,7 @@ export const TRACKER_METHOD_IMG = 1; export const TRACKER_METHOD_JS = 2; export const EVENT_TYPE_IMPRESSION = 1; export const EVENT_TYPE_WIN = 500; +export const EVENT_TYPE_VIEWABLE = 2; /** * Returns a map from event type (EVENT_TYPE_*) diff --git a/src/native.ts b/src/native.ts index 89a2bb8053d..007b96a3a4c 100644 --- a/src/native.ts +++ b/src/native.ts @@ -23,7 +23,7 @@ import { import {NATIVE} from './mediaTypes.js'; import {getRenderingData} from './adRendering.js'; import {getCreativeRendererSource, PUC_MIN_VERSION} from './creativeRenderers.js'; -import {EVENT_TYPE_IMPRESSION, parseEventTrackers, TRACKER_METHOD_IMG, TRACKER_METHOD_JS} from './eventTrackers.js'; +import {EVENT_TYPE_IMPRESSION, EVENT_TYPE_VIEWABLE, parseEventTrackers, TRACKER_METHOD_IMG, TRACKER_METHOD_JS} from './eventTrackers.js'; import type {Link, NativeRequest, NativeResponse} from "./types/ortb/native.d.ts"; import type {Size} from "./types/common.d.ts"; import type {Ext} from "./types/ortb/common.d.ts"; @@ -350,14 +350,15 @@ export function fireNativeTrackers(message, bidResponse) { if (message.action === 'click') { fireClickTrackers(nativeResponse, message?.assetId); } else { - fireImpressionTrackers(nativeResponse); + fireImpressionTrackers(nativeResponse, bidResponse); } return message.action; } -export function fireImpressionTrackers(nativeResponse, {runMarkup = (mkup) => insertHtmlIntoIframe(mkup), fetchURL = triggerPixel} = {}) { +export function fireImpressionTrackers(nativeResponse, bidResponse, {runMarkup = (mkup) => insertHtmlIntoIframe(mkup), fetchURL = triggerPixel} = {}) { + const filteredEventTrackers = filterEventTrackers(nativeResponse, bidResponse); let {[TRACKER_METHOD_IMG]: img = [], [TRACKER_METHOD_JS]: js = []} = parseEventTrackers( - nativeResponse.eventtrackers || [] + filteredEventTrackers || [] )[EVENT_TYPE_IMPRESSION] || {}; if (nativeResponse.imptrackers) { @@ -398,6 +399,20 @@ export function fireClickTrackers(nativeResponse, assetId = null, {fetchURL = tr } } +export function filterEventTrackers(nativeResponse, bid) { + const DEFAULT_ALLOWED_TRACKERS = [ + { event: EVENT_TYPE_IMPRESSION, methods: [TRACKER_METHOD_IMG, TRACKER_METHOD_JS] }, + { event: EVENT_TYPE_VIEWABLE, methods: [TRACKER_METHOD_IMG, TRACKER_METHOD_JS] }, + ]; + const mediaTypes = auctionManager.index.getMediaTypes(bid) || {}; + const nativeMediaType = mediaTypes.native || {}; + const requestEventTrackers = nativeMediaType.ortb?.eventtrackers || DEFAULT_ALLOWED_TRACKERS; + + const { eventtrackers = [] } = nativeResponse || {}; + + return eventtrackers.filter(tracker => requestEventTrackers.some(requestTracker => requestTracker.event === tracker.event && requestTracker.methods.includes(tracker.method))); +} + export function setNativeResponseProperties(bid, adUnit) { const nativeOrtbRequest = adUnit?.nativeOrtbRequest; const nativeOrtbResponse = bid.native?.ortb; diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index a0c0b28a19d..488f00c9a65 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -22,6 +22,7 @@ import {auctionManager} from '../../src/auctionManager.js'; import {getRenderingData} from '../../src/adRendering.js'; import {getCreativeRendererSource, PUC_MIN_VERSION} from '../../src/creativeRenderers.js'; import {deepSetValue} from '../../src/utils.js'; +import { EVENT_TYPE_IMPRESSION, TRACKER_METHOD_IMG, TRACKER_METHOD_JS } from 'src/eventTrackers.js'; const utils = require('src/utils'); const bid = { @@ -1126,7 +1127,7 @@ describe('fireImpressionTrackers', () => { }) function runTrackers(resp) { - fireImpressionTrackers(resp, {runMarkup, fetchURL}) + fireImpressionTrackers(resp, {}, {runMarkup, fetchURL}) } it('should run markup in jstracker', () => { @@ -1173,7 +1174,108 @@ describe('fireImpressionTrackers', () => { }); sinon.assert.notCalled(fetchURL); sinon.assert.notCalled(runMarkup); - }) + }); + + describe('when bidResponse mediaTypes.native.ortb.eventtrackers filters allowed trackers', () => { + let indexStub; + let getMediaTypesStub; + + beforeEach(() => { + getMediaTypesStub = sinon.stub(); + indexStub = sinon.stub(auctionManager, 'index').get(() => ({ getMediaTypes: getMediaTypesStub })); + }); + + afterEach(() => { + indexStub.restore(); + }); + + it('should fire only impression+IMG eventtrackers when request allows only IMG for impression', () => { + getMediaTypesStub.returns({ + native: { + ortb: { + eventtrackers: [{ event: EVENT_TYPE_IMPRESSION, methods: [TRACKER_METHOD_IMG] }] + } + } + }); + const bidResponse = { adUnitId: 'au', requestId: 'req' }; + fireImpressionTrackers({ + eventtrackers: [ + { event: EVENT_TYPE_IMPRESSION, method: TRACKER_METHOD_IMG, url: 'img-url' }, + { event: EVENT_TYPE_IMPRESSION, method: TRACKER_METHOD_JS, url: 'js-url' } + ] + }, bidResponse, { runMarkup, fetchURL }); + sinon.assert.calledOnceWithExactly(fetchURL, 'img-url'); + sinon.assert.notCalled(runMarkup); + }); + + it('should fire only impression+JS eventtrackers when request allows only JS for impression', () => { + getMediaTypesStub.returns({ + native: { + ortb: { + eventtrackers: [{ event: EVENT_TYPE_IMPRESSION, methods: [TRACKER_METHOD_JS] }] + } + } + }); + const bidResponse = { adUnitId: 'au', requestId: 'req' }; + fireImpressionTrackers({ + eventtrackers: [ + { event: EVENT_TYPE_IMPRESSION, method: TRACKER_METHOD_IMG, url: 'img-url' }, + { event: EVENT_TYPE_IMPRESSION, method: TRACKER_METHOD_JS, url: 'js-url' } + ] + }, bidResponse, { runMarkup, fetchURL }); + sinon.assert.notCalled(fetchURL); + sinon.assert.calledWith(runMarkup, sinon.match('script async src="js-url"')); + }); + + it('should not fire any eventtrackers when request eventtrackers do not include impression', () => { + getMediaTypesStub.returns({ + native: { + ortb: { + eventtrackers: [{ event: 2, methods: [TRACKER_METHOD_IMG, TRACKER_METHOD_JS] }] + } + } + }); + const bidResponse = { adUnitId: 'au', requestId: 'req' }; + fireImpressionTrackers({ + eventtrackers: [ + { event: EVENT_TYPE_IMPRESSION, method: TRACKER_METHOD_IMG, url: 'imp-img-url' } + ] + }, bidResponse, { runMarkup, fetchURL }); + sinon.assert.notCalled(fetchURL); + sinon.assert.notCalled(runMarkup); + }); + + it('should still fire legacy imptrackers and jstracker when eventtrackers are filtered out', () => { + getMediaTypesStub.returns({ + native: { + ortb: { + eventtrackers: [] + } + } + }); + const bidResponse = { adUnitId: 'au', requestId: 'req' }; + fireImpressionTrackers({ + eventtrackers: [{ event: EVENT_TYPE_IMPRESSION, method: TRACKER_METHOD_IMG, url: 'from-eventtrackers' }], + imptrackers: ['legacy-imp-url'], + jstracker: 'legacy-js-markup' + }, bidResponse, { runMarkup, fetchURL }); + sinon.assert.calledOnceWithExactly(fetchURL, 'legacy-imp-url'); + sinon.assert.calledWith(runMarkup, 'legacy-js-markup'); + }); + + it('should use default allowed trackers when getMediaTypes returns empty', () => { + getMediaTypesStub.returns({}); + const bidResponse = { adUnitId: 'au', requestId: 'req' }; + fireImpressionTrackers({ + eventtrackers: [ + { event: EVENT_TYPE_IMPRESSION, method: TRACKER_METHOD_IMG, url: 'default-img' }, + { event: EVENT_TYPE_IMPRESSION, method: TRACKER_METHOD_JS, url: 'default-js' } + ] + }, bidResponse, { runMarkup, fetchURL }); + sinon.assert.calledWith(fetchURL, 'default-img'); + sinon.assert.calledWith(runMarkup, sinon.match('script async src="default-js"')); + }); + }); }) describe('fireClickTrackers', () => { From 34658565fb4e6a2165bb2f1fa28ebb320e448692 Mon Sep 17 00:00:00 2001 From: mkomorski Date: Fri, 27 Feb 2026 15:29:57 +0100 Subject: [PATCH 28/48] Prebid 11: gpt slots matching to ad units logic unification (#14480) * Promoting customSlotMatching to config * Update gptPreAuction.ts * Update gptPreAuction.ts * renaming --------- Co-authored-by: Patrick McCann --- libraries/gptUtils/gptUtils.js | 12 +++-- modules/bidViewability.js | 16 +++---- modules/bidViewability.md | 3 +- modules/gptPreAuction.ts | 19 +------- src/prebid.ts | 7 ++- src/targeting.ts | 11 +++-- src/utils.js | 4 +- test/spec/modules/bidViewability_spec.js | 56 ++++++++---------------- test/spec/modules/gptPreAuction_spec.js | 21 ++------- test/spec/unit/core/targeting_spec.js | 24 ++++++---- test/spec/unit/pbjs_api_spec.js | 19 ++++---- 11 files changed, 77 insertions(+), 115 deletions(-) diff --git a/libraries/gptUtils/gptUtils.js b/libraries/gptUtils/gptUtils.js index 17ca64483ab..21310ac7b5b 100644 --- a/libraries/gptUtils/gptUtils.js +++ b/libraries/gptUtils/gptUtils.js @@ -1,5 +1,5 @@ import { CLIENT_SECTIONS } from '../../src/fpd/oneClient.js'; -import {compareCodeAndSlot, deepAccess, isGptPubadsDefined, uniques, isEmpty} from '../../src/utils.js'; +import {deepAccess, isGptPubadsDefined, uniques, isEmpty, isAdUnitCodeMatchingSlot} from '../../src/utils.js'; const slotInfoCache = new Map(); @@ -13,7 +13,10 @@ export function clearSlotInfoCache() { * @return {function} filter function */ export function isSlotMatchingAdUnitCode(adUnitCode) { - return (slot) => compareCodeAndSlot(slot, adUnitCode); + return (slot) => { + const match = isAdUnitCodeMatchingSlot(slot); + return match(adUnitCode); + } } /** @@ -35,7 +38,10 @@ export function getGptSlotForAdUnitCode(adUnitCode) { let matchingSlot; if (isGptPubadsDefined()) { // find the first matching gpt slot on the page - matchingSlot = window.googletag.pubads().getSlots().find(isSlotMatchingAdUnitCode(adUnitCode)); + matchingSlot = window.googletag.pubads().getSlots().find(slot => { + const match = isAdUnitCodeMatchingSlot(slot); + return match(adUnitCode); + }); } return matchingSlot; } diff --git a/modules/bidViewability.js b/modules/bidViewability.js index f1acc6096cc..2c09c60748d 100644 --- a/modules/bidViewability.js +++ b/modules/bidViewability.js @@ -5,7 +5,7 @@ import {config} from '../src/config.js'; import * as events from '../src/events.js'; import {EVENTS} from '../src/constants.js'; -import {isFn, logWarn, triggerPixel} from '../src/utils.js'; +import {isAdUnitCodeMatchingSlot, logWarn, triggerPixel} from '../src/utils.js'; import {getGlobal} from '../src/prebidGlobal.js'; import adapterManager, {gppDataHandler, uspDataHandler} from '../src/adapterManager.js'; import {gdprParams} from '../libraries/dfpUtils/dfpUtils.js'; @@ -13,20 +13,14 @@ import {gdprParams} from '../libraries/dfpUtils/dfpUtils.js'; const MODULE_NAME = 'bidViewability'; const CONFIG_ENABLED = 'enabled'; const CONFIG_FIRE_PIXELS = 'firePixels'; -const CONFIG_CUSTOM_MATCH = 'customMatchFunction'; const BID_VURL_ARRAY = 'vurls'; const GPT_IMPRESSION_VIEWABLE_EVENT = 'impressionViewable'; -export const isBidAdUnitCodeMatchingSlot = (bid, slot) => { - return (slot.getAdUnitPath() === bid.adUnitCode || slot.getSlotElementId() === bid.adUnitCode); -} - -export const getMatchingWinningBidForGPTSlot = (globalModuleConfig, slot) => { +export const getMatchingWinningBidForGPTSlot = (slot) => { + const match = isAdUnitCodeMatchingSlot(slot); return getGlobal().getAllWinningBids().find( // supports custom match function from config - bid => isFn(globalModuleConfig[CONFIG_CUSTOM_MATCH]) - ? globalModuleConfig[CONFIG_CUSTOM_MATCH](bid, slot) - : isBidAdUnitCodeMatchingSlot(bid, slot) + ({ adUnitCode }) => match(adUnitCode) ) || null; }; @@ -63,7 +57,7 @@ export const logWinningBidNotFound = (slot) => { export const impressionViewableHandler = (globalModuleConfig, event) => { const slot = event.slot; - const respectiveBid = getMatchingWinningBidForGPTSlot(globalModuleConfig, slot); + const respectiveBid = getMatchingWinningBidForGPTSlot(slot); if (respectiveBid === null) { logWinningBidNotFound(slot); diff --git a/modules/bidViewability.md b/modules/bidViewability.md index 922a4a9def4..24f7dcd019e 100644 --- a/modules/bidViewability.md +++ b/modules/bidViewability.md @@ -12,7 +12,7 @@ Maintainer: harshad.mane@pubmatic.com - GPT API is used to find when a bid is viewable, https://developers.google.com/publisher-tag/reference#googletag.events.impressionviewableevent . This event is fired when an impression becomes viewable, according to the Active View criteria. Refer: https://support.google.com/admanager/answer/4524488 - This module does not work with any adserver's other than GAM with GPT integration -- Logic used to find a matching pbjs-bid for a GPT slot is ``` (slot.getAdUnitPath() === bid.adUnitCode || slot.getSlotElementId() === bid.adUnitCode) ``` this logic can be changed by using param ```customMatchFunction``` +- Logic used to find a matching pbjs-bid for a GPT slot is ``` (slot.getAdUnitPath() === bid.adUnitCode || slot.getSlotElementId() === bid.adUnitCode) ``` this logic can be changed by using config param ```customGptSlotMatching``` - When a rendered PBJS bid is viewable the module will trigger a BID_VIEWABLE event, which can be consumed by bidders and analytics adapters - If the viewable bid contains a ```vurls``` param containing URL's and the Bid Viewability module is configured with ``` firePixels: true ``` then the URLs mentioned in bid.vurls will be called. Please note that GDPR and USP related parameters will be added to the given URLs - This module is also compatible with Prebid core's billing deferral logic, this means that bids linked to an ad unit marked with `deferBilling: true` will trigger a bid adapter's `onBidBillable` function (if present) indicating an ad slot was viewed and also billing ready (if it were deferred). @@ -20,7 +20,6 @@ Refer: https://support.google.com/admanager/answer/4524488 # Params - enabled [required] [type: boolean, default: false], when set to true, the module will emit BID_VIEWABLE when applicable - firePixels [optional] [type: boolean], when set to true, will fire the urls mentioned in bid.vurls which should be array of urls -- customMatchFunction [optional] [type: function(bid, slot)], when passed this function will be used to `find` the matching winning bid for the GPT slot. Default value is ` (bid, slot) => (slot.getAdUnitPath() === bid.adUnitCode || slot.getSlotElementId() === bid.adUnitCode) ` # Example of consuming BID_VIEWABLE event ``` diff --git a/modules/gptPreAuction.ts b/modules/gptPreAuction.ts index db2978e1302..dedeb45202c 100644 --- a/modules/gptPreAuction.ts +++ b/modules/gptPreAuction.ts @@ -13,8 +13,6 @@ import { pick, uniques } from '../src/utils.js'; -import type {SlotMatchingFn} from '../src/targeting.ts'; -import type {AdUnitCode} from '../src/types/common.d.ts'; import type {AdUnit} from '../src/adUnits.ts'; const MODULE_NAME = 'GPT Pre-Auction'; @@ -66,8 +64,6 @@ export function getAuctionsIdsFromTargeting(targeting, am = auctionManager) { } export const appendGptSlots = adUnits => { - const { customGptSlotMatching } = _currentConfig; - if (!isGptPubadsDefined()) { return; } @@ -81,9 +77,7 @@ export const appendGptSlots = adUnits => { const adUnitPaths = {}; window.googletag.pubads().getSlots().forEach((slot: googletag.Slot) => { - const matchingAdUnitCode = Object.keys(adUnitMap).find(customGptSlotMatching - ? customGptSlotMatching(slot) - : isAdUnitCodeMatchingSlot(slot)); + const matchingAdUnitCode = Object.keys(adUnitMap).find(isAdUnitCodeMatchingSlot(slot)); if (matchingAdUnitCode) { const path = adUnitPaths[matchingAdUnitCode] = slot.getAdUnitPath(); @@ -174,16 +168,9 @@ type GPTPreAuctionConfig = { */ enabled?: boolean; /** - * If true, use default behavior for determining GPID and PbAdSlot. Defaults to false. + * If true, use default behavior for determining GPID. Defaults to false. */ useDefaultPreAuction?: boolean; - customGptSlotMatching?: SlotMatchingFn; - /** - * @param adUnitCode Ad unit code - * @param adServerAdSlot The value of that ad unit's `ortb2Imp.ext.data.adserver.adslot` - * @returns pbadslot for the ad unit - */ - customPbAdSlot?: (adUnitCode: AdUnitCode, adServerAdSlot: string) => string; /** * @param adUnit An ad unit object * @param adServerAdSlot The value of that ad unit's `ortb2Imp.ext.data.adserver.adslot` @@ -206,8 +193,6 @@ declare module '../src/config' { const handleSetGptConfig = moduleConfig => { _currentConfig = pick(moduleConfig, [ 'enabled', enabled => enabled !== false, - 'customGptSlotMatching', customGptSlotMatching => - typeof customGptSlotMatching === 'function' && customGptSlotMatching, 'customPreAuction', customPreAuction => typeof customPreAuction === 'function' && customPreAuction, 'useDefaultPreAuction', useDefaultPreAuction => useDefaultPreAuction ?? true, ]); diff --git a/src/prebid.ts b/src/prebid.ts index e662a0e178c..6b30ca192ca 100644 --- a/src/prebid.ts +++ b/src/prebid.ts @@ -28,7 +28,7 @@ import {listenMessagesFromCreative} from './secureCreatives.js'; import {userSync} from './userSync.js'; import {config} from './config.js'; import {auctionManager} from './auctionManager.js'; -import {isBidUsable, type SlotMatchingFn, targeting} from './targeting.js'; +import {isBidUsable, targeting} from './targeting.js'; import {hook, wrapHook} from './hook.js'; import {loadSession} from './debugging.js'; import {storageCallbacks} from './storageManager.js'; @@ -610,14 +610,13 @@ addApiMethod('getBidResponsesForAdUnitCode', getBidResponsesForAdUnitCode); /** * Set query string targeting on one or more GPT ad units. * @param adUnit a single `adUnit.code` or multiple. - * @param customSlotMatching gets a GoogleTag slot and returns a filter function for adUnitCode, so you can decide to match on either eg. return slot => { return adUnitCode => { return slot.getSlotElementId() === 'myFavoriteDivId'; } }; */ -function setTargetingForGPTAsync(adUnit?: AdUnitCode | AdUnitCode[], customSlotMatching?: SlotMatchingFn) { +function setTargetingForGPTAsync(adUnit?: AdUnitCode | AdUnitCode[]) { if (!isGptPubadsDefined()) { logError('window.googletag is not defined on the page'); return; } - targeting.setTargetingForGPT(adUnit, customSlotMatching); + targeting.setTargetingForGPT(adUnit); } addApiMethod('setTargetingForGPTAsync', setTargetingForGPTAsync); diff --git a/src/targeting.ts b/src/targeting.ts index 4837fd3b1b4..636c5d5787c 100644 --- a/src/targeting.ts +++ b/src/targeting.ts @@ -132,13 +132,12 @@ export function sortByDealAndPriceBucketOrCpm(useCpm = false) { * Return a map where each code in `adUnitCodes` maps to a list of GPT slots that match it. * * @param adUnitCodes - * @param customSlotMatching * @param getSlots */ -export function getGPTSlotsForAdUnits(adUnitCodes: AdUnitCode[], customSlotMatching, getSlots = () => window.googletag.pubads().getSlots()): ByAdUnit { +export function getGPTSlotsForAdUnits(adUnitCodes: AdUnitCode[], getSlots = () => window.googletag.pubads().getSlots()): ByAdUnit { return getSlots().reduce((auToSlots, slot) => { - const customMatch = isFn(customSlotMatching) && customSlotMatching(slot); - Object.keys(auToSlots).filter(isFn(customMatch) ? customMatch : isAdUnitCodeMatchingSlot(slot)).forEach(au => auToSlots[au].push(slot)); + Object.keys(auToSlots).filter(isAdUnitCodeMatchingSlot(slot)) + .forEach(au => auToSlots[au].push(slot)); return auToSlots; }, Object.fromEntries(adUnitCodes.map(au => [au, []]))); } @@ -305,13 +304,13 @@ export function newTargeting(auctionManager) { return flatTargeting; }, - setTargetingForGPT: hook('sync', function (adUnit?: AdUnitCode | AdUnitCode[], customSlotMatching?: SlotMatchingFn) { + setTargetingForGPT: hook('sync', function (adUnit?: AdUnitCode | AdUnitCode[]) { // get our ad unit codes const targetingSet: ByAdUnit = targeting.getAllTargeting(adUnit); const resetMap = Object.fromEntries(pbTargetingKeys.map(key => [key, null])); - Object.entries(getGPTSlotsForAdUnits(Object.keys(targetingSet), customSlotMatching)).forEach(([targetId, slots]) => { + Object.entries(getGPTSlotsForAdUnits(Object.keys(targetingSet))).forEach(([targetId, slots]) => { slots.forEach(slot => { // now set new targeting keys Object.keys(targetingSet[targetId]).forEach(key => { diff --git a/src/utils.js b/src/utils.js index fc36922bf6e..2fdb0a7fdaa 100644 --- a/src/utils.js +++ b/src/utils.js @@ -810,7 +810,9 @@ export const compareCodeAndSlot = (slot, adUnitCode) => slot.getAdUnitPath() === * @return filter function */ export function isAdUnitCodeMatchingSlot(slot) { - return (adUnitCode) => compareCodeAndSlot(slot, adUnitCode); + const customGptSlotMatching = config.getConfig('customGptSlotMatching'); + const match = isFn(customGptSlotMatching) && customGptSlotMatching(slot); + return isFn(match) ? match : (adUnitCode) => compareCodeAndSlot(slot, adUnitCode); } /** diff --git a/test/spec/modules/bidViewability_spec.js b/test/spec/modules/bidViewability_spec.js index e33e4a9687b..04858f261e7 100644 --- a/test/spec/modules/bidViewability_spec.js +++ b/test/spec/modules/bidViewability_spec.js @@ -55,22 +55,6 @@ describe('#bidViewability', function() { pbjsWinningBid = Object.assign({}, PBJS_WINNING_BID); }); - describe('isBidAdUnitCodeMatchingSlot', function() { - it('match found by GPT Slot getAdUnitPath', function() { - expect(bidViewability.isBidAdUnitCodeMatchingSlot(pbjsWinningBid, gptSlot)).to.equal(true); - }); - - it('match found by GPT Slot getSlotElementId', function() { - pbjsWinningBid.adUnitCode = 'DIV-1'; - expect(bidViewability.isBidAdUnitCodeMatchingSlot(pbjsWinningBid, gptSlot)).to.equal(true); - }); - - it('match not found', function() { - pbjsWinningBid.adUnitCode = 'DIV-10'; - expect(bidViewability.isBidAdUnitCodeMatchingSlot(pbjsWinningBid, gptSlot)).to.equal(false); - }); - }); - describe('getMatchingWinningBidForGPTSlot', function() { let winningBidsArray; let sandbox @@ -89,44 +73,40 @@ describe('#bidViewability', function() { sandbox.restore(); }) - it('should find a match by using customMatchFunction provided in config', function() { - // Needs config to be passed with customMatchFunction - const bidViewabilityConfig = { - customMatchFunction(bid, slot) { - return ('AD-' + slot.getAdUnitPath()) === bid.adUnitCode; + it('should find a match by using customGptSlotMatching provided in config', function() { + config.setConfig({ + customGptSlotMatching: slot => { + return (adUnitCode) => ('AD-' + slot.getAdUnitPath()) === adUnitCode; } - }; + }); const newWinningBid = Object.assign({}, PBJS_WINNING_BID, {adUnitCode: 'AD-' + PBJS_WINNING_BID.adUnitCode}); // Needs pbjs.getWinningBids to be implemented with match winningBidsArray.push(newWinningBid); - const wb = bidViewability.getMatchingWinningBidForGPTSlot(bidViewabilityConfig, gptSlot); + const wb = bidViewability.getMatchingWinningBidForGPTSlot(gptSlot); expect(wb).to.deep.equal(newWinningBid); + config.resetConfig(); }); - it('should NOT find a match by using customMatchFunction provided in config', function() { - // Needs config to be passed with customMatchFunction - const bidViewabilityConfig = { - customMatchFunction(bid, slot) { - return ('AD-' + slot.getAdUnitPath()) === bid.adUnitCode; - } - }; - // Needs pbjs.getWinningBids to be implemented without match; winningBidsArray is set to empty in beforeEach - const wb = bidViewability.getMatchingWinningBidForGPTSlot(bidViewabilityConfig, gptSlot); + it('should NOT find a match when customGptSlotMatching is set and no winning bid matches', function() { + config.setConfig({ + customGptSlotMatching: slot => (adUnitCode) => ('AD-' + slot.getAdUnitPath()) === adUnitCode + }); + // winningBidsArray is empty in beforeEach, so no bid matches + const wb = bidViewability.getMatchingWinningBidForGPTSlot(gptSlot); expect(wb).to.equal(null); + config.resetConfig(); }); it('should find a match by using default matching function', function() { - // Needs config to be passed without customMatchFunction - // Needs pbjs.getWinningBids to be implemented with match + // No customGptSlotMatching in config; pbjs.getWinningBids returns matching bid winningBidsArray.push(PBJS_WINNING_BID); - const wb = bidViewability.getMatchingWinningBidForGPTSlot({}, gptSlot); + const wb = bidViewability.getMatchingWinningBidForGPTSlot(gptSlot); expect(wb).to.deep.equal(PBJS_WINNING_BID); }); it('should NOT find a match by using default matching function', function() { - // Needs config to be passed without customMatchFunction - // Needs pbjs.getWinningBids to be implemented without match; winningBidsArray is set to empty in beforeEach - const wb = bidViewability.getMatchingWinningBidForGPTSlot({}, gptSlot); + // No customGptSlotMatching; winningBidsArray is empty in beforeEach + const wb = bidViewability.getMatchingWinningBidForGPTSlot(gptSlot); expect(wb).to.equal(null); }); }); diff --git a/test/spec/modules/gptPreAuction_spec.js b/test/spec/modules/gptPreAuction_spec.js index c369597ecbd..3ba49ede215 100644 --- a/test/spec/modules/gptPreAuction_spec.js +++ b/test/spec/modules/gptPreAuction_spec.js @@ -183,9 +183,8 @@ describe('GPT pre-auction module', () => { it('should use the customGptSlotMatching function if one is given', () => { config.setConfig({ - gptPreAuction: { - customGptSlotMatching: slot => - adUnitCode => adUnitCode.toUpperCase() === slot.getAdUnitPath().toUpperCase() + customGptSlotMatching: slot => { + return (adUnitCode) => adUnitCode.toUpperCase() === slot.getAdUnitPath().toUpperCase(); } }); @@ -194,6 +193,7 @@ describe('GPT pre-auction module', () => { appendGptSlots([adUnit]); expect(adUnit.ortb2Imp.ext.data.adserver).to.be.an('object'); expect(adUnit.ortb2Imp.ext.data.adserver).to.deep.equal({ name: 'gam', adslot: 'slotCode1' }); + config.resetConfig(); }); }); @@ -208,27 +208,14 @@ describe('GPT pre-auction module', () => { expect(_currentConfig).to.be.an('object').that.is.empty; }); - it('should accept custom functions in config', () => { - config.setConfig({ - gptPreAuction: { - customGptSlotMatching: () => 'customGptSlot', - } - }); - - expect(_currentConfig.enabled).to.equal(true); - expect(_currentConfig.customGptSlotMatching).to.a('function'); - expect(_currentConfig.customGptSlotMatching()).to.equal('customGptSlot'); - }); - it('should check that custom functions in config are type function', () => { config.setConfig({ gptPreAuction: { - customGptSlotMatching: 12345, + customPreAuction: 12345, } }); expect(_currentConfig).to.deep.equal({ enabled: true, - customGptSlotMatching: false, customPreAuction: false, useDefaultPreAuction: true }); diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 344229346c5..1f4d386a413 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -1641,22 +1641,22 @@ describe('targeting tests', function () { it('can find slots by ad unit path', () => { const paths = ['slot/1', 'slot/2'] - expect(getGPTSlotsForAdUnits(paths, null, () => slots)).to.eql({[paths[0]]: [slots[0], slots[2]], [paths[1]]: [slots[1]]}); + expect(getGPTSlotsForAdUnits(paths, () => slots)).to.eql({[paths[0]]: [slots[0], slots[2]], [paths[1]]: [slots[1]]}); }) it('can find slots by ad element ID', () => { const elementIds = ['div-1', 'div-2'] - expect(getGPTSlotsForAdUnits(elementIds, null, () => slots)).to.eql({[elementIds[0]]: [slots[0]], [elementIds[1]]: [slots[1]]}); + expect(getGPTSlotsForAdUnits(elementIds, () => slots)).to.eql({[elementIds[0]]: [slots[0]], [elementIds[1]]: [slots[1]]}); }) it('returns empty list on no match', () => { - expect(getGPTSlotsForAdUnits(['missing', 'slot/2'], null, () => slots)).to.eql({ + expect(getGPTSlotsForAdUnits(['missing', 'slot/2'], () => slots)).to.eql({ missing: [], 'slot/2': [slots[1]] }); }); - it('can use customSlotMatching resolving to ad unit codes', () => { + it('can use customGptSlotMatching resolving to ad unit codes', () => { const csm = (slot) => { if (slot.getAdUnitPath() === 'slot/1') { return (au) => { @@ -1664,13 +1664,17 @@ describe('targeting tests', function () { } } } - expect(getGPTSlotsForAdUnits(['div-2', 'custom'], csm, () => slots)).to.eql({ + config.setConfig({ + customGptSlotMatching: csm + }) + expect(getGPTSlotsForAdUnits(['div-2', 'custom'], () => slots)).to.eql({ 'custom': [slots[0], slots[2]], 'div-2': [slots[1]] }) + config.resetConfig(); }); - it('can use customSlotMatching resolving to elementIds', () => { + it('can use customGptSlotMatching resolving to elementIds', () => { const csm = (slot) => { if (slot.getSlotElementId() === 'div-1') { return (au) => { @@ -1678,14 +1682,18 @@ describe('targeting tests', function () { } } } - expect(getGPTSlotsForAdUnits(['div-2', 'custom'], csm, () => slots)).to.eql({ + config.setConfig({ + customGptSlotMatching: csm + }) + expect(getGPTSlotsForAdUnits(['div-2', 'custom'], () => slots)).to.eql({ 'custom': [slots[0]], 'div-2': [slots[1]] }) + config.resetConfig(); }); it('can handle repeated adUnitCodes', () => { - expect(getGPTSlotsForAdUnits(['div-1', 'div-1'], null, () => slots)).to.eql({ + expect(getGPTSlotsForAdUnits(['div-1', 'div-1'], () => slots)).to.eql({ 'div-1': [slots[0]] }) }) diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index dd16e6321ad..257b86f2992 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -1104,11 +1104,18 @@ describe('Unit: Prebid Module', function () { }); }); - it('should set googletag targeting keys to specific slot with customSlotMatching', function () { + it('should set googletag targeting keys to specific slot with customGptSlotMatching', function () { // same ad unit code but two differnt divs - // we make sure we can set targeting for a specific one with customSlotMatching + // we make sure we can set targeting for a specific one with customGptSlotMatching - pbjs.setConfig({ enableSendAllBids: false }); + pbjs.setConfig({ + enableSendAllBids: false, + customGptSlotMatching: (slot) => { + return (adUnitCode) => { + return slots[0].getSlotElementId() === slot.getSlotElementId(); + }; + } + }); var slots = createSlotArrayScenario2(); @@ -1116,11 +1123,7 @@ describe('Unit: Prebid Module', function () { slots[1].spySetTargeting.resetHistory(); window.googletag.pubads().setSlots(slots); pbjs.setConfig({ targetingControls: {allBidsCustomTargeting: true }}); - pbjs.setTargetingForGPTAsync([config.adUnitCodes[0]], (slot) => { - return (adUnitCode) => { - return slots[0].getSlotElementId() === slot.getSlotElementId(); - }; - }); + pbjs.setTargetingForGPTAsync([config.adUnitCodes[0]]); var expected = getTargetingKeys(); expect(slots[0].spySetTargeting.args).to.deep.contain.members(expected); From 18627fdedd6122622bdcbf48e03be0dc04723ca0 Mon Sep 17 00:00:00 2001 From: Matt Fitzgerald Date: Tue, 3 Mar 2026 11:03:36 -0600 Subject: [PATCH 29/48] Module: Remove dmd userid module (#14545) * Remove dmd userid module * Remove dmd userId module test coverage --------- Co-authored-by: mfitzgerald_dmd --- modules/.submodules.json | 1 - modules/dmdIdSystem.js | 104 -------------------------- modules/dmdIdSystem.md | 26 ------- modules/userId/userId.md | 10 --- test/spec/modules/dmdIdSystem_spec.js | 101 ------------------------- 5 files changed, 242 deletions(-) delete mode 100644 modules/dmdIdSystem.js delete mode 100644 modules/dmdIdSystem.md delete mode 100644 test/spec/modules/dmdIdSystem_spec.js diff --git a/modules/.submodules.json b/modules/.submodules.json index 50416bf3c4c..244104c93da 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -14,7 +14,6 @@ "czechAdIdSystem", "dacIdSystem", "deepintentDpesIdSystem", - "dmdIdSystem", "euidIdSystem", "fabrickIdSystem", "freepassIdSystem", diff --git a/modules/dmdIdSystem.js b/modules/dmdIdSystem.js deleted file mode 100644 index 4fc986bd1fc..00000000000 --- a/modules/dmdIdSystem.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * This module adds dmdId to the User ID module - * The {@link module:modules/userId} module is required - * @module modules/dmdIdSystem - * @requires module:modules/userId - */ - -import { logError, getWindowLocation } from '../src/utils.js'; -import { submodule } from '../src/hook.js'; -import { ajax } from '../src/ajax.js'; - -/** - * @typedef {import('../modules/userId/index.js').Submodule} Submodule - * @typedef {import('../modules/userId/index.js').SubmoduleConfig} SubmoduleConfig - * @typedef {import('../modules/userId/index.js').ConsentData} ConsentData - * @typedef {import('../modules/userId/index.js').IdResponse} IdResponse - */ - -const MODULE_NAME = 'dmdId'; - -/** @type {Submodule} */ -export const dmdIdSubmodule = { - /** - * used to link submodule with config - * @type {string} - */ - name: MODULE_NAME, - - /** - * decode the stored id value for passing to bid requests - * @function decode - * @param {(Object|string)} value - * @returns {(Object|undefined)} - */ - decode(value) { - return value && typeof value === 'string' - ? { 'dmdId': value } - : undefined; - }, - - /** - * performs action to obtain id and return a value in the callback's response argument - * @function getId - * @param {SubmoduleConfig} [config] - * @param {ConsentData} consentData - * @param {Object} cacheIdObj - existing id, if any - * @returns {IdResponse|undefined} - */ - getId(config, consentData, cacheIdObj) { - const configParams = (config && config.params) || {}; - if ( - !configParams || - !configParams.api_key || - typeof configParams.api_key !== 'string' - ) { - logError('dmd submodule requires an api_key.'); - return; - } - // If cahceIdObj is null or undefined - calling AIX-API - if (cacheIdObj) { - return cacheIdObj; - } else { - const url = configParams && configParams.api_url - ? configParams.api_url - : `https://aix.hcn.health/api/v1/auths`; - // Setting headers - const headers = {}; - headers['x-api-key'] = configParams.api_key; - headers['x-domain'] = getWindowLocation(); - // Response callbacks - const resp = function (callback) { - const callbacks = { - success: response => { - let responseObj; - let responseId; - try { - responseObj = JSON.parse(response); - if (responseObj && responseObj.dgid) { - responseId = responseObj.dgid; - } - } catch (error) { - logError(error); - } - callback(responseId); - }, - error: error => { - logError(`${MODULE_NAME}: ID fetch encountered an error`, error); - callback(); - } - }; - ajax(url, callbacks, undefined, { method: 'GET', withCredentials: true, customHeaders: headers }); - }; - return { callback: resp }; - } - }, - eids: { - 'dmdId': { - source: 'hcn.health', - atype: 3 - }, - } -}; - -submodule('userId', dmdIdSubmodule); diff --git a/modules/dmdIdSystem.md b/modules/dmdIdSystem.md deleted file mode 100644 index f2a5b76ade7..00000000000 --- a/modules/dmdIdSystem.md +++ /dev/null @@ -1,26 +0,0 @@ -pbjs.setConfig({ - userSync: { - userIds: [{ - name: 'dmdId', - storage: { - name: 'dmd-dgid', - type: 'cookie', - expires: 30 - }, - params: { - api_key: '3fdbe297-3690-4f5c-9e11-ee9186a6d77c', // provided by DMD - } - }] - } -}); - -#### DMD ID Configuration - -{: .table .table-bordered .table-striped } -| Param under userSync.userIds[] | Scope | Type | Description | Example | -| --- | --- | --- | --- | --- | -| name | Required | String | The name of Module | `"dmdId"` | -| storage | Required | Object | | -| storage.name | Required | String | `dmd-dgid` | -| params | Required | Object | Container of all module params. | | -| params.api_key | Required | String | This is your `api_key` as provided by DMD Marketing Corp. | `3fdbe297-3690-4f5c-9e11-ee9186a6d77c` | \ No newline at end of file diff --git a/modules/userId/userId.md b/modules/userId/userId.md index f7bea8fd9f8..328e23d96b0 100644 --- a/modules/userId/userId.md +++ b/modules/userId/userId.md @@ -26,16 +26,6 @@ pbjs.setConfig({ name: "_pubcid", expires: 60 } - }, { - name: 'dmdId', - storage: { - name: 'dmd-dgid', - type: 'cookie', - expires: 30 - }, - params: { - api_key: '3fdbe297-3690-4f5c-9e11-ee9186a6d77c', // provided by DMD - } }, { name: "unifiedId", params: { diff --git a/test/spec/modules/dmdIdSystem_spec.js b/test/spec/modules/dmdIdSystem_spec.js deleted file mode 100644 index d0d8747dee9..00000000000 --- a/test/spec/modules/dmdIdSystem_spec.js +++ /dev/null @@ -1,101 +0,0 @@ -import * as utils from '../../../src/utils.js'; -import { server } from 'test/mocks/xhr.js'; -import { dmdIdSubmodule } from 'modules/dmdIdSystem.js'; - -describe('Dmd ID System', function () { - let logErrorStub; - const config = { - params: { - api_key: '33344ffjddk22k22k222k22234k', - api_url: 'https://aix.hcn.health/api/v1/auths' - } - }; - - beforeEach(function () { - if (utils.logError.restore && utils.logError.restore.sinon) { - utils.logError.restore(); - } - logErrorStub = sinon.stub(utils, 'logError'); - }); - - afterEach(function () { - if (logErrorStub && logErrorStub.restore) { - logErrorStub.restore(); - } - }); - - it('should log an error if no configParams were passed into getId', function () { - dmdIdSubmodule.getId(); - expect(logErrorStub.calledOnce).to.be.true; - }); - - it('should log an error if configParams doesnot have api_key passed to getId', function () { - dmdIdSubmodule.getId({params: {}}); - expect(logErrorStub.calledOnce).to.be.true; - }); - - it('should log an error if configParams has invalid api_key passed into getId', function () { - dmdIdSubmodule.getId({params: {api_key: 123}}); - expect(logErrorStub.calledOnce).to.be.true; - }); - - it('should not log an error if configParams has valid api_key passed into getId', function () { - dmdIdSubmodule.getId({params: {api_key: '3fdbe297-3690-4f5c-9e11-ee9186a6d77c'}}); - expect(logErrorStub.calledOnce).to.be.false; - }); - - it('should return undefined if empty value passed into decode', function () { - expect(dmdIdSubmodule.decode()).to.be.undefined; - }); - - it('should return undefined if invalid dmd-dgid passed into decode', function () { - expect(dmdIdSubmodule.decode(123)).to.be.undefined; - }); - - it('should return dmdId if valid dmd-dgid passed into decode', function () { - const data = { 'dmdId': 'U12345' }; - expect(dmdIdSubmodule.decode('U12345')).to.deep.equal(data); - }); - - it('should return cacheObj if cacheObj is passed into getId', function () { - const data = { 'dmdId': 'U12345' }; - expect(dmdIdSubmodule.getId(config, {}, { cookie: 'dmd-dgid' })).to.deep.equal({ cookie: 'dmd-dgid' }); - expect(server.requests.length).to.eq(0); - }); - - it('Should invoke callback with response from API call', function () { - const callbackSpy = sinon.spy(); - const domain = utils.getWindowLocation().href; - const callback = dmdIdSubmodule.getId(config).callback; - callback(callbackSpy); - const request = server.requests[0]; - expect(request.method).to.eq('GET'); - expect(request.requestHeaders['x-domain']).to.be.eq(domain); - expect(request.url).to.eq(config.params.api_url); - request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ dgid: 'U12345' })); - expect(callbackSpy.lastCall.lastArg).to.deep.equal('U12345'); - }); - - it('Should log error if API response is not valid', function () { - const callbackSpy = sinon.spy(); - const domain = utils.getWindowLocation().href; - const callback = dmdIdSubmodule.getId(config).callback; - callback(callbackSpy); - const request = server.requests[0]; - expect(request.method).to.eq('GET'); - expect(request.requestHeaders['x-domain']).to.be.eq(domain); - expect(request.url).to.eq(config.params.api_url); - request.respond(400, { 'Content-Type': 'application/json' }, undefined); - expect(logErrorStub.calledOnce).to.be.true; - }); - - it('Should log error if API call throws error', function () { - const callbackSpy = sinon.spy(); - const callback = dmdIdSubmodule.getId(config).callback; - callback(callbackSpy); - const request = server.requests[0]; - expect(request.url).to.eq(config.params.api_url); - request.error(); - expect(logErrorStub.calledOnce).to.be.true; - }); -}); From 6ab1634ec227b5d1e1653c3bc54776f0c5462a71 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Mon, 9 Mar 2026 14:19:04 -0400 Subject: [PATCH 30/48] lint fix --- libraries/advangUtils/index.js | 2 +- modules/adagioBidAdapter.js | 2 +- modules/adkernelBidAdapter.js | 2 +- modules/adnuntiusAnalyticsAdapter.js | 2 +- modules/adotBidAdapter.js | 2 +- modules/adtrgtmeBidAdapter.js | 2 +- modules/adtrueBidAdapter.js | 58 +-- modules/alkimiBidAdapter.js | 24 +- modules/apacdexBidAdapter.js | 6 +- modules/appnexusBidAdapter.js | 37 +- modules/apstreamBidAdapter.js | 6 +- modules/axonixBidAdapter.js | 12 +- modules/beachfrontBidAdapter.js | 10 +- modules/bidViewability.js | 12 +- modules/bidViewabilityIO.js | 6 +- modules/bmtmBidAdapter.js | 2 +- modules/cadent_aperture_mxBidAdapter.js | 25 +- modules/chtnwBidAdapter.js | 6 +- modules/cointrafficBidAdapter.js | 2 +- modules/concertBidAdapter.js | 2 +- modules/connatixBidAdapter.js | 2 +- modules/connectadBidAdapter.js | 8 +- modules/criteoBidAdapter.js | 30 +- modules/cwireBidAdapter.js | 2 +- modules/debugging/bidInterceptor.js | 28 +- modules/debugging/debugging.js | 58 +-- modules/deepintentBidAdapter.js | 2 +- modules/digitalMatterBidAdapter.js | 22 +- modules/distroscaleBidAdapter.js | 8 +- modules/empowerBidAdapter.js | 2 +- modules/fanBidAdapter.js | 2 +- modules/gamoshiBidAdapter.js | 18 +- modules/gptPreAuction.ts | 8 +- modules/gumgumBidAdapter.js | 18 +- modules/h12mediaBidAdapter.js | 2 +- modules/hypelabBidAdapter.js | 2 +- modules/impactifyBidAdapter.js | 2 +- modules/ixBidAdapter.js | 9 +- modules/jixieBidAdapter.js | 24 +- modules/jwplayerBidAdapter.js | 2 +- modules/lemmaDigitalBidAdapter.js | 2 +- modules/livewrappedAnalyticsAdapter.js | 2 +- modules/luceadBidAdapter.js | 12 +- modules/marsmediaBidAdapter.js | 12 +- modules/mediaforceBidAdapter.js | 6 +- modules/mediafuseBidAdapter.js | 37 +- modules/mediakeysBidAdapter.js | 15 +- modules/medianetBidAdapter.js | 46 +-- modules/mgidBidAdapter.js | 16 +- modules/msftBidAdapter.js | 2 +- modules/nexverseBidAdapter.js | 12 +- modules/omsBidAdapter.js | 26 +- modules/onetagBidAdapter.js | 2 +- modules/onomagicBidAdapter.js | 20 +- modules/operaadsBidAdapter.js | 16 +- modules/ozoneBidAdapter.js | 72 ++-- modules/panxoBidAdapter.js | 2 +- modules/prebidServerBidAdapter/index.ts | 46 +-- modules/pubmaticBidAdapter.js | 2 +- modules/pubstackBidAdapter.ts | 2 +- modules/pwbidBidAdapter.js | 4 +- modules/rhythmoneBidAdapter.js | 4 +- modules/rubiconBidAdapter.js | 56 +-- modules/scaliburBidAdapter.js | 20 +- modules/seedtagBidAdapter.js | 2 +- modules/sharethroughBidAdapter.js | 2 +- modules/smaatoBidAdapter.js | 25 +- modules/smartxBidAdapter.js | 2 +- modules/snigelBidAdapter.js | 16 +- modules/sspBCBidAdapter.js | 16 +- modules/storageControl.ts | 26 +- modules/taboolaBidAdapter.js | 50 +-- modules/tappxBidAdapter.js | 6 +- modules/theAdxBidAdapter.js | 2 +- modules/ttdBidAdapter.js | 2 +- modules/ucfunnelBidAdapter.js | 10 +- modules/underdogmediaBidAdapter.js | 10 +- modules/undertoneBidAdapter.js | 10 +- modules/valuadBidAdapter.js | 8 +- modules/visxBidAdapter.js | 2 +- modules/widespaceBidAdapter.js | 2 +- modules/yandexBidAdapter.js | 2 +- modules/yieldmoBidAdapter.js | 2 +- src/adRendering.ts | 58 +-- src/adapters/bidderFactory.ts | 60 ++-- src/auction.ts | 70 ++-- src/fpd/enrichment.ts | 26 +- src/native.ts | 38 +- src/prebid.ts | 92 ++--- src/secureCreatives.js | 26 +- src/targeting.ts | 42 +-- src/utils/adUnits.ts | 6 +- .../libraries/placementPositionInfo_spec.js | 10 +- test/spec/libraries/storageDisclosure_spec.js | 8 +- test/spec/modules/33acrossIdSystem_spec.js | 4 +- test/spec/modules/adkernelBidAdapter_spec.js | 154 ++++---- test/spec/modules/bidViewability_spec.js | 16 +- test/spec/modules/concertBidAdapter_spec.js | 4 +- test/spec/modules/criteoBidAdapter_spec.js | 90 ++--- test/spec/modules/debugging_mod_spec.js | 186 +++++----- test/spec/modules/gamAdServerVideo_spec.js | 4 +- test/spec/modules/gumgumBidAdapter_spec.js | 10 +- test/spec/modules/ixBidAdapter_spec.js | 74 ++-- test/spec/modules/logicadBidAdapter_spec.js | 8 +- test/spec/modules/luceadBidAdapter_spec.js | 22 +- .../spec/modules/mediaforceBidAdapter_spec.js | 54 +-- test/spec/modules/mediafuseBidAdapter_spec.js | 100 +++--- test/spec/modules/medianetBidAdapter_spec.js | 26 +- test/spec/modules/mgidBidAdapter_spec.js | 158 ++++---- test/spec/modules/openxBidAdapter_spec.js | 182 +++++----- test/spec/modules/ozoneBidAdapter_spec.js | 285 +++++++-------- .../modules/prebidServerBidAdapter_spec.js | 336 +++++++++--------- test/spec/modules/pubmaticBidAdapter_spec.js | 8 +- test/spec/modules/smaatoBidAdapter_spec.js | 84 ++--- test/spec/modules/storageControl_spec.js | 4 +- .../spec/modules/tripleliftBidAdapter_spec.js | 46 +-- .../modules/twistDigitalBidAdapter_spec.js | 138 +++---- test/spec/modules/undertoneBidAdapter_spec.js | 34 +- test/spec/modules/vidazooBidAdapter_spec.js | 138 +++---- test/spec/modules/visxBidAdapter_spec.js | 234 ++++++------ test/spec/native_spec.js | 48 +-- test/spec/unit/core/bidderFactory_spec.js | 74 ++-- test/spec/unit/core/targeting_spec.js | 96 ++--- test/spec/unit/pbjs_api_spec.js | 235 ++++++------ test/spec/unit/secureCreatives_spec.js | 42 +-- test/spec/utils/adUnits_spec.js | 4 +- 126 files changed, 2230 insertions(+), 2202 deletions(-) diff --git a/libraries/advangUtils/index.js b/libraries/advangUtils/index.js index dc6463bf3dd..cf15c5025b5 100644 --- a/libraries/advangUtils/index.js +++ b/libraries/advangUtils/index.js @@ -1,6 +1,6 @@ import { generateUUID, isFn, parseSizesInput, parseUrl } from '../../src/utils.js'; import { config } from '../../src/config.js'; -import {getDNT} from '../dnt/index.js'; +import { getDNT } from '../dnt/index.js'; export const DEFAULT_MIMES = ['video/mp4', 'application/javascript']; diff --git a/modules/adagioBidAdapter.js b/modules/adagioBidAdapter.js index 6de60552a22..3da9746128b 100644 --- a/modules/adagioBidAdapter.js +++ b/modules/adagioBidAdapter.js @@ -25,7 +25,7 @@ import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { userSync } from '../src/userSync.js'; import { validateOrtbFields } from '../src/prebid.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'adagio'; const LOG_PREFIX = 'Adagio:'; diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 815a7553c86..3e22acb9f08 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -415,7 +415,7 @@ function makeDevice(fpd) { 'js': 1, 'language': getLanguage() }, fpd.device || {}); - return {device: device}; + return { device: device }; } /** diff --git a/modules/adnuntiusAnalyticsAdapter.js b/modules/adnuntiusAnalyticsAdapter.js index 91ee5c0fd43..a2fcc9018fd 100644 --- a/modules/adnuntiusAnalyticsAdapter.js +++ b/modules/adnuntiusAnalyticsAdapter.js @@ -3,7 +3,7 @@ import { ajax } from '../src/ajax.js'; import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js'; import { EVENTS } from '../src/constants.js'; import adapterManager from '../src/adapterManager.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const URL = 'https://analytics.adnuntius.com/prebid'; const REQUEST_SENT = 1; diff --git a/modules/adotBidAdapter.js b/modules/adotBidAdapter.js index 052be840333..6105463d0f3 100644 --- a/modules/adotBidAdapter.js +++ b/modules/adotBidAdapter.js @@ -7,7 +7,7 @@ import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { isArray, isBoolean, isFn, isPlainObject, isStr, logError, replaceAuctionPrice } from '../src/utils.js'; import { OUTSTREAM } from '../src/video.js'; import { NATIVE_ASSETS_IDS as NATIVE_ID_MAPPING, NATIVE_ASSETS as NATIVE_PLACEMENTS } from '../libraries/braveUtils/nativeAssets.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/adtrgtmeBidAdapter.js b/modules/adtrgtmeBidAdapter.js index 5e2319b85df..a4badd11a4c 100644 --- a/modules/adtrgtmeBidAdapter.js +++ b/modules/adtrgtmeBidAdapter.js @@ -11,7 +11,7 @@ import { } from '../src/utils.js'; import { config } from '../src/config.js'; import { hasPurpose1Consent } from '../src/utils/gdpr.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'adtrgtme'; const BIDDER_VERSION = '1.0.7'; diff --git a/modules/adtrueBidAdapter.js b/modules/adtrueBidAdapter.js index 0658788d52b..9fdb1c051c4 100644 --- a/modules/adtrueBidAdapter.js +++ b/modules/adtrueBidAdapter.js @@ -1,13 +1,13 @@ import { logWarn, isArray, inIframe, isNumber, isStr, deepClone, deepSetValue, logError, deepAccess, isBoolean } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {getStorageManager} from '../src/storageManager.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import { getStorageManager } from '../src/storageManager.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'adtrue'; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); +const storage = getStorageManager({ bidderCode: BIDDER_CODE }); const ADTRUE_CURRENCY = 'USD'; const ENDPOINT_URL = 'https://hb.adtrue.com/prebid/auction'; const LOG_WARN_PREFIX = 'AdTrue: '; @@ -50,28 +50,28 @@ const VIDEO_CUSTOM_PARAMS = { }; const NATIVE_ASSETS = { - 'TITLE': {ID: 1, KEY: 'title', TYPE: 0}, - 'IMAGE': {ID: 2, KEY: 'image', TYPE: 0}, - 'ICON': {ID: 3, KEY: 'icon', TYPE: 0}, - 'SPONSOREDBY': {ID: 4, KEY: 'sponsoredBy', TYPE: 1}, // please note that type of SPONSORED is also 1 - 'BODY': {ID: 5, KEY: 'body', TYPE: 2}, // please note that type of DESC is also set to 2 - 'CLICKURL': {ID: 6, KEY: 'clickUrl', TYPE: 0}, - 'VIDEO': {ID: 7, KEY: 'video', TYPE: 0}, - 'EXT': {ID: 8, KEY: 'ext', TYPE: 0}, - 'DATA': {ID: 9, KEY: 'data', TYPE: 0}, - 'LOGO': {ID: 10, KEY: 'logo', TYPE: 0}, - 'SPONSORED': {ID: 11, KEY: 'sponsored', TYPE: 1}, // please note that type of SPONSOREDBY is also set to 1 - 'DESC': {ID: 12, KEY: 'data', TYPE: 2}, // please note that type of BODY is also set to 2 - 'RATING': {ID: 13, KEY: 'rating', TYPE: 3}, - 'LIKES': {ID: 14, KEY: 'likes', TYPE: 4}, - 'DOWNLOADS': {ID: 15, KEY: 'downloads', TYPE: 5}, - 'PRICE': {ID: 16, KEY: 'price', TYPE: 6}, - 'SALEPRICE': {ID: 17, KEY: 'saleprice', TYPE: 7}, - 'PHONE': {ID: 18, KEY: 'phone', TYPE: 8}, - 'ADDRESS': {ID: 19, KEY: 'address', TYPE: 9}, - 'DESC2': {ID: 20, KEY: 'desc2', TYPE: 10}, - 'DISPLAYURL': {ID: 21, KEY: 'displayurl', TYPE: 11}, - 'CTA': {ID: 22, KEY: 'cta', TYPE: 12} + 'TITLE': { ID: 1, KEY: 'title', TYPE: 0 }, + 'IMAGE': { ID: 2, KEY: 'image', TYPE: 0 }, + 'ICON': { ID: 3, KEY: 'icon', TYPE: 0 }, + 'SPONSOREDBY': { ID: 4, KEY: 'sponsoredBy', TYPE: 1 }, // please note that type of SPONSORED is also 1 + 'BODY': { ID: 5, KEY: 'body', TYPE: 2 }, // please note that type of DESC is also set to 2 + 'CLICKURL': { ID: 6, KEY: 'clickUrl', TYPE: 0 }, + 'VIDEO': { ID: 7, KEY: 'video', TYPE: 0 }, + 'EXT': { ID: 8, KEY: 'ext', TYPE: 0 }, + 'DATA': { ID: 9, KEY: 'data', TYPE: 0 }, + 'LOGO': { ID: 10, KEY: 'logo', TYPE: 0 }, + 'SPONSORED': { ID: 11, KEY: 'sponsored', TYPE: 1 }, // please note that type of SPONSOREDBY is also set to 1 + 'DESC': { ID: 12, KEY: 'data', TYPE: 2 }, // please note that type of BODY is also set to 2 + 'RATING': { ID: 13, KEY: 'rating', TYPE: 3 }, + 'LIKES': { ID: 14, KEY: 'likes', TYPE: 4 }, + 'DOWNLOADS': { ID: 15, KEY: 'downloads', TYPE: 5 }, + 'PRICE': { ID: 16, KEY: 'price', TYPE: 6 }, + 'SALEPRICE': { ID: 17, KEY: 'saleprice', TYPE: 7 }, + 'PHONE': { ID: 18, KEY: 'phone', TYPE: 8 }, + 'ADDRESS': { ID: 19, KEY: 'address', TYPE: 9 }, + 'DESC2': { ID: 20, KEY: 'desc2', TYPE: 10 }, + 'DISPLAYURL': { ID: 21, KEY: 'displayurl', TYPE: 11 }, + 'CTA': { ID: 22, KEY: 'cta', TYPE: 12 } }; function _getDomainFromURL(url) { @@ -299,7 +299,7 @@ function _createBannerRequest(bid) { format = []; sizes.forEach(function (size) { if (size.length > 1) { - format.push({w: size[0], h: size[1]}); + format.push({ w: size[0], h: size[1] }); } }); if (format.length > 0) { diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index 8d923d26713..9611cd93521 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -1,16 +1,16 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {deepAccess, deepClone, generateUUID, replaceAuctionPrice} from '../src/utils.js'; -import {ajax} from '../src/ajax.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {VIDEO, BANNER} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { deepAccess, deepClone, generateUUID, replaceAuctionPrice } from '../src/utils.js'; +import { ajax } from '../src/ajax.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { VIDEO, BANNER } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'alkimi'; const GVLID = 1169; const USER_ID_KEY = 'alkimiUserID'; export const ENDPOINT = 'https://exchange.alkimi-onboarding.com/bid?prebid=true'; -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); +export const storage = getStorageManager({ bidderCode: BIDDER_CODE }); export const spec = { code: BIDDER_CODE, @@ -85,7 +85,7 @@ export const spec = { let payload = { requestId: generateUUID(), - signRequest: {bids, randomUUID: alkimiConfig && alkimiConfig.randomUUID}, + signRequest: { bids, randomUUID: alkimiConfig && alkimiConfig.randomUUID }, bidIds, referer: bidderRequest.refererInfo.page, signature: alkimiConfig && alkimiConfig.signature, @@ -148,7 +148,7 @@ export const spec = { return []; } - const {prebidResponse} = serverBody; + const { prebidResponse } = serverBody; if (!Array.isArray(prebidResponse)) { return []; } @@ -194,7 +194,7 @@ export const spec = { const urls = []; iframeList.forEach(url => { - urls.push({type: 'iframe', url}); + urls.push({ type: 'iframe', url }); }); return urls; @@ -204,7 +204,7 @@ export const spec = { }; function prepareSizes(sizes) { - return sizes ? sizes.map(size => ({width: size[0], height: size[1]})) : []; + return sizes ? sizes.map(size => ({ width: size[0], height: size[1] })) : []; } function prepareBidFloorSize(sizes) { diff --git a/modules/apacdexBidAdapter.js b/modules/apacdexBidAdapter.js index 0e669a8fdbc..e4d19055ce0 100644 --- a/modules/apacdexBidAdapter.js +++ b/modules/apacdexBidAdapter.js @@ -1,9 +1,9 @@ import { deepAccess, isPlainObject, isArray, replaceAuctionPrice, isFn, logError, deepClone } from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import {hasPurpose1Consent} from '../src/utils/gdpr.js'; -import {parseDomain} from '../src/refererDetection.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { hasPurpose1Consent } from '../src/utils/gdpr.js'; +import { parseDomain } from '../src/refererDetection.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'apacdex'; const ENDPOINT = 'https://useast.quantumdex.io/auction/pbjs' const USERSYNC = 'https://sync.quantumdex.io/usersync/pbjs' diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 5eb2a8a483e..cad4bd0c948 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -18,24 +18,24 @@ import { logWarn, mergeDeep } from '../src/utils.js'; -import {Renderer} from '../src/Renderer.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {INSTREAM, OUTSTREAM} from '../src/video.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {bidderSettings} from '../src/bidderSettings.js'; -import {hasPurpose1Consent} from '../src/utils/gdpr.js'; -import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; +import { Renderer } from '../src/Renderer.js'; +import { config } from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { INSTREAM, OUTSTREAM } from '../src/video.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { bidderSettings } from '../src/bidderSettings.js'; +import { hasPurpose1Consent } from '../src/utils/gdpr.js'; +import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { convertKeywordStringToANMap, getANKewyordParamFromMaps, getANKeywordParam } from '../libraries/appnexusUtils/anKeywords.js'; -import {convertCamelToUnderscore, appnexusAliases} from '../libraries/appnexusUtils/anUtils.js'; -import {convertTypes} from '../libraries/transformParamsUtils/convertTypes.js'; -import {chunk} from '../libraries/chunk/chunk.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { convertCamelToUnderscore, appnexusAliases } from '../libraries/appnexusUtils/anUtils.js'; +import { convertTypes } from '../libraries/transformParamsUtils/convertTypes.js'; +import { chunk } from '../libraries/chunk/chunk.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -99,7 +99,7 @@ const NATIVE_MAPPING = { const SOURCE = 'pbjs'; const MAX_IMPS_PER_REQUEST = 15; const GVLID = 32; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); +const storage = getStorageManager({ bidderCode: BIDDER_CODE }); // ORTB2 device types according to the OpenRTB specification const ORTB2_DEVICE_TYPE = { MOBILE_TABLET: 1, @@ -166,7 +166,7 @@ export const spec = { const segs = []; userObjBid.params.user[param].forEach(val => { if (isNumber(val)) { - segs.push({'id': val}); + segs.push({ 'id': val }); } else if (isPlainObject(val)) { segs.push(val); } @@ -351,7 +351,7 @@ export const spec = { bidRequests[0].userIdAsEids.forEach(eid => { if (!eid || !eid.uids || eid.uids.length < 1) { return; } eid.uids.forEach(uid => { - const tmp = {'source': eid.source, 'id': uid.id}; + const tmp = { 'source': eid.source, 'id': uid.id }; if (eid.source === 'adserver.org') { tmp.rti_partner = 'TDID'; } else if (eid.source === 'uidapi.com') { @@ -583,12 +583,13 @@ function newBid(serverBid, rtbBid, bidderRequest) { complete: 0, nodes: [{ bsid: rtbBid.buyer_member_id.toString() - }]}; + }] + }; return dchain; } if (rtbBid.buyer_member_id) { - bid.meta = Object.assign({}, bid.meta, {dchain: setupDChain(rtbBid)}); + bid.meta = Object.assign({}, bid.meta, { dchain: setupDChain(rtbBid) }); } if (rtbBid.brand_id) { diff --git a/modules/apstreamBidAdapter.js b/modules/apstreamBidAdapter.js index 64c91f60ab0..32c5f8242ec 100644 --- a/modules/apstreamBidAdapter.js +++ b/modules/apstreamBidAdapter.js @@ -4,14 +4,14 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const CONSTANTS = { DSU_KEY: 'apr_dsu', BIDDER_CODE: 'apstream', GVLID: 394 }; -const storage = getStorageManager({bidderCode: CONSTANTS.BIDDER_CODE}); +const storage = getStorageManager({ bidderCode: CONSTANTS.BIDDER_CODE }); var dsuModule = (function() { 'use strict'; @@ -19,7 +19,7 @@ var dsuModule = (function() { var DSU_KEY = 'apr_dsu'; var DSU_VERSION_NUMBER = '1'; var SIGNATURE_SALT = 'YicAu6ZpNG'; - var DSU_CREATOR = {'USERREPORT': '1'}; + var DSU_CREATOR = { 'USERREPORT': '1' }; function stringToU8(str) { if (typeof TextEncoder === 'function') { diff --git a/modules/axonixBidAdapter.js b/modules/axonixBidAdapter.js index e2177da2f4e..5c51167b63e 100644 --- a/modules/axonixBidAdapter.js +++ b/modules/axonixBidAdapter.js @@ -1,10 +1,10 @@ -import {deepAccess, isArray, isEmpty, logError, replaceAuctionPrice, triggerPixel} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {ajax} from '../src/ajax.js'; +import { deepAccess, isArray, isEmpty, logError, replaceAuctionPrice, triggerPixel } from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import { ajax } from '../src/ajax.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'axonix'; const BIDDER_VERSION = '1.0.2'; diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index e6e8074df76..f85c233e644 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -7,12 +7,12 @@ import { logWarn, formatQS } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {Renderer} from '../src/Renderer.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { Renderer } from '../src/Renderer.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { getFirstSize, getOsVersion, getVideoSizes, getBannerSizes, isConnectedTV, isMobile, isBannerBid, isVideoBid, getBannerBidFloor, getVideoBidFloor, getVideoTargetingParams, getTopWindowLocation } from '../libraries/advangUtils/index.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const ADAPTER_VERSION = '1.21'; const GVLID = 157; @@ -40,7 +40,7 @@ let appId = ''; export const spec = { code: 'beachfront', - supportedMediaTypes: [ VIDEO, BANNER ], + supportedMediaTypes: [VIDEO, BANNER], gvlid: GVLID, isBidRequestValid(bid) { if (isVideoBid(bid)) { diff --git a/modules/bidViewability.js b/modules/bidViewability.js index 2c09c60748d..d1a4640b991 100644 --- a/modules/bidViewability.js +++ b/modules/bidViewability.js @@ -2,13 +2,13 @@ // GPT API is used to find when a bid is viewable, https://developers.google.com/publisher-tag/reference#googletag.events.impressionviewableevent // Does not work with other than GPT integration -import {config} from '../src/config.js'; +import { config } from '../src/config.js'; import * as events from '../src/events.js'; -import {EVENTS} from '../src/constants.js'; -import {isAdUnitCodeMatchingSlot, logWarn, triggerPixel} from '../src/utils.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import adapterManager, {gppDataHandler, uspDataHandler} from '../src/adapterManager.js'; -import {gdprParams} from '../libraries/dfpUtils/dfpUtils.js'; +import { EVENTS } from '../src/constants.js'; +import { isAdUnitCodeMatchingSlot, logWarn, triggerPixel } from '../src/utils.js'; +import { getGlobal } from '../src/prebidGlobal.js'; +import adapterManager, { gppDataHandler, uspDataHandler } from '../src/adapterManager.js'; +import { gdprParams } from '../libraries/dfpUtils/dfpUtils.js'; const MODULE_NAME = 'bidViewability'; const CONFIG_ENABLED = 'enabled'; diff --git a/modules/bidViewabilityIO.js b/modules/bidViewabilityIO.js index 201a779bb32..5281c82f130 100644 --- a/modules/bidViewabilityIO.js +++ b/modules/bidViewabilityIO.js @@ -1,8 +1,8 @@ import { logMessage } from '../src/utils.js'; import { config } from '../src/config.js'; import * as events from '../src/events.js'; -import {EVENTS} from '../src/constants.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { EVENTS } from '../src/constants.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const MODULE_NAME = 'bidViewabilityIO'; const CONFIG_ENABLED = 'enabled'; @@ -78,7 +78,7 @@ export const init = () => { if (conf[MODULE_NAME][CONFIG_ENABLED] && CLIENT_SUPPORTS_IO) { // if the module is enabled and the browser supports Intersection Observer, // then listen to AD_RENDER_SUCCEEDED to setup IO's for supported mediaTypes - events.on(EVENTS.AD_RENDER_SUCCEEDED, ({doc, bid, id}) => { + events.on(EVENTS.AD_RENDER_SUCCEEDED, ({ doc, bid, id }) => { if (isSupportedMediaType(bid)) { const viewable = new IntersectionObserver(viewCallbackFactory(bid), getViewableOptions(bid)); const element = getAdUnitElement(bid); diff --git a/modules/bmtmBidAdapter.js b/modules/bmtmBidAdapter.js index a5af67e7512..a5663d35299 100644 --- a/modules/bmtmBidAdapter.js +++ b/modules/bmtmBidAdapter.js @@ -2,7 +2,7 @@ import { generateUUID, deepAccess, logWarn, deepSetValue, isPlainObject } from ' import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'bmtm'; const AD_URL = 'https://one.elitebidder.com/api/hb?sid='; diff --git a/modules/cadent_aperture_mxBidAdapter.js b/modules/cadent_aperture_mxBidAdapter.js index 4a16444553b..fa8a283b924 100644 --- a/modules/cadent_aperture_mxBidAdapter.js +++ b/modules/cadent_aperture_mxBidAdapter.js @@ -8,11 +8,11 @@ import { logError, logWarn } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {Renderer} from '../src/Renderer.js'; -import {parseDomain} from '../src/refererDetection.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { Renderer } from '../src/Renderer.js'; +import { parseDomain } from '../src/refererDetection.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'cadent_aperture_mx'; const ENDPOINT = 'hb.emxdgt.com'; @@ -20,10 +20,10 @@ const RENDERER_URL = 'https://js.brealtime.com/outstream/1.30.0/bundle.js'; const ADAPTER_VERSION = '1.5.1'; const DEFAULT_CUR = 'USD'; const ALIASES = [ - { code: 'emx_digital'}, - { code: 'cadent'}, - { code: 'emxdigital'}, - { code: 'cadentaperturemx'}, + { code: 'emx_digital' }, + { code: 'cadent' }, + { code: 'emxdigital' }, + { code: 'cadentaperturemx' }, ]; const EIDS_SUPPORTED = [ @@ -87,7 +87,8 @@ export const cadentAdapter = { h: screen.height, w: screen.width, devicetype: cadentAdapter.isMobile() ? 1 : cadentAdapter.isConnectedTV() ? 3 : 2, - language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage)}; + language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage) + }; }, cleanProtocols: (video) => { if (video.protocols && video.protocols.includes(7)) { @@ -173,7 +174,7 @@ export const cadentAdapter = { getGpp: (bidRequest, cadentData) => { if (bidRequest.gppConsent) { - const {gppString: gpp, applicableSections: gppSid} = bidRequest.gppConsent; + const { gppString: gpp, applicableSections: gppSid } = bidRequest.gppConsent; if (cadentData.regs) { cadentData.regs.gpp = gpp; cadentData.regs.gpp_sid = gppSid; @@ -315,7 +316,7 @@ export const spec = { cadentData.user.ext.eids = eids; } else { cadentData.user = { - ext: {eids} + ext: { eids } }; } } diff --git a/modules/chtnwBidAdapter.js b/modules/chtnwBidAdapter.js index 4c904e79596..920c4670b84 100644 --- a/modules/chtnwBidAdapter.js +++ b/modules/chtnwBidAdapter.js @@ -8,12 +8,12 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { getStorageManager } from '../src/storageManager.js'; import { ajax } from '../src/ajax.js'; -import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js'; +import { getDNT } from '../libraries/dnt/index.js'; const ENDPOINT_URL = 'https://prebid.cht.hinet.net/api/v1'; const BIDDER_CODE = 'chtnw'; const COOKIE_NAME = '__htid'; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); +const storage = getStorageManager({ bidderCode: BIDDER_CODE }); const { getConfig } = config; diff --git a/modules/cointrafficBidAdapter.js b/modules/cointrafficBidAdapter.js index 60a3ffdf7da..93c031dcdf7 100644 --- a/modules/cointrafficBidAdapter.js +++ b/modules/cointrafficBidAdapter.js @@ -4,7 +4,7 @@ import { BANNER } from '../src/mediaTypes.js' import { config } from '../src/config.js' import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js'; import { getViewportSize } from '../libraries/viewport/viewport.js' -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/concertBidAdapter.js b/modules/concertBidAdapter.js index 0af69b71f32..e9d463ca937 100644 --- a/modules/concertBidAdapter.js +++ b/modules/concertBidAdapter.js @@ -4,7 +4,7 @@ import { getStorageManager } from '../src/storageManager.js'; import { hasPurpose1Consent } from '../src/utils/gdpr.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index 0c5451e713b..a40d497eb6f 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -25,7 +25,7 @@ import { BANNER, VIDEO, } from '../src/mediaTypes.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'connatix'; diff --git a/modules/connectadBidAdapter.js b/modules/connectadBidAdapter.js index 459c27ea756..d1fec831b50 100644 --- a/modules/connectadBidAdapter.js +++ b/modules/connectadBidAdapter.js @@ -1,9 +1,9 @@ import { deepAccess, deepSetValue, mergeDeep, logWarn, generateUUID } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js' -import {config} from '../src/config.js'; -import {tryAppendQueryString} from '../libraries/urlUtils/urlUtils.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { config } from '../src/config.js'; +import { tryAppendQueryString } from '../libraries/urlUtils/urlUtils.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'connectad'; const BIDDER_CODE_ALIAS = 'connectadrealtime'; @@ -13,7 +13,7 @@ const SUPPORTED_MEDIA_TYPES = [BANNER]; export const spec = { code: BIDDER_CODE, gvlid: 138, - aliases: [ BIDDER_CODE_ALIAS ], + aliases: [BIDDER_CODE_ALIAS], supportedMediaTypes: SUPPORTED_MEDIA_TYPES, isBidRequestValid: function(bid) { diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 46b1e5d75a0..56fc19ef7be 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -1,15 +1,15 @@ -import {deepAccess, deepSetValue, logError, logInfo, logWarn, parseUrl, triggerPixel} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import {hasPurpose1Consent} from '../src/utils/gdpr.js'; -import {Renderer} from '../src/Renderer.js'; -import {OUTSTREAM} from '../src/video.js'; -import {ajax} from '../src/ajax.js'; -import {ortbConverter} from '../libraries/ortbConverter/converter.js'; -import {ortb25Translator} from '../libraries/ortb2.5Translator/translator.js'; -import {config} from '../src/config.js'; +import { deepAccess, deepSetValue, logError, logInfo, logWarn, parseUrl, triggerPixel } from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { getRefererInfo } from '../src/refererDetection.js'; +import { hasPurpose1Consent } from '../src/utils/gdpr.js'; +import { Renderer } from '../src/Renderer.js'; +import { OUTSTREAM } from '../src/video.js'; +import { ajax } from '../src/ajax.js'; +import { ortbConverter } from '../libraries/ortbConverter/converter.js'; +import { ortb25Translator } from '../libraries/ortb2.5Translator/translator.js'; +import { config } from '../src/config.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -161,7 +161,7 @@ function bidResponse(buildBidResponse, bid, context) { } const bidResponse = buildBidResponse(bid, context); - const {bidRequest} = context; + const { bidRequest } = context; bidResponse.currency = bid?.ext?.cur; @@ -370,7 +370,7 @@ export const spec = { const context = buildContext(bidRequests, bidderRequest); const url = buildCdbUrl(context); - const data = CONVERTER.toORTB({bidderRequest, bidRequests, context}); + const data = CONVERTER.toORTB({ bidderRequest, bidRequests, context }); if (data) { return { @@ -395,7 +395,7 @@ export const spec = { return []; // no bid } - const interpretedResponse = CONVERTER.fromORTB({response: response.body, request: request.data}); + const interpretedResponse = CONVERTER.fromORTB({ response: response.body, request: request.data }); return interpretedResponse.bids || []; }, diff --git a/modules/cwireBidAdapter.js b/modules/cwireBidAdapter.js index ccf6697987b..46647b31c58 100644 --- a/modules/cwireBidAdapter.js +++ b/modules/cwireBidAdapter.js @@ -11,7 +11,7 @@ import { getBoundingClientRect } from "../libraries/boundingClientRect/boundingC import { hasPurpose1Consent } from "../src/utils/gdpr.js"; import { sendBeacon } from "../src/ajax.js"; import { isAutoplayEnabled } from "../libraries/autoplayDetection/autoplay.js"; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/debugging/bidInterceptor.js b/modules/debugging/bidInterceptor.js index 4acf543764c..afd644684d7 100644 --- a/modules/debugging/bidInterceptor.js +++ b/modules/debugging/bidInterceptor.js @@ -4,11 +4,11 @@ import makeResponseResolvers from './responses.js'; * @typedef {Number|String|boolean|null|undefined} Scalar */ -export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { - const {deepAccess, deepClone, delayExecution, hasNonSerializableProperty, mergeDeep} = utils; - const responseResolvers = makeResponseResolvers({Renderer, BANNER, NATIVE, VIDEO}); +export function makebidInterceptor({ utils, BANNER, NATIVE, VIDEO, Renderer }) { + const { deepAccess, deepClone, delayExecution, hasNonSerializableProperty, mergeDeep } = utils; + const responseResolvers = makeResponseResolvers({ Renderer, BANNER, NATIVE, VIDEO }); function BidInterceptor(opts = {}) { - ({setTimeout: this.setTimeout = window.setTimeout.bind(window)} = opts); + ({ setTimeout: this.setTimeout = window.setTimeout.bind(window) } = opts); this.logger = opts.logger; this.rules = []; } @@ -77,7 +77,7 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { this.logger.logError(`Invalid 'when' definition for debug bid interceptor (in rule #${ruleNo})`); return () => false; } - function matches(candidate, {ref = matchDef, args = []}) { + function matches(candidate, { ref = matchDef, args = [] }) { return Object.entries(ref).map(([key, val]) => { const cVal = candidate[key]; if (val instanceof RegExp) { @@ -87,12 +87,12 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { return !!val(cVal, ...args); } if (typeof val === 'object') { - return matches(cVal, {ref: val, args}); + return matches(cVal, { ref: val, args }); } return cVal === val; }).every((i) => i); } - return (candidate, ...args) => matches(candidate, {args}); + return (candidate, ...args) => matches(candidate, { args }); }, /** * @typedef {Function} ReplacerFn @@ -115,18 +115,18 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { replDef = replDef || {}; let replFn; if (typeof replDef === 'function') { - replFn = ({args}) => replDef(...args); + replFn = ({ args }) => replDef(...args); } else if (typeof replDef !== 'object') { this.logger.logError(`Invalid 'then' definition for debug bid interceptor (in rule #${ruleNo})`); replFn = () => ({}); } else { - replFn = ({args, ref = replDef}) => { + replFn = ({ args, ref = replDef }) => { const result = Array.isArray(ref) ? [] : {}; Object.entries(ref).forEach(([key, val]) => { if (typeof val === 'function') { result[key] = val(...args); } else if (val != null && typeof val === 'object') { - result[key] = replFn({args, ref: val}) + result[key] = replFn({ args, ref: val }) } else { result[key] = val; } @@ -136,7 +136,7 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { } return (bid, ...args) => { const response = this.responseDefaults(bid); - mergeDeep(response, replFn({args: [bid, ...args]})); + mergeDeep(response, replFn({ args: [bid, ...args] })); const resolver = responseResolvers[response.mediaType]; resolver && resolver(bid, response); response.isDebug = true; @@ -191,7 +191,7 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { bids.forEach((bid) => { const rule = this.match(bid, bidRequest); if (rule != null) { - matches.push({rule: rule, bid: bid}); + matches.push({ rule: rule, bid: bid }); } else { remainder.push(bid); } @@ -209,7 +209,7 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { * returns {{bids: {}[], bidRequest: {}} remaining bids that did not match any rule (this applies also to * bidRequest.bids) */ - intercept({bids, bidRequest, addBid, done}) { + intercept({ bids, bidRequest, addBid, done }) { if (bids == null) { bids = bidRequest.bids; } @@ -230,7 +230,7 @@ export function makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}) { } else { this.setTimeout(done, 0); } - return {bids, bidRequest}; + return { bids, bidRequest }; } }); return BidInterceptor; diff --git a/modules/debugging/debugging.js b/modules/debugging/debugging.js index 1db564ceb95..022d901264d 100644 --- a/modules/debugging/debugging.js +++ b/modules/debugging/debugging.js @@ -1,29 +1,29 @@ -import {makebidInterceptor} from './bidInterceptor.js'; -import {makePbsInterceptor} from './pbsInterceptor.js'; -import {addHooks, removeHooks} from './legacy.js'; +import { makebidInterceptor } from './bidInterceptor.js'; +import { makePbsInterceptor } from './pbsInterceptor.js'; +import { addHooks, removeHooks } from './legacy.js'; const interceptorHooks = []; let bidInterceptor; let enabled = false; -function enableDebugging(debugConfig, {fromSession = false, config, hook, logger}) { - config.setConfig({debug: true}); +function enableDebugging(debugConfig, { fromSession = false, config, hook, logger }) { + config.setConfig({ debug: true }); bidInterceptor.updateConfig(debugConfig); resetHooks(true); // also enable "legacy" overrides - removeHooks({hook}); - addHooks(debugConfig, {hook, logger}); + removeHooks({ hook }); + addHooks(debugConfig, { hook, logger }); if (!enabled) { enabled = true; logger.logMessage(`Debug overrides enabled${fromSession ? ' from session' : ''}`); } } -export function disableDebugging({hook, logger}) { +export function disableDebugging({ hook, logger }) { bidInterceptor.updateConfig(({})); resetHooks(false); // also disable "legacy" overrides - removeHooks({hook}); + removeHooks({ hook }); if (enabled) { enabled = false; logger.logMessage('Debug overrides disabled'); @@ -31,8 +31,8 @@ export function disableDebugging({hook, logger}) { } // eslint-disable-next-line no-restricted-properties -function saveDebuggingConfig(debugConfig, {sessionStorage = window.sessionStorage, DEBUG_KEY, utils} = {}) { - const {deepClone} = utils; +function saveDebuggingConfig(debugConfig, { sessionStorage = window.sessionStorage, DEBUG_KEY, utils } = {}) { + const { deepClone } = utils; if (!debugConfig.enabled) { try { sessionStorage.removeItem(DEBUG_KEY); @@ -51,7 +51,7 @@ function saveDebuggingConfig(debugConfig, {sessionStorage = window.sessionStorag } // eslint-disable-next-line no-restricted-properties -export function getConfig(debugging, {getStorage = () => window.sessionStorage, DEBUG_KEY, config, hook, logger, utils} = {}) { +export function getConfig(debugging, { getStorage = () => window.sessionStorage, DEBUG_KEY, config, hook, logger, utils } = {}) { if (debugging == null) return; let sessionStorage; try { @@ -60,16 +60,16 @@ export function getConfig(debugging, {getStorage = () => window.sessionStorage, logger.logError(`sessionStorage is not available: debugging configuration will not persist on page reload`, e); } if (sessionStorage != null) { - saveDebuggingConfig(debugging, {sessionStorage, DEBUG_KEY, utils}); + saveDebuggingConfig(debugging, { sessionStorage, DEBUG_KEY, utils }); } if (!debugging.enabled) { - disableDebugging({hook, logger}); + disableDebugging({ hook, logger }); } else { - enableDebugging(debugging, {config, hook, logger}); + enableDebugging(debugging, { config, hook, logger }); } } -export function sessionLoader({DEBUG_KEY, storage, config, hook, logger}) { +export function sessionLoader({ DEBUG_KEY, storage, config, hook, logger }) { let overrides; try { // eslint-disable-next-line no-restricted-properties @@ -78,13 +78,13 @@ export function sessionLoader({DEBUG_KEY, storage, config, hook, logger}) { } catch (e) { } if (overrides) { - enableDebugging(overrides, {fromSession: true, config, hook, logger}); + enableDebugging(overrides, { fromSession: true, config, hook, logger }); } } function resetHooks(enable) { interceptorHooks.forEach(([getHookFn, interceptor]) => { - getHookFn().getHooks({hook: interceptor}).remove(); + getHookFn().getHooks({ hook: interceptor }).remove(); }); if (enable) { interceptorHooks.forEach(([getHookFn, interceptor]) => { @@ -100,11 +100,11 @@ function registerBidInterceptor(getHookFn, interceptor) { }]); } -export function makeBidderBidInterceptor({utils}) { - const {delayExecution} = utils; +export function makeBidderBidInterceptor({ utils }) { + const { delayExecution } = utils; return function bidderBidInterceptor(next, interceptBids, spec, bids, bidRequest, ajax, wrapCallback, cbs) { const done = delayExecution(cbs.onCompletion, 2); - ({bids, bidRequest} = interceptBids({ + ({ bids, bidRequest } = interceptBids({ bids, bidRequest, addBid: wrapCallback(cbs.onBid), @@ -114,17 +114,17 @@ export function makeBidderBidInterceptor({utils}) { cbs.onResponse?.({}); // trigger onResponse so that the bidder may be marked as "timely" if necessary done(); } else { - next(spec, bids, bidRequest, ajax, wrapCallback, {...cbs, onCompletion: done}); + next(spec, bids, bidRequest, ajax, wrapCallback, { ...cbs, onCompletion: done }); } } } -export function install({DEBUG_KEY, config, hook, createBid, logger, utils, BANNER, NATIVE, VIDEO, Renderer}) { - const BidInterceptor = makebidInterceptor({utils, BANNER, NATIVE, VIDEO, Renderer}); - bidInterceptor = new BidInterceptor({logger}); - const pbsBidInterceptor = makePbsInterceptor({createBid, utils}); - registerBidInterceptor(() => hook.get('processBidderRequests'), makeBidderBidInterceptor({utils})); +export function install({ DEBUG_KEY, config, hook, createBid, logger, utils, BANNER, NATIVE, VIDEO, Renderer }) { + const BidInterceptor = makebidInterceptor({ utils, BANNER, NATIVE, VIDEO, Renderer }); + bidInterceptor = new BidInterceptor({ logger }); + const pbsBidInterceptor = makePbsInterceptor({ createBid, utils }); + registerBidInterceptor(() => hook.get('processBidderRequests'), makeBidderBidInterceptor({ utils })); registerBidInterceptor(() => hook.get('processPBSRequest'), pbsBidInterceptor); - sessionLoader({DEBUG_KEY, config, hook, logger}); - config.getConfig('debugging', ({debugging}) => getConfig(debugging, {DEBUG_KEY, config, hook, logger, utils}), {init: true}); + sessionLoader({ DEBUG_KEY, config, hook, logger }); + config.getConfig('debugging', ({ debugging }) => getConfig(debugging, { DEBUG_KEY, config, hook, logger, utils }), { init: true }); } diff --git a/modules/deepintentBidAdapter.js b/modules/deepintentBidAdapter.js index eabcc036cca..09635b63d0e 100644 --- a/modules/deepintentBidAdapter.js +++ b/modules/deepintentBidAdapter.js @@ -3,7 +3,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { COMMON_ORTB_VIDEO_PARAMS, formatResponse } from '../libraries/deepintentUtils/index.js'; import { addDealCustomTargetings, addPMPDeals } from '../libraries/dealUtils/dealUtils.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const LOG_WARN_PREFIX = 'DeepIntent: '; const BIDDER_CODE = 'deepintent'; diff --git a/modules/digitalMatterBidAdapter.js b/modules/digitalMatterBidAdapter.js index c0f972d9a3b..0c56118dc71 100644 --- a/modules/digitalMatterBidAdapter.js +++ b/modules/digitalMatterBidAdapter.js @@ -1,9 +1,9 @@ -import {deepAccess, deepSetValue, getWinDimensions, inIframe, logWarn, parseSizesInput} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER} from '../src/mediaTypes.js'; -import {hasPurpose1Consent} from '../src/utils/gdpr.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { deepAccess, deepSetValue, getWinDimensions, inIframe, logWarn, parseSizesInput } from '../src/utils.js'; +import { config } from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER } from '../src/mediaTypes.js'; +import { hasPurpose1Consent } from '../src/utils/gdpr.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'digitalMatter'; const GVLID = 1345; @@ -30,7 +30,7 @@ export const spec = { const common = bidderRequest.ortb2 || {}; const site = common.site; const tid = common?.source?.tid; - const {user} = common || {}; + const { user } = common || {}; if (!site.page) { site.page = bidderRequest.refererInfo.page; @@ -43,7 +43,7 @@ export const spec = { const cur = currency && [currency]; const imp = validBidRequests.map((bid, id) => { - const {accountId, siteId} = bid.params; + const { accountId, siteId } = bid.params; const bannerParams = deepAccess(bid, 'mediaTypes.banner'); const position = deepAccess(bid, 'mediaTypes.banner.pos') ?? 0; @@ -110,7 +110,7 @@ export const spec = { }, interpretResponse: function (serverResponse) { const body = serverResponse.body || serverResponse; - const {cur} = body; + const { cur } = body; const bids = []; if (body && body.bids && Array.isArray(body.bids)) { @@ -162,9 +162,9 @@ export const spec = { if (url) { if ((type === 'image' || type === 'redirect') && syncOptions.pixelEnabled) { - userSyncs.push({type: 'image', url: url}); + userSyncs.push({ type: 'image', url: url }); } else if (type === 'iframe' && syncOptions.iframeEnabled) { - userSyncs.push({type: 'iframe', url: url}); + userSyncs.push({ type: 'iframe', url: url }); } } }) diff --git a/modules/distroscaleBidAdapter.js b/modules/distroscaleBidAdapter.js index cb7f5636fbd..a2eea9e9130 100644 --- a/modules/distroscaleBidAdapter.js +++ b/modules/distroscaleBidAdapter.js @@ -2,7 +2,7 @@ import { logWarn, isPlainObject, isStr, isArray, isFn, inIframe, mergeDeep, deep import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER } from '../src/mediaTypes.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'distroscale'; const SHORT_CODE = 'ds'; const LOG_WARN_PREFIX = 'DistroScale: '; @@ -12,7 +12,7 @@ const AUCTION_TYPE = 1; const GVLID = 754; const UNDEF = undefined; -const SUPPORTED_MEDIATYPES = [ BANNER ]; +const SUPPORTED_MEDIATYPES = [BANNER]; function _getHost(url) { const a = document.createElement('a'); @@ -222,10 +222,10 @@ export const spec = { // First Party Data const commonFpd = bidderRequest.ortb2 || {}; if (commonFpd.site) { - mergeDeep(payload, {site: commonFpd.site}); + mergeDeep(payload, { site: commonFpd.site }); } if (commonFpd.user) { - mergeDeep(payload, {user: commonFpd.user}); + mergeDeep(payload, { user: commonFpd.user }); } // User IDs diff --git a/modules/empowerBidAdapter.js b/modules/empowerBidAdapter.js index fb8d7d2b620..919305f5519 100644 --- a/modules/empowerBidAdapter.js +++ b/modules/empowerBidAdapter.js @@ -13,7 +13,7 @@ import { registerBidder } from "../src/adapters/bidderFactory.js"; import { config } from "../src/config.js"; import { VIDEO, BANNER } from "../src/mediaTypes.js"; import { getConnectionType } from "../libraries/connectionInfo/connectionUtils.js"; -import {getDNT} from "../libraries/dnt/index.js"; +import { getDNT } from "../libraries/dnt/index.js"; export const ENDPOINT = "https://bid.virgul.com/prebid"; diff --git a/modules/fanBidAdapter.js b/modules/fanBidAdapter.js index b73208b3483..a3690cd6098 100644 --- a/modules/fanBidAdapter.js +++ b/modules/fanBidAdapter.js @@ -6,7 +6,7 @@ import { getBidFloor } from '../libraries/currencyUtils/floor.js'; import { getStorageManager } from '../src/storageManager.js'; import { Renderer } from '../src/Renderer.js'; import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'freedomadnetwork'; const BIDDER_VERSION = '0.2.0'; diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index d4d6c888057..f1ae1d1aab4 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -10,13 +10,13 @@ import { logWarn, mergeDeep } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {Renderer} from '../src/Renderer.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {ortbConverter} from '../libraries/ortbConverter/converter.js'; -import {ortb25Translator} from '../libraries/ortb2.5Translator/translator.js'; -import {getCurrencyFromBidderRequest} from '../libraries/ortb2Utils/currency.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { Renderer } from '../src/Renderer.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { ortbConverter } from '../libraries/ortbConverter/converter.js'; +import { ortb25Translator } from '../libraries/ortb2.5Translator/translator.js'; +import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const ENDPOINTS = { 'gamoshi': 'https://rtb.gamoshi.io', 'cleanmedianet': 'https://bidder.cleanmediaads.com' @@ -209,7 +209,7 @@ export const spec = { bidResponse.ext['utrk'] .forEach(pixel => { const url = helper.replaceMacros(pixel.url, params); - syncs.push({type: pixel.type, url}); + syncs.push({ type: pixel.type, url }); }); } if (Array.isArray(bidResponse.seatbid)) { @@ -220,7 +220,7 @@ export const spec = { bid.ext['utrk'] .forEach(pixel => { const url = helper.replaceMacros(pixel.url, params); - syncs.push({type: pixel.type, url}); + syncs.push({ type: pixel.type, url }); }); } }); diff --git a/modules/gptPreAuction.ts b/modules/gptPreAuction.ts index dedeb45202c..5bfb9d243a0 100644 --- a/modules/gptPreAuction.ts +++ b/modules/gptPreAuction.ts @@ -13,7 +13,7 @@ import { pick, uniques } from '../src/utils.js'; -import type {AdUnit} from '../src/adUnits.ts'; +import type { AdUnit } from '../src/adUnits.ts'; const MODULE_NAME = 'GPT Pre-Auction'; export let _currentConfig: any = {}; @@ -158,7 +158,7 @@ const setPpsConfigFromTargetingSet = (next, targetingSet) => { // set gpt config const auctionsIds = getAuctionsIdsFromTargeting(targetingSet); const signals = getSignalsIntersection(getSignalsArrayByAuctionsIds(auctionsIds)); - window.googletag.setConfig && window.googletag.setConfig({pps: { taxonomies: signals }}); + window.googletag.setConfig && window.googletag.setConfig({ pps: { taxonomies: signals } }); next(targetingSet); }; @@ -206,8 +206,8 @@ const handleSetGptConfig = moduleConfig => { } else { logInfo(`${MODULE_NAME}: Turning off module`); _currentConfig = {}; - getHook('makeBidRequests').getHooks({hook: makeBidRequestsHook}).remove(); - getHook('targetingDone').getHooks({hook: setPpsConfigFromTargetingSet}).remove(); + getHook('makeBidRequests').getHooks({ hook: makeBidRequestsHook }).remove(); + getHook('targetingDone').getHooks({ hook: setPpsConfigFromTargetingSet }).remove(); hooksAdded = false; } }; diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index cb251230899..12be9426b2a 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -1,13 +1,13 @@ -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {_each, deepAccess, getWinDimensions, logError, logWarn, parseSizesInput} from '../src/utils.js'; -import {getDevicePixelRatio} from '../libraries/devicePixelRatio/devicePixelRatio.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { _each, deepAccess, getWinDimensions, logError, logWarn, parseSizesInput } from '../src/utils.js'; +import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRatio.js'; -import {config} from '../src/config.js'; -import {getStorageManager} from '../src/storageManager.js'; +import { config } from '../src/config.js'; +import { getStorageManager } from '../src/storageManager.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -19,7 +19,7 @@ import {getDNT} from '../libraries/dnt/index.js'; */ const BIDDER_CODE = 'gumgum'; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); +const storage = getStorageManager({ bidderCode: BIDDER_CODE }); const ALIAS_BIDDER_CODE = ['gg']; const BID_ENDPOINT = `https://g2.gumgum.com/hbid/imp`; const JCSI = { t: 0, rq: 8, pbv: '$prebid.version$' } @@ -648,7 +648,7 @@ function interpretResponse(serverResponse, bidRequest) { // added logic for in-slot multi-szie } else if ((product === 2 && sizes.includes('1x1')) || product === 3) { const requestSizesThatMatchResponse = (bidRequest.sizes && bidRequest.sizes.reduce((result, current) => { - const [ width, height ] = current; + const [width, height] = current; if (responseWidth === width && responseHeight === height) result.push(current.join('x')); return result }, [])) || []; diff --git a/modules/h12mediaBidAdapter.js b/modules/h12mediaBidAdapter.js index bea275a1c9d..90b284a485c 100644 --- a/modules/h12mediaBidAdapter.js +++ b/modules/h12mediaBidAdapter.js @@ -2,7 +2,7 @@ import { inIframe, logError, logMessage, deepAccess, getWinDimensions } from '.. import { registerBidder } from '../src/adapters/bidderFactory.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getViewportSize } from '../libraries/viewport/viewport.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'h12media'; const DEFAULT_URL = 'https://bidder.h12-media.com/prebid/'; const DEFAULT_CURRENCY = 'USD'; diff --git a/modules/hypelabBidAdapter.js b/modules/hypelabBidAdapter.js index 8edd78232b3..2112d93b9e5 100644 --- a/modules/hypelabBidAdapter.js +++ b/modules/hypelabBidAdapter.js @@ -5,7 +5,7 @@ import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRa import { ajax } from '../src/ajax.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getWalletPresence, getWalletProviderFlags } from '../libraries/hypelabUtils/hypelabUtils.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; export const BIDDER_CODE = 'hypelab'; export const ENDPOINT_URL = 'https://api.hypelab.com'; diff --git a/modules/impactifyBidAdapter.js b/modules/impactifyBidAdapter.js index 3cc74429b50..14a35d318f5 100644 --- a/modules/impactifyBidAdapter.js +++ b/modules/impactifyBidAdapter.js @@ -5,7 +5,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { ajax } from '../src/ajax.js'; import { getStorageManager } from '../src/storageManager.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js index eedccabac52..b2da2f3c077 100644 --- a/modules/ixBidAdapter.js +++ b/modules/ixBidAdapter.js @@ -22,8 +22,8 @@ import { getStorageManager } from '../src/storageManager.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { INSTREAM, OUTSTREAM } from '../src/video.js'; import { Renderer } from '../src/Renderer.js'; -import {getGptSlotInfoForAdUnitCode} from '../libraries/gptUtils/gptUtils.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const divIdCache = {}; @@ -975,7 +975,8 @@ function addImpressions(impressions, impKeys, r, adUnitIndex) { banner: { topframe, format: bannerImps.map(({ banner: { w, h }, ext }) => ({ w, h, ext })) - }}; + } + }; for (let i = 0; i < _bannerImpression.banner.format.length; i++) { // We add sid and externalID in imp.ext therefore, remove from banner.format[].ext @@ -1165,7 +1166,7 @@ function addFPD(bidderRequest, r, fpd, site, user) { }); if (fpd.device) { - const sua = {...fpd.device.sua}; + const sua = { ...fpd.device.sua }; if (!isEmpty(sua)) { deepSetValue(r, 'device.sua', sua); } diff --git a/modules/jixieBidAdapter.js b/modules/jixieBidAdapter.js index 6fc6c86cfcc..67895347e73 100644 --- a/modules/jixieBidAdapter.js +++ b/modules/jixieBidAdapter.js @@ -1,18 +1,18 @@ -import {deepAccess, isArray, logWarn, isFn, isPlainObject, logError, logInfo, getWinDimensions} from '../src/utils.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {ajax} from '../src/ajax.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import {Renderer} from '../src/Renderer.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { deepAccess, isArray, logWarn, isFn, isPlainObject, logError, logInfo, getWinDimensions } from '../src/utils.js'; +import { config } from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { ajax } from '../src/ajax.js'; +import { getRefererInfo } from '../src/refererDetection.js'; +import { Renderer } from '../src/Renderer.js'; +import { getDNT } from '../libraries/dnt/index.js'; const ADAPTER_VERSION = '2.1.0'; const PREBID_VERSION = '$prebid.version$'; const BIDDER_CODE = 'jixie'; -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); +export const storage = getStorageManager({ bidderCode: BIDDER_CODE }); const JX_OUTSTREAM_RENDERER_URL = 'https://scripts.jixie.media/jxhbrenderer.1.1.min.js'; const REQUESTS_URL = 'https://hb.jixie.io/v2/hbpost'; const sidTTLMins_ = 30; @@ -130,7 +130,7 @@ function createRenderer_(bidAd, scriptUrl, createFcn) { id: bidAd.adUnitCode, url: scriptUrl, loaded: false, - config: {'player_height': bidAd.height, 'player_width': bidAd.width}, + config: { 'player_height': bidAd.height, 'player_width': bidAd.width }, adUnitCode: bidAd.adUnitCode }); try { @@ -307,7 +307,7 @@ export const spec = { if (syncOptions.iframeEnabled) { syncs.push(sync.uf ? { url: sync.uf, type: 'iframe' } : { url: sync.up, type: 'image' }); } else if (syncOptions.pixelEnabled && sync.up) { - syncs.push({url: sync.up, type: 'image'}) + syncs.push({ url: sync.up, type: 'image' }) } }) return syncs; diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 7f2a3224819..3ff51fce8c1 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -3,7 +3,7 @@ import { VIDEO } from '../src/mediaTypes.js'; import { isArray, isFn, deepAccess, deepSetValue, logError, logWarn } from '../src/utils.js'; import { config } from '../src/config.js'; import { hasPurpose1Consent } from '../src/utils/gdpr.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'jwplayer'; const BASE_URL = 'https://vpb-server.jwplayer.com/'; diff --git a/modules/lemmaDigitalBidAdapter.js b/modules/lemmaDigitalBidAdapter.js index 227499424be..8c9eaeb925c 100644 --- a/modules/lemmaDigitalBidAdapter.js +++ b/modules/lemmaDigitalBidAdapter.js @@ -2,7 +2,7 @@ import * as utils from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/livewrappedAnalyticsAdapter.js b/modules/livewrappedAnalyticsAdapter.js index 2fea8711f57..686d90b7cc7 100644 --- a/modules/livewrappedAnalyticsAdapter.js +++ b/modules/livewrappedAnalyticsAdapter.js @@ -4,7 +4,7 @@ import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js'; import { EVENTS } from '../src/constants.js'; import adapterManager from '../src/adapterManager.js'; import { getGlobal } from '../src/prebidGlobal.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const ANALYTICSTYPE = 'endpoint'; const URL = 'https://lwadm.com/analytics/10'; diff --git a/modules/luceadBidAdapter.js b/modules/luceadBidAdapter.js index 186002b77ba..52f7718a7ab 100755 --- a/modules/luceadBidAdapter.js +++ b/modules/luceadBidAdapter.js @@ -2,10 +2,10 @@ * @module modules/luceadBidAdapter */ -import {ortbConverter} from '../libraries/ortbConverter/converter.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {getUniqueIdentifierStr, deepSetValue, logInfo} from '../src/utils.js'; -import {fetch} from '../src/ajax.js'; +import { ortbConverter } from '../libraries/ortbConverter/converter.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { getUniqueIdentifierStr, deepSetValue, logInfo } from '../src/utils.js'; +import { fetch } from '../src/ajax.js'; const bidderCode = 'lucead'; const defaultCurrency = 'EUR'; @@ -105,8 +105,8 @@ function interpretResponse(serverResponse, bidRequest) { }, })); - logInfo('interpretResponse', {serverResponse, bidRequest, bidRequestData, bids}); - return {bids}; + logInfo('interpretResponse', { serverResponse, bidRequest, bidRequestData, bids }); + return { bids }; } function report(type, data) { diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js index 1ed553a30d0..074a96b6268 100644 --- a/modules/marsmediaBidAdapter.js +++ b/modules/marsmediaBidAdapter.js @@ -1,12 +1,12 @@ 'use strict'; import { deepAccess, parseSizesInput, isArray, getWindowTop, deepSetValue, triggerPixel, getWindowSelf, isPlainObject } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; +import { config } from '../src/config.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; -import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getMinSize } from '../libraries/sizeUtils/sizeUtils.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; +import { getDNT } from '../libraries/dnt/index.js'; function MarsmediaAdapter() { this.code = 'marsmedia'; @@ -166,7 +166,7 @@ function MarsmediaAdapter() { let bidSizes = (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) || bid.sizes; bidSizes = ((isArray(bidSizes) && isArray(bidSizes[0])) ? bidSizes : [bidSizes]); bidSizes = bidSizes.filter(size => isArray(size)); - const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); + const processedSizes = bidSizes.map(size => ({ w: parseInt(size[0], 10), h: parseInt(size[1], 10) })); const element = getAdUnitElement(bid); const minSize = getMinSize(processedSizes); diff --git a/modules/mediaforceBidAdapter.js b/modules/mediaforceBidAdapter.js index a5a87fc80a1..2fda15971ea 100644 --- a/modules/mediaforceBidAdapter.js +++ b/modules/mediaforceBidAdapter.js @@ -1,9 +1,9 @@ import { deepAccess, isStr, replaceAuctionPrice, triggerPixel, parseGPTSingleSizeArrayToRtbSize } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { buildNativeRequest, parseNativeResponse } from '../libraries/nativeAssetsUtils.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/mediafuseBidAdapter.js b/modules/mediafuseBidAdapter.js index 9123f05c601..88902040067 100644 --- a/modules/mediafuseBidAdapter.js +++ b/modules/mediafuseBidAdapter.js @@ -16,22 +16,22 @@ import { logMessage, logWarn } from '../src/utils.js'; -import {Renderer} from '../src/Renderer.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {INSTREAM, OUTSTREAM} from '../src/video.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {bidderSettings} from '../src/bidderSettings.js'; -import {hasPurpose1Consent} from '../src/utils/gdpr.js'; -import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; +import { Renderer } from '../src/Renderer.js'; +import { config } from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { INSTREAM, OUTSTREAM } from '../src/video.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { bidderSettings } from '../src/bidderSettings.js'; +import { hasPurpose1Consent } from '../src/utils/gdpr.js'; +import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { getANKewyordParamFromMaps, getANKeywordParam } from '../libraries/appnexusUtils/anKeywords.js'; -import {convertCamelToUnderscore} from '../libraries/appnexusUtils/anUtils.js'; -import {chunk} from '../libraries/chunk/chunk.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { convertCamelToUnderscore } from '../libraries/appnexusUtils/anUtils.js'; +import { chunk } from '../libraries/chunk/chunk.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -88,7 +88,7 @@ const SCRIPT_TAG_START = ' { if (isNumber(val)) { - segs.push({'id': val}); + segs.push({ 'id': val }); } else if (isPlainObject(val)) { segs.push(val); } @@ -262,7 +262,7 @@ export const spec = { bidRequests[0].userIdAsEids.forEach(eid => { if (!eid || !eid.uids || eid.uids.length < 1) { return; } eid.uids.forEach(uid => { - const tmp = {'source': eid.source, 'id': uid.id}; + const tmp = { 'source': eid.source, 'id': uid.id }; if (eid.source === 'adserver.org') { tmp.rti_partner = 'TDID'; } else if (eid.source === 'uidapi.com') { @@ -334,7 +334,7 @@ export const spec = { }, getUserSyncs: function (syncOptions, responses, gdprConsent) { - if (syncOptions.iframeEnabled && hasPurpose1Consent({gdprConsent})) { + if (syncOptions.iframeEnabled && hasPurpose1Consent({ gdprConsent })) { return [{ type: 'iframe', url: 'https://acdn.adnxs.com/dmp/async_usersync.html' @@ -551,12 +551,13 @@ function newBid(serverBid, rtbBid, bidderRequest) { complete: 0, nodes: [{ bsid: rtbBid.buyer_member_id.toString() - }]}; + }] + }; return dchain; } if (rtbBid.buyer_member_id) { - bid.meta = Object.assign({}, bid.meta, {dchain: setupDChain(rtbBid)}); + bid.meta = Object.assign({}, bid.meta, { dchain: setupDChain(rtbBid) }); } if (rtbBid.brand_id) { diff --git a/modules/mediakeysBidAdapter.js b/modules/mediakeysBidAdapter.js index 34159385cc7..c7065a95f2b 100644 --- a/modules/mediakeysBidAdapter.js +++ b/modules/mediakeysBidAdapter.js @@ -16,11 +16,11 @@ import { mergeDeep, triggerPixel } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {config} from '../src/config.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import { getDNT } from '../libraries/dnt/index.js'; const AUCTION_TYPE = 1; const BIDDER_CODE = 'mediakeys'; @@ -81,7 +81,8 @@ const ORTB_VIDEO_PARAMS = { playbackend: value => [1, 2, 3].indexOf(value) !== -1, delivery: value => [1, 2, 3].indexOf(value) !== -1, pos: value => [0, 1, 2, 3, 4, 5, 6, 7].indexOf(value) !== -1, - api: value => Array.isArray(value) && value.every(v => [1, 2, 3, 4, 5, 6].indexOf(v) !== -1)}; + api: value => Array.isArray(value) && value.every(v => [1, 2, 3, 4, 5, 6].indexOf(v) !== -1) +}; /** * Returns the OpenRtb deviceType id detected from User Agent @@ -226,7 +227,7 @@ function createBannerImp(bid) { const format = []; sizes.forEach(function (size) { if (size.length && size.length > 1) { - format.push({w: size[0], h: size[1]}); + format.push({ w: size[0], h: size[1] }); } }); banner.format = format; diff --git a/modules/medianetBidAdapter.js b/modules/medianetBidAdapter.js index 6e6685ef737..f8ff33ddc81 100644 --- a/modules/medianetBidAdapter.js +++ b/modules/medianetBidAdapter.js @@ -10,20 +10,20 @@ import { deepClone, deepSetValue, getWindowTop } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {config} from '../src/config.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {Renderer} from '../src/Renderer.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { Renderer } from '../src/Renderer.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; -import {getGptSlotInfoForAdUnitCode} from '../libraries/gptUtils/gptUtils.js'; -import {getViewportCoordinates} from '../libraries/viewport/viewport.js'; -import {filterBidsListByFilters, getTopWindowReferrer} from '../libraries/medianetUtils/utils.js'; -import {errorLogger} from '../libraries/medianetUtils/logger.js'; -import {GLOBAL_VENDOR_ID, MEDIANET} from '../libraries/medianetUtils/constants.js'; -import {getGlobal} from '../src/prebidGlobal.js'; -import {getBoundingClientRect} from '../libraries/boundingClientRect/boundingClientRect.js'; -import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; +import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; +import { filterBidsListByFilters, getTopWindowReferrer } from '../libraries/medianetUtils/utils.js'; +import { errorLogger } from '../libraries/medianetUtils/logger.js'; +import { GLOBAL_VENDOR_ID, MEDIANET } from '../libraries/medianetUtils/constants.js'; +import { getGlobal } from '../src/prebidGlobal.js'; +import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; +import { getMinSize } from '../libraries/sizeUtils/sizeUtils.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -138,7 +138,7 @@ function getCoordinates(bidRequest) { let element = getAdUnitElement(bidRequest); if (!element && bidRequest.adUnitCode.indexOf('/') !== -1) { // now it means that adUnitCode is GAM AdUnitPath - const {divId} = getGptSlotInfoForAdUnitCode(bidRequest.adUnitCode); + const { divId } = getGptSlotInfoForAdUnitCode(bidRequest.adUnitCode); if (isStr(divId)) { element = document.getElementById(divId); } @@ -169,7 +169,7 @@ function extParams(bidRequest, bidderRequests) { const gdprApplies = !!(gdpr && gdpr.gdprApplies); const uspApplies = !!(uspConsent); const coppaApplies = !!(config.getConfig('coppa')); - const {top = -1, right = -1, bottom = -1, left = -1} = getViewportCoordinates(); + const { top = -1, right = -1, bottom = -1, left = -1 } = getViewportCoordinates(); return Object.assign({}, { customer_id: params.cid }, { prebid_version: 'v' + '$prebid.version$' }, @@ -177,11 +177,11 @@ function extParams(bidRequest, bidderRequests) { (gdprApplies) && { gdpr_consent_string: gdpr.consentString || '' }, { usp_applies: uspApplies }, uspApplies && { usp_consent_string: uspConsent || '' }, - {coppa_applies: coppaApplies}, + { coppa_applies: coppaApplies }, windowSize.w !== -1 && windowSize.h !== -1 && { screen: windowSize }, userId && { user_id: userId }, getGlobal().medianetGlobals.analyticsEnabled && { analytics: true }, - !isEmpty(sChain) && {schain: sChain}, + !isEmpty(sChain) && { schain: sChain }, { vcoords: { top_left: { x: left, y: top }, @@ -280,7 +280,7 @@ function getBidFloorByType(bidRequest) { return floorInfo; } function setFloorInfo(bidRequest, mediaType, size, floorInfo) { - const floor = bidRequest.getFloor({currency: 'USD', mediaType: mediaType, size: size}) || {}; + const floor = bidRequest.getFloor({ currency: 'USD', mediaType: mediaType, size: size }) || {}; if (size.length > 1) floor.size = size; floor.mediaType = mediaType; floorInfo.push(floor); @@ -297,7 +297,7 @@ function getSlotVisibility(topLeft, size) { return 0; } - return getOverlapArea(topLeft, bottomRight, {x: 0, y: 0}, {x: windowSize.w, y: windowSize.h}) / maxArea; + return getOverlapArea(topLeft, bottomRight, { x: 0, y: 0 }, { x: windowSize.w, y: windowSize.h }) / maxArea; } // find the overlapping area between two rectangles @@ -311,7 +311,7 @@ function getOverlapArea(topLeft1, bottomRight1, topLeft2, bottomRight2) { } function normalizeCoordinates(coordinates) { - const {scrollX, scrollY} = window; + const { scrollX, scrollY } = window; return { top_left: { x: coordinates.top_left.x + scrollX, @@ -506,11 +506,11 @@ export const spec = { const cookieSyncUrls = fetchCookieSyncUrls(serverResponses); if (syncOptions.iframeEnabled) { - return filterBidsListByFilters(cookieSyncUrls, {type: 'iframe'}); + return filterBidsListByFilters(cookieSyncUrls, { type: 'iframe' }); } if (syncOptions.pixelEnabled) { - return filterBidsListByFilters(cookieSyncUrls, {type: 'image'}); + return filterBidsListByFilters(cookieSyncUrls, { type: 'image' }); } }, @@ -554,7 +554,7 @@ export const spec = { } catch (e) {} }, - onBidderError: ({error, bidderRequest}) => { + onBidderError: ({ error, bidderRequest }) => { try { const eventData = { name: EVENTS.BIDDER_ERROR, diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index c74a3ba65b2..f370d220464 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -17,14 +17,14 @@ import { isInteger, deepSetValue, getBidIdParameter, setOnAny, getWinDimensions } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js' -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -35,7 +35,7 @@ import {getDNT} from '../libraries/dnt/index.js'; const GVLID = 358; const DEFAULT_CUR = 'USD'; const BIDDER_CODE = 'mgid'; -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); +export const storage = getStorageManager({ bidderCode: BIDDER_CODE }); const ENDPOINT_URL = 'https://prebid.mgid.com/prebid/'; const LOG_WARN_PREFIX = '[MGID warn]: '; const LOG_INFO_PREFIX = '[MGID info]: '; @@ -210,7 +210,7 @@ export const spec = { id: deepAccess(bidderRequest, 'bidderRequestId'), site: ortb2Data?.site || {}, cur: [cur], - geo: {utcoffset: info.timeOffset}, + geo: { utcoffset: info.timeOffset }, device: ortb2Data?.device || {}, ext: { mgid_ver: spec.VERSION, @@ -455,7 +455,7 @@ function createBannerRequest(bid) { if (sizes.length > 1) { for (let f = 0; f < sizes.length; f++) { if (sizes[f].length === 2) { - format.push({w: sizes[f][0], h: sizes[f][1]}); + format.push({ w: sizes[f][0], h: sizes[f][1] }); } } } @@ -692,7 +692,7 @@ function getBidFloor(bid, cur) { if (reqCur === cur) { cur = '' } - return {floor: bidFloor, cur: cur} + return { floor: bidFloor, cur: cur } } function copyFromAdmAsset(asset) { diff --git a/modules/msftBidAdapter.js b/modules/msftBidAdapter.js index 2d2c0becdd0..e9539cce6fc 100644 --- a/modules/msftBidAdapter.js +++ b/modules/msftBidAdapter.js @@ -31,7 +31,7 @@ import { logWarn, mergeDeep } from "../src/utils.js"; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = "msft"; const DEBUG_PARAMS = ['enabled', 'dongle', 'member_id', 'debug_timeout']; diff --git a/modules/nexverseBidAdapter.js b/modules/nexverseBidAdapter.js index 6aef2b2d078..4e65a98066c 100644 --- a/modules/nexverseBidAdapter.js +++ b/modules/nexverseBidAdapter.js @@ -2,14 +2,14 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js'; import { isArray, generateUUID, getWinDimensions, isNumber } from '../src/utils.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; -import {getConnectionType} from '../libraries/connectionInfo/connectionUtils.js' +import { getConnectionType } from '../libraries/connectionInfo/connectionUtils.js' import { getDeviceType } from '../libraries/userAgentUtils/index.js'; import { getDeviceModel, buildEndpointUrl, isBidRequestValid, parseNativeResponse, printLog, getUid, getBidFloor, getOsInfo } from '../libraries/nexverseUtils/index.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {MODULE_TYPE_UID} from '../src/activities/modules.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { MODULE_TYPE_UID } from '../src/activities/modules.js'; import { config } from '../src/config.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'nexverse'; const BIDDER_ENDPOINT = 'https://rtb.nexverse.ai'; @@ -18,7 +18,7 @@ const DEFAULT_CURRENCY = 'USD'; const BID_TTL = 300; const DEFAULT_LANG = 'en'; -export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: BIDDER_CODE}); +export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: BIDDER_CODE }); export const spec = { code: BIDDER_CODE, diff --git a/modules/omsBidAdapter.js b/modules/omsBidAdapter.js index 0be6d55aea5..d9f1e8091db 100644 --- a/modules/omsBidAdapter.js +++ b/modules/omsBidAdapter.js @@ -10,14 +10,14 @@ import { formatQS, deepAccess, } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; -import {ajax} from '../src/ajax.js'; -import {percentInView} from '../libraries/percentInView/percentInView.js'; -import {getUserSyncParams} from '../libraries/userSyncUtils/userSyncUtils.js'; -import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; -import {getBidFloor, isIframe} from '../libraries/omsUtils/index.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { ajax } from '../src/ajax.js'; +import { percentInView } from '../libraries/percentInView/percentInView.js'; +import { getUserSyncParams } from '../libraries/userSyncUtils/userSyncUtils.js'; +import { getMinSize } from '../libraries/sizeUtils/sizeUtils.js'; +import { getBidFloor, isIframe } from '../libraries/omsUtils/index.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'oms'; const URL = 'https://rt.marphezis.com/hb'; @@ -43,7 +43,7 @@ function buildRequests(bidReqs, bidderRequest) { let bidSizes = bid?.mediaTypes?.banner?.sizes || bid.sizes || []; bidSizes = ((isArray(bidSizes) && isArray(bidSizes[0])) ? bidSizes : [bidSizes]); bidSizes = bidSizes.filter(size => isArray(size)); - const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); + const processedSizes = bidSizes.map(size => ({ w: parseInt(size[0], 10), h: parseInt(size[1], 10) })); const element = getAdUnitElement(bid); const minSize = getMinSize(processedSizes); @@ -150,7 +150,7 @@ function buildRequests(bidReqs, bidderRequest) { data: JSON.stringify(payload), }; } catch (e) { - logError(e, {bidReqs, bidderRequest}); + logError(e, { bidReqs, bidderRequest }); } } @@ -169,7 +169,7 @@ function interpretResponse(serverResponse) { return response; } - const {body: {id, seatbid}} = serverResponse; + const { body: { id, seatbid } } = serverResponse; try { if (id && seatbid && seatbid.length > 0 && seatbid[0].bid && seatbid[0].bid.length > 0) { @@ -200,7 +200,7 @@ function interpretResponse(serverResponse) { }); } } catch (e) { - logError(e, {id, seatbid}); + logError(e, { id, seatbid }); } return response; @@ -279,8 +279,8 @@ function _isViewabilityMeasurable(element) { return !isIframe() && element !== null; } -function _getViewability(element, topWin, {w, h} = {}) { - return getWindowTop().document.visibilityState === 'visible' ? percentInView(element, {w, h}) : 0; +function _getViewability(element, topWin, { w, h } = {}) { + return getWindowTop().document.visibilityState === 'visible' ? percentInView(element, { w, h }) : 0; } function _extractGpidData(bid) { diff --git a/modules/onetagBidAdapter.js b/modules/onetagBidAdapter.js index 8486a982050..3d70c233805 100644 --- a/modules/onetagBidAdapter.js +++ b/modules/onetagBidAdapter.js @@ -9,7 +9,7 @@ import { deepClone, logError, deepAccess, getWinDimensions } from '../src/utils. import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { toOrtbNativeRequest } from '../src/native.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/onomagicBidAdapter.js b/modules/onomagicBidAdapter.js index 7e380d540c0..1dade3668ea 100644 --- a/modules/onomagicBidAdapter.js +++ b/modules/onomagicBidAdapter.js @@ -7,12 +7,12 @@ import { logError, logWarn } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER} from '../src/mediaTypes.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER } from '../src/mediaTypes.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; -import {getMinSize} from '../libraries/sizeUtils/sizeUtils.js'; -import {getBidFloor, isIframe} from '../libraries/omsUtils/index.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getMinSize } from '../libraries/sizeUtils/sizeUtils.js'; +import { getBidFloor, isIframe } from '../libraries/omsUtils/index.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'onomagic'; const URL = 'https://bidder.onomagic.com/hb'; @@ -38,7 +38,7 @@ function buildRequests(bidReqs, bidderRequest) { let bidSizes = (bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes) || bid.sizes; bidSizes = ((isArray(bidSizes) && isArray(bidSizes[0])) ? bidSizes : [bidSizes]); bidSizes = bidSizes.filter(size => isArray(size)); - const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})); + const processedSizes = bidSizes.map(size => ({ w: parseInt(size[0], 10), h: parseInt(size[1], 10) })); const element = getAdUnitElement(bid); const minSize = getMinSize(processedSizes); @@ -86,10 +86,10 @@ function buildRequests(bidReqs, bidderRequest) { method: 'POST', url: URL, data: JSON.stringify(onomagicBidReq), - options: {contentType: 'text/plain', withCredentials: false} + options: { contentType: 'text/plain', withCredentials: false } }; } catch (e) { - logError(e, {bidReqs, bidderRequest}); + logError(e, { bidReqs, bidderRequest }); } } @@ -110,7 +110,7 @@ function interpretResponse(serverResponse) { logWarn('Onomagic server returned empty/non-json response: ' + JSON.stringify(serverResponse.body)); return []; } - const { body: {id, seatbid} } = serverResponse; + const { body: { id, seatbid } } = serverResponse; try { const onomagicBidResponses = []; if (id && @@ -138,7 +138,7 @@ function interpretResponse(serverResponse) { } return onomagicBidResponses; } catch (e) { - logError(e, {id, seatbid}); + logError(e, { id, seatbid }); } } diff --git a/modules/operaadsBidAdapter.js b/modules/operaadsBidAdapter.js index 201ecfb8540..4a8e22aaa6a 100644 --- a/modules/operaadsBidAdapter.js +++ b/modules/operaadsBidAdapter.js @@ -10,13 +10,13 @@ import { logWarn, triggerPixel } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {config} from '../src/config.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {Renderer} from '../src/Renderer.js'; -import {OUTSTREAM} from '../src/video.js'; -import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { Renderer } from '../src/Renderer.js'; +import { OUTSTREAM } from '../src/video.js'; +import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -709,7 +709,7 @@ function getUserId(bidRequest) { * @param {*} params.size * @returns {Object} floor price */ -function getBidFloor(bid, {mediaType = '*', size = '*'}) { +function getBidFloor(bid, { mediaType = '*', size = '*' }) { if (isFn(bid.getFloor)) { const floorInfo = bid.getFloor({ currency: DEFAULT_CURRENCY, diff --git a/modules/ozoneBidAdapter.js b/modules/ozoneBidAdapter.js index 027d623ba12..ee631309610 100644 --- a/modules/ozoneBidAdapter.js +++ b/modules/ozoneBidAdapter.js @@ -11,13 +11,13 @@ import { mergeDeep, parseUrl } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {getPriceBucketString} from '../src/cpmBucketManager.js'; -import {Renderer} from '../src/Renderer.js'; -import {getRefererInfo} from '../src/refererDetection.js'; -import {toOrtb25} from '../libraries/ortb2.5Translator/translator.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import { getPriceBucketString } from '../src/cpmBucketManager.js'; +import { Renderer } from '../src/Renderer.js'; +import { getRefererInfo } from '../src/refererDetection.js'; +import { toOrtb25 } from '../libraries/ortb2.5Translator/translator.js'; const BIDDER_CODE = 'ozone'; const ORIGIN = 'https://elb.the-ozone-project.com'; @@ -31,8 +31,8 @@ export const spec = { version: OZONEVERSION, code: BIDDER_CODE, supportedMediaTypes: [VIDEO, BANNER], - cookieSyncBag: {publisherId: null, siteId: null, userIdObject: {}}, - propertyBag: {pageId: null, buildRequestsStart: 0, buildRequestsEnd: 0}, + cookieSyncBag: { publisherId: null, siteId: null, userIdObject: {} }, + propertyBag: { pageId: null, buildRequestsStart: 0, buildRequestsEnd: 0 }, getAuctionUrl() { const ep = config.getConfig('ozone.endpointOverride') || {}; if (ep.auctionUrl) return ep.auctionUrl; @@ -140,7 +140,7 @@ export const spec = { if (this.blockTheRequest()) { return []; } - let htmlParams = {'publisherId': '', 'siteId': ''}; + let htmlParams = { 'publisherId': '', 'siteId': '' }; if (validBidRequests.length > 0) { Object.assign(this.cookieSyncBag.userIdObject, this.findAllUserIdsFromEids(validBidRequests[0])); this.cookieSyncBag.siteId = deepAccess(validBidRequests[0], 'params.siteId'); @@ -150,9 +150,9 @@ export const spec = { logInfo('cookie sync bag', this.cookieSyncBag); let singleRequest = config.getConfig('ozone.singleRequest'); singleRequest = singleRequest !== false; - const ozoneRequest = {site: {}, regs: {}, user: {}}; + const ozoneRequest = { site: {}, regs: {}, user: {} }; const fpd = deepAccess(bidderRequest, 'ortb2', {}); - const fpdPruned = this.pruneToExtPaths(fpd, {maxTestDepth: 2}); + const fpdPruned = this.pruneToExtPaths(fpd, { maxTestDepth: 2 }); logInfo('got ortb2 fpd: ', fpd); logInfo('got ortb2 fpdPruned: ', fpdPruned); logInfo('going to assign the pruned (ext only) FPD ortb2 object to ozoneRequest, wholesale'); @@ -161,7 +161,7 @@ export const spec = { const getParams = this.getGetParametersAsObject(); const wlOztestmodeKey = 'oztestmode'; const isTestMode = getParams[wlOztestmodeKey] || null; - mergeDeep(ozoneRequest, {device: bidderRequest?.ortb2?.device || {}}); + mergeDeep(ozoneRequest, { device: bidderRequest?.ortb2?.device || {} }); const placementIdOverrideFromGetParam = this.getPlacementIdOverrideFromGetParam(); let schain = null; var auctionId = deepAccess(validBidRequests, '0.ortb2.source.tid'); @@ -170,7 +170,7 @@ export const spec = { } const tosendtags = validBidRequests.map(ozoneBidRequest => { var obj = {}; - let prunedImp = this.pruneToExtPaths(ozoneBidRequest.ortb2Imp, {maxTestDepth: 2}); + let prunedImp = this.pruneToExtPaths(ozoneBidRequest.ortb2Imp, { maxTestDepth: 2 }); logInfo('merging into bid[] from pruned ozoneBidRequest.ortb2Imp (this includes adunits ortb2imp and gpid & tid from gptPreAuction if included', prunedImp); mergeDeep(obj, prunedImp); const placementId = placementIdOverrideFromGetParam || this.getPlacementId(ozoneBidRequest); @@ -231,12 +231,12 @@ export const spec = { w: arrBannerSizes[0][0] || 0, h: arrBannerSizes[0][1] || 0, format: arrBannerSizes.map(s => { - return {w: s[0], h: s[1]}; + return { w: s[0], h: s[1] }; }) }; } obj.placementId = placementId; - mergeDeep(obj, {ext: {prebid: {'storedrequest': {'id': placementId}}}}); + mergeDeep(obj, { ext: { prebid: { 'storedrequest': { 'id': placementId } } } }); obj.ext[bidderKey] = obj.ext[bidderKey] || {}; obj.ext[bidderKey].adUnitCode = ozoneBidRequest.adUnitCode; if (ozoneBidRequest.params.hasOwnProperty('customData')) { @@ -258,7 +258,7 @@ export const spec = { obj.ext[bidderKey].customData[i]['targeting'][wlOztestmodeKey] = isTestMode; } } else { - obj.ext[bidderKey].customData = [{'settings': {}, 'targeting': {}}]; + obj.ext[bidderKey].customData = [{ 'settings': {}, 'targeting': {} }]; obj.ext[bidderKey].customData[0].targeting[wlOztestmodeKey] = isTestMode; } } @@ -305,7 +305,7 @@ export const spec = { } const userExtEids = deepAccess(validBidRequests, '0.userIdAsEids', []); mergeDeep(ozoneRequest.site, { - 'publisher': {'id': htmlParams.publisherId}, + 'publisher': { 'id': htmlParams.publisherId }, 'page': getRefererInfo().page, 'id': htmlParams.siteId }); @@ -313,7 +313,7 @@ export const spec = { if (bidderRequest && bidderRequest.gdprConsent) { logInfo('ADDING GDPR'); const apiVersion = deepAccess(bidderRequest, 'gdprConsent.apiVersion', 1); - mergeDeep(ozoneRequest.regs, {ext: {gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0, apiVersion: apiVersion}}); + mergeDeep(ozoneRequest.regs, { ext: { gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0, apiVersion: apiVersion } }); if (bidderRequest.gdprConsent.gdprApplies) { deepSetValue(ozoneRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); } else { @@ -347,12 +347,12 @@ export const spec = { const arrRet = []; for (let i = 0; i < tosendtags.length; i += batchRequestsVal) { ozoneRequest.id = generateUUID(); - mergeDeep(ozoneRequest, {user: {ext: {eids: userExtEids}}}); + mergeDeep(ozoneRequest, { user: { ext: { eids: userExtEids } } }); if (auctionId) { deepSetValue(ozoneRequest, 'source.tid', auctionId); } ozoneRequest.imp = tosendtags.slice(i, i + batchRequestsVal); - mergeDeep(ozoneRequest, {ext: extObj}); + mergeDeep(ozoneRequest, { ext: extObj }); toOrtb25(ozoneRequest); if (ozoneRequest.imp.length > 0) { arrRet.push({ @@ -371,9 +371,9 @@ export const spec = { logInfo('single request starting'); ozoneRequest.id = generateUUID(); ozoneRequest.imp = tosendtags; - mergeDeep(ozoneRequest, {ext: extObj}); + mergeDeep(ozoneRequest, { ext: extObj }); toOrtb25(ozoneRequest); - mergeDeep(ozoneRequest, {user: {ext: {eids: userExtEids}}}); + mergeDeep(ozoneRequest, { user: { ext: { eids: userExtEids } } }); if (auctionId) { deepSetValue(ozoneRequest, 'source.tid', auctionId); } @@ -392,8 +392,8 @@ export const spec = { const ozoneRequestSingle = Object.assign({}, ozoneRequest); ozoneRequestSingle.id = generateUUID(); ozoneRequestSingle.imp = [imp]; - mergeDeep(ozoneRequestSingle, {ext: extObj}); - mergeDeep(ozoneRequestSingle, {user: {ext: {eids: userExtEids}}}); + mergeDeep(ozoneRequestSingle, { ext: extObj }); + mergeDeep(ozoneRequestSingle, { user: { ext: { eids: userExtEids } } }); if (auctionId) { deepSetValue(ozoneRequestSingle, 'source.tid', auctionId); } @@ -418,13 +418,13 @@ export const spec = { logInfo('getFloorObjectForAuction mediaTypesSizes : ', mediaTypesSizes); const ret = {}; if (mediaTypesSizes.banner) { - ret.banner = bidRequestRef.getFloor({mediaType: 'banner', currency: 'USD', size: mediaTypesSizes.banner[0]}); + ret.banner = bidRequestRef.getFloor({ mediaType: 'banner', currency: 'USD', size: mediaTypesSizes.banner[0] }); } if (mediaTypesSizes.video) { - ret.video = bidRequestRef.getFloor({mediaType: 'video', currency: 'USD', size: mediaTypesSizes.video[0]}); + ret.video = bidRequestRef.getFloor({ mediaType: 'video', currency: 'USD', size: mediaTypesSizes.video[0] }); } if (mediaTypesSizes.native) { - ret.native = bidRequestRef.getFloor({mediaType: 'native', currency: 'USD', size: mediaTypesSizes.native[0]}); + ret.native = bidRequestRef.getFloor({ mediaType: 'native', currency: 'USD', size: mediaTypesSizes.native[0] }); } logInfo('getFloorObjectForAuction returning : ', deepClone(ret)); return ret; @@ -462,9 +462,9 @@ export const spec = { for (let j = 0; j < sb.bid.length; j++) { const thisRequestBid = this.getBidRequestForBidId(sb.bid[j].impid, request.bidderRequest.bids); logInfo(`seatbid:${i}, bid:${j} Going to set default w h for seatbid/bidRequest`, sb.bid[j], thisRequestBid); - const {defaultWidth, defaultHeight} = defaultSize(thisRequestBid); + const { defaultWidth, defaultHeight } = defaultSize(thisRequestBid); const thisBid = ozoneAddStandardProperties(sb.bid[j], defaultWidth, defaultHeight); - thisBid.meta = {advertiserDomains: thisBid.adomain || []}; + thisBid.meta = { advertiserDomains: thisBid.adomain || [] }; let videoContext = null; let isVideo = false; const bidType = deepAccess(thisBid, 'ext.prebid.type'); @@ -538,7 +538,7 @@ export const spec = { logInfo(perBidInfo); } } - let {seat: winningSeat, bid: winningBid} = ozoneGetWinnerForRequestBid(thisBid.bidId, serverResponse.seatbid); + let { seat: winningSeat, bid: winningBid } = ozoneGetWinnerForRequestBid(thisBid.bidId, serverResponse.seatbid); winningBid = ozoneAddStandardProperties(winningBid, defaultWidth, defaultHeight); adserverTargeting[prefix + '_auc_id'] = String(aucId); adserverTargeting[prefix + '_winner'] = String(winningSeat); @@ -583,7 +583,7 @@ export const spec = { var ret = []; for (let i = 0; i < seatbid.length; i++) { const sb = seatbid[i]; - var retSeatbid = {'seat': sb.seat, 'bid': []}; + var retSeatbid = { 'seat': sb.seat, 'bid': [] }; var bidIds = []; for (let j = 0; j < sb.bid.length; j++) { var candidate = sb.bid[j]; @@ -707,7 +707,7 @@ export const spec = { return this.propertyBag.pageId; }, unpackVideoConfigIntoIABformat(videoConfig, childConfig) { - let ret = {'ext': {}}; + let ret = { 'ext': {} }; ret = this._unpackVideoConfigIntoIABformat(ret, videoConfig); ret = this._unpackVideoConfigIntoIABformat(ret, childConfig); return ret; @@ -866,7 +866,7 @@ export function ozoneGetWinnerForRequestBid(requestBidId, serverResponseSeatBid) } } } - return {'seat': winningSeat, 'bid': thisBidWinner}; + return { 'seat': winningSeat, 'bid': thisBidWinner }; } export function ozoneGetAllBidsForBidId(matchBidId, serverResponseSeatBid, defaultWidth, defaultHeight) { const objBids = {}; @@ -906,7 +906,7 @@ export function getRoundedBid(price, mediaType) { key = 'custom'; } } - const mapping = {medium: 'med', custom: 'custom', high: 'high', low: 'low', dense: 'dense'}; + const mapping = { medium: 'med', custom: 'custom', high: 'high', low: 'low', dense: 'dense' }; const priceStrings = getPriceBucketString(price, buckets, config.getConfig('currency.granularityMultiplier')); logInfo('getRoundedBid price:', price, 'mediaType:', mediaType, 'bucketKey:', key); return priceStrings[mapping[key] || 'auto']; @@ -941,7 +941,7 @@ export function getWidthAndHeightFromVideoObject(objVideo) { logError('getWidthAndHeightFromVideoObject found playerSize with length of ' + playerSize.length + '. This is totally wrong - cannot continue.'); return null; } - return ({'w': playerSize[0], 'h': playerSize[1]}); + return ({ 'w': playerSize[0], 'h': playerSize[1] }); } function getPlayerSizeFromObject(objVideo) { logInfo('getPlayerSizeFromObject received object', objVideo); diff --git a/modules/panxoBidAdapter.js b/modules/panxoBidAdapter.js index 1a898b64887..5de64af33ff 100644 --- a/modules/panxoBidAdapter.js +++ b/modules/panxoBidAdapter.js @@ -8,7 +8,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; import { deepAccess, logWarn, isFn, isPlainObject } from '../src/utils.js'; import { getStorageManager } from '../src/storageManager.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'panxo'; const ENDPOINT_URL = 'https://panxo-sys.com/openrtb/2.5/bid'; diff --git a/modules/prebidServerBidAdapter/index.ts b/modules/prebidServerBidAdapter/index.ts index e2dcaf8bd28..056eca786a1 100644 --- a/modules/prebidServerBidAdapter/index.ts +++ b/modules/prebidServerBidAdapter/index.ts @@ -18,23 +18,23 @@ import { triggerPixel, uniques, } from '../../src/utils.js'; -import {DEBUG_MODE, EVENTS, REJECTION_REASON, S2S} from '../../src/constants.js'; -import adapterManager, {s2sActivityParams} from '../../src/adapterManager.js'; -import {config} from '../../src/config.js'; -import {isValid} from '../../src/adapters/bidderFactory.js'; +import { DEBUG_MODE, EVENTS, REJECTION_REASON, S2S } from '../../src/constants.js'; +import adapterManager, { s2sActivityParams } from '../../src/adapterManager.js'; +import { config } from '../../src/config.js'; +import { isValid } from '../../src/adapters/bidderFactory.js'; import * as events from '../../src/events.js'; -import {ajax} from '../../src/ajax.js'; -import {hook} from '../../src/hook.js'; -import {hasPurpose1Consent} from '../../src/utils/gdpr.js'; -import {buildPBSRequest, interpretPBSResponse} from './ortbConverter.js'; -import {useMetrics} from '../../src/utils/perfMetrics.js'; -import {isActivityAllowed} from '../../src/activities/rules.js'; -import {ACTIVITY_TRANSMIT_UFPD} from '../../src/activities/activities.js'; -import type {Identifier, BidderCode} from '../../src/types/common.d.ts'; -import type {Metrics} from "../../src/utils/perfMetrics.ts"; -import type {ORTBResponse} from "../../src/types/ortb/response.d.ts"; -import type {NativeRequest} from '../../src/types/ortb/native.d.ts'; -import type {SyncType} from "../../src/userSync.ts"; +import { ajax } from '../../src/ajax.js'; +import { hook } from '../../src/hook.js'; +import { hasPurpose1Consent } from '../../src/utils/gdpr.js'; +import { buildPBSRequest, interpretPBSResponse } from './ortbConverter.js'; +import { useMetrics } from '../../src/utils/perfMetrics.js'; +import { isActivityAllowed } from '../../src/activities/rules.js'; +import { ACTIVITY_TRANSMIT_UFPD } from '../../src/activities/activities.js'; +import type { Identifier, BidderCode } from '../../src/types/common.d.ts'; +import type { Metrics } from "../../src/utils/perfMetrics.ts"; +import type { ORTBResponse } from "../../src/types/ortb/response.d.ts"; +import type { NativeRequest } from '../../src/types/ortb/native.d.ts'; +import type { SyncType } from "../../src/userSync.ts"; const getConfig = config.getConfig; @@ -155,7 +155,7 @@ export const s2sDefaultConfig: Partial = { syncUrlModifier: {}, ortbNative: { eventtrackers: [ - {event: 1, methods: [1, 2]} + { event: 1, methods: [1, 2] } ], }, maxTimeout: 1500, @@ -247,7 +247,7 @@ function setS2sConfig(options) { _s2sConfigs = options; } } -getConfig('s2sConfig', ({s2sConfig}) => setS2sConfig(s2sConfig)); +getConfig('s2sConfig', ({ s2sConfig }) => setS2sConfig(s2sConfig)); /** * resets the _synced variable back to false, primiarily used for testing purposes @@ -476,7 +476,7 @@ export function PrebidServer() { .newMetrics() .renameWith((n) => [`adapter.s2s.${n}`, `adapters.s2s.${s2sBidRequest.s2sConfig.defaultVendor}.${n}`]) done = adapterMetrics.startTiming('total').stopBefore(done); - bidRequests.forEach(req => useMetrics(req.metrics).join(adapterMetrics, {stopPropagation: true})); + bidRequests.forEach(req => useMetrics(req.metrics).join(adapterMetrics, { stopPropagation: true })); const { gdprConsent, uspConsent, gppConsent } = getConsentData(bidRequests); @@ -512,7 +512,7 @@ export function PrebidServer() { doClientSideSyncs(requestedBidders, gdprConsent, uspConsent, gppConsent); }, onError(msg, error) { - const {p1Consent = '', noP1Consent = ''} = s2sBidRequest?.s2sConfig?.endpoint || {}; + const { p1Consent = '', noP1Consent = '' } = s2sBidRequest?.s2sConfig?.endpoint || {}; if (p1Consent === noP1Consent) { logError(`Prebid server call failed: '${msg}'. Endpoint: "${p1Consent}"}`, error); } else { @@ -521,7 +521,7 @@ export function PrebidServer() { bidRequests.forEach(bidderRequest => events.emit(EVENTS.BIDDER_ERROR, { error, bidderRequest })); done(error.timedOut); }, - onBid: function ({adUnit, bid}) { + onBid: function ({ adUnit, bid }) { const metrics = bid.metrics = s2sBidRequest.metrics.fork().renameWith(); metrics.checkpoint('addBidResponse'); if ((bid.requestId == null || bid.requestBidder == null) && !s2sBidRequest.s2sConfig.allowUnknownBidderCodes) { @@ -562,7 +562,7 @@ type PbsRequestData = { * @param onError {function(String, {})} invoked on HTTP failure - with status message and XHR error * @param onBid {function({})} invoked once for each bid in the response - with the bid as returned by interpretResponse */ -export const processPBSRequest = hook('async', function (s2sBidRequest, bidRequests, ajax, {onResponse, onError, onBid}) { +export const processPBSRequest = hook('async', function (s2sBidRequest, bidRequests, ajax, { onResponse, onError, onBid }) { const { gdprConsent } = getConsentData(bidRequests); const adUnits = deepClone(s2sBidRequest.ad_units); @@ -591,7 +591,7 @@ export const processPBSRequest = hook('async', function (s2sBidRequest, bidReque let result; try { result = JSON.parse(response); - const {bids} = s2sBidRequest.metrics.measureTime('interpretResponse', () => interpretPBSResponse(result, request)); + const { bids } = s2sBidRequest.metrics.measureTime('interpretResponse', () => interpretPBSResponse(result, request)); bids.forEach(onBid); } catch (error) { logError(error); diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 6b4a5b1df95..942f9496f63 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -9,7 +9,7 @@ import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { NATIVE_ASSET_TYPES, NATIVE_IMAGE_TYPES, PREBID_NATIVE_DATA_KEYS_TO_ORTB, NATIVE_KEYS_THAT_ARE_NOT_ASSETS, NATIVE_KEYS } from '../src/constants.js'; import { addDealCustomTargetings, addPMPDeals } from '../libraries/dealUtils/dealUtils.js'; import { getConnectionType } from '../libraries/connectionInfo/connectionUtils.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/pubstackBidAdapter.ts b/modules/pubstackBidAdapter.ts index b43ca7be4b8..3ef04f138e1 100644 --- a/modules/pubstackBidAdapter.ts +++ b/modules/pubstackBidAdapter.ts @@ -143,7 +143,7 @@ const getUserSyncs: GetUserSyncFn = (syncOptions, _serverResponses, gdprConsent, export const spec: BidderSpec = { code: BIDDER_CODE, - aliases: [ {code: `${BIDDER_CODE}_server`, gvlid: GVLID} ], + aliases: [{ code: `${BIDDER_CODE}_server`, gvlid: GVLID }], gvlid: GVLID, supportedMediaTypes: [BANNER, VIDEO, NATIVE], isBidRequestValid, diff --git a/modules/pwbidBidAdapter.js b/modules/pwbidBidAdapter.js index 854d56e4ae0..1d2fa182b79 100644 --- a/modules/pwbidBidAdapter.js +++ b/modules/pwbidBidAdapter.js @@ -4,7 +4,7 @@ import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { OUTSTREAM, INSTREAM } from '../src/video.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -275,7 +275,7 @@ export const spec = { deepSetValue(payload, 'regs.coppa', 1); } - var options = {contentType: 'text/plain'}; + var options = { contentType: 'text/plain' }; _logInfo('buildRequests payload', payload); _logInfo('buildRequests bidderRequest', bidderRequest); diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 173c8e0649f..f7518d0d916 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -1,9 +1,9 @@ 'use strict'; import { deepAccess, parseSizesInput, isArray } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; function RhythmOneBidAdapter() { this.code = 'rhythmone'; diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index cb8101bbae7..bc932314527 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -21,9 +21,9 @@ import { _each, isPlainObject } from '../src/utils.js'; -import {getAllOrtbKeywords} from '../libraries/keywords/keywords.js'; -import {getUserSyncParams} from '../libraries/userSyncUtils/userSyncUtils.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAllOrtbKeywords } from '../libraries/keywords/keywords.js'; +import { getUserSyncParams } from '../libraries/userSyncUtils/userSyncUtils.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -169,7 +169,7 @@ _each(sizeMap, (item, key) => { export const converter = ortbConverter({ request(buildRequest, imps, bidderRequest, context) { - const {bidRequests} = context; + const { bidRequests } = context; const data = buildRequest(imps, bidderRequest, context); data.cur = ['USD']; data.test = config.getConfig('debug') ? 1 : 0; @@ -189,7 +189,7 @@ export const converter = ortbConverter({ const modules = (getGlobal()).installedModules; if (modules && (!modules.length || modules.indexOf('rubiconAnalyticsAdapter') !== -1)) { - deepSetValue(data, 'ext.prebid.analytics', {'rubicon': {'client-analytics': true}}); + deepSetValue(data, 'ext.prebid.analytics', { 'rubicon': { 'client-analytics': true } }); } addOrtbFirstPartyData(data, bidRequests, bidderRequest.ortb2); @@ -234,7 +234,7 @@ export const converter = ortbConverter({ bidResponse(buildBidResponse, bid, context) { const bidResponse = buildBidResponse(bid, context); bidResponse.meta.mediaType = deepAccess(bid, 'ext.prebid.type'); - const {bidRequest} = context; + const { bidRequest } = context; const [parseSizeWidth, parseSizeHeight] = bidRequest.mediaTypes.video?.context === 'outstream' ? parseSizes(bidRequest, VIDEO) : [undefined, undefined]; // 0 by default to avoid undefined size @@ -318,7 +318,7 @@ export const spec = { }); if (filteredRequests && filteredRequests.length) { - const data = converter.toORTB({bidRequests: filteredRequests, bidderRequest}); + const data = converter.toORTB({ bidRequests: filteredRequests, bidderRequest }); resetImpIdMap(); filteredHttpRequest.push({ @@ -331,7 +331,7 @@ export const spec = { const bannerBidRequests = bidRequests.filter((req) => { const mediaTypes = bidType(req) || []; - const {bidonmultiformat, video} = req.params || {}; + const { bidonmultiformat, video } = req.params || {}; return ( // Send to fastlane if: it must include BANNER and... mediaTypes.includes(BANNER) && ( @@ -536,7 +536,7 @@ export const spec = { // add p_pos only if specified and valid // For SRA we need to explicitly put empty semi colons so AE treats it as empty, instead of copying the latter value - const posMapping = {1: 'atf', 3: 'btf'}; + const posMapping = { 1: 'atf', 3: 'btf' }; const pos = posMapping[deepAccess(bidRequest, 'mediaTypes.banner.pos')] || ''; data['p_pos'] = (params.position === 'atf' || params.position === 'btf') ? params.position : pos; @@ -656,7 +656,7 @@ export const spec = { */ interpretResponse: function (responseObj, request) { responseObj = responseObj.body; - const {data} = request; + const { data } = request; // check overall response if (!responseObj || typeof responseObj !== 'object') { @@ -668,14 +668,14 @@ export const spec = { if (Array.isArray(responseErrors) && responseErrors.length > 0) { logWarn('Rubicon: Error in video response'); } - const bids = converter.fromORTB({request: data, response: responseObj}).bids; + const bids = converter.fromORTB({ request: data, response: responseObj }).bids; return bids; } let ads = responseObj.ads; let lastImpId; let multibid = 0; - const {bidRequest} = request; + const { bidRequest } = request; // video ads array is wrapped in an object if (typeof bidRequest === 'object' && !Array.isArray(bidRequest) && bidType(bidRequest).includes(VIDEO) && typeof ads === 'object') { @@ -753,7 +753,7 @@ export const spec = { .reduce((memo, item) => { memo[item.key] = item.values[0]; return memo; - }, {'rpfl_elemid': associatedBidRequest.adUnitCode}); + }, { 'rpfl_elemid': associatedBidRequest.adUnitCode }); bids.push(bid); } else { @@ -910,8 +910,8 @@ function parseSizes(bid, mediaType) { function applyFPD(bidRequest, mediaType, data) { const BID_FPD = { - user: {ext: {data: {...bidRequest.params.visitor}}}, - site: {ext: {data: {...bidRequest.params.inventory}}} + user: { ext: { data: { ...bidRequest.params.visitor } } }, + site: { ext: { data: { ...bidRequest.params.inventory } } } }; if (bidRequest.params.keywords) BID_FPD.site.keywords = (isArray(bidRequest.params.keywords)) ? bidRequest.params.keywords.join(',') : bidRequest.params.keywords; @@ -922,8 +922,8 @@ function applyFPD(bidRequest, mediaType, data) { const gpid = deepAccess(bidRequest, 'ortb2Imp.ext.gpid'); const dsa = deepAccess(fpd, 'regs.ext.dsa'); - const SEGTAX = {user: [4], site: [1, 2, 5, 6, 7]}; - const MAP = {user: 'tg_v.', site: 'tg_i.', adserver: 'tg_i.dfp_ad_unit_code', pbadslot: 'tg_i.pbadslot', keywords: 'kw'}; + const SEGTAX = { user: [4], site: [1, 2, 5, 6, 7] }; + const MAP = { user: 'tg_v.', site: 'tg_i.', adserver: 'tg_i.dfp_ad_unit_code', pbadslot: 'tg_i.pbadslot', keywords: 'kw' }; const validate = function(prop, key, parentName) { if (key === 'data' && Array.isArray(prop)) { return prop.filter(name => name.segment && deepAccess(name, 'ext.segtax') && SEGTAX[parentName] && @@ -1205,18 +1205,18 @@ export function determineRubiconVideoSizeId(bid) { export function getPriceGranularity(config) { return { ranges: { - low: [{max: 5.00, increment: 0.50}], - medium: [{max: 20.00, increment: 0.10}], - high: [{max: 20.00, increment: 0.01}], + low: [{ max: 5.00, increment: 0.50 }], + medium: [{ max: 20.00, increment: 0.10 }], + high: [{ max: 20.00, increment: 0.01 }], auto: [ - {max: 5.00, increment: 0.05}, - {min: 5.00, max: 10.00, increment: 0.10}, - {min: 10.00, max: 20.00, increment: 0.50} + { max: 5.00, increment: 0.05 }, + { min: 5.00, max: 10.00, increment: 0.10 }, + { min: 10.00, max: 20.00, increment: 0.50 } ], dense: [ - {max: 3.00, increment: 0.01}, - {min: 3.00, max: 8.00, increment: 0.05}, - {min: 8.00, max: 20.00, increment: 0.50} + { max: 3.00, increment: 0.01 }, + { min: 3.00, max: 8.00, increment: 0.05 }, + { min: 8.00, max: 20.00, increment: 0.50 } ], custom: config.getConfig('customPriceBucket') && config.getConfig('customPriceBucket').buckets }[config.getConfig('priceGranularity')] @@ -1314,8 +1314,8 @@ function addOrtbFirstPartyData(data, nonBannerRequests, ortb2) { const keywords = getAllOrtbKeywords(ortb2, ...nonBannerRequests.map(req => req.params.keywords)) nonBannerRequests.forEach(bidRequest => { const bidFirstPartyData = { - user: {ext: {data: {...bidRequest.params.visitor}}}, - site: {ext: {data: {...bidRequest.params.inventory}}} + user: { ext: { data: { ...bidRequest.params.visitor } } }, + site: { ext: { data: { ...bidRequest.params.inventory } } } }; // add site.content.language diff --git a/modules/scaliburBidAdapter.js b/modules/scaliburBidAdapter.js index 7dce8ee319a..71613297001 100644 --- a/modules/scaliburBidAdapter.js +++ b/modules/scaliburBidAdapter.js @@ -1,9 +1,9 @@ -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {config} from '../src/config.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {sizesToSizeTuples} from "../src/utils.js"; -import {getDNT} from '../libraries/dnt/index.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { sizesToSizeTuples } from "../src/utils.js"; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'scalibur'; const ENDPOINT_SERVER = new URLSearchParams(window.location.search).get('sclServer') || 'srv'; @@ -15,7 +15,7 @@ const BIDDER_VERSION = '1.0.0'; const IFRAME_TYPE_Q_PARAM = 'iframe'; const IMAGE_TYPE_Q_PARAM = 'img'; const GVLID = 1471; -const storage = getStorageManager({bidderCode: BIDDER_CODE}); +const storage = getStorageManager({ bidderCode: BIDDER_CODE }); const STORAGE_KEY = `${BIDDER_CODE}_fp_data`; export const spec = { @@ -93,7 +93,7 @@ export const spec = { } // Floor Price - const floor = bid.getFloor ? bid.getFloor({currency: DEFAULT_CURRENCY, mediaType: '*', size: '*'}) : {}; + const floor = bid.getFloor ? bid.getFloor({ currency: DEFAULT_CURRENCY, mediaType: '*', size: '*' }) : {}; imp.bidfloor = floor.floor || bid.params.bidfloor || 0; imp.bidfloorcur = floor.currency || bid.params.bidfloorcur || DEFAULT_CURRENCY; @@ -213,10 +213,10 @@ export const spec = { const syncs = []; if (syncOptions.iframeEnabled) { - syncs.push({type: 'iframe', url: `${SYNC_IFRAME_URL}?${queryParams}`}); + syncs.push({ type: 'iframe', url: `${SYNC_IFRAME_URL}?${queryParams}` }); } if (syncOptions.pixelEnabled) { - syncs.push({type: 'image', url: `${SYNC_PIXEL_URL}?${queryParams}`}); + syncs.push({ type: 'image', url: `${SYNC_PIXEL_URL}?${queryParams}` }); } return syncs; }, diff --git a/modules/seedtagBidAdapter.js b/modules/seedtagBidAdapter.js index 2e9ca96f6f7..5e1dc3308ba 100644 --- a/modules/seedtagBidAdapter.js +++ b/modules/seedtagBidAdapter.js @@ -5,7 +5,7 @@ import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { _map, getWinDimensions, isArray, triggerPixel } from '../src/utils.js'; import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/sharethroughBidAdapter.js b/modules/sharethroughBidAdapter.js index 2f47729de09..406ed77fc2b 100644 --- a/modules/sharethroughBidAdapter.js +++ b/modules/sharethroughBidAdapter.js @@ -5,7 +5,7 @@ import { config } from '../src/config.js'; import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; import { deepAccess, generateUUID, inIframe, isPlainObject, logWarn, mergeDeep } from '../src/utils.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const VERSION = '4.3.0'; const BIDDER_CODE = 'sharethrough'; diff --git a/modules/smaatoBidAdapter.js b/modules/smaatoBidAdapter.js index 23c96a3292a..99bb13ff3a7 100644 --- a/modules/smaatoBidAdapter.js +++ b/modules/smaatoBidAdapter.js @@ -1,11 +1,11 @@ -import {deepAccess, deepSetValue, isEmpty, isNumber, logError, logInfo} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {config} from '../src/config.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {NATIVE_IMAGE_TYPES} from '../src/constants.js'; -import {getAdUnitSizes} from '../libraries/sizeUtils/sizeUtils.js'; -import {ortbConverter} from '../libraries/ortbConverter/converter.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { deepAccess, deepSetValue, isEmpty, isNumber, logError, logInfo } from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { NATIVE_IMAGE_TYPES } from '../src/constants.js'; +import { getAdUnitSizes } from '../libraries/sizeUtils/sizeUtils.js'; +import { ortbConverter } from '../libraries/ortbConverter/converter.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -68,14 +68,15 @@ export const spec = { // separate requests per mediaType SUPPORTED_MEDIA_TYPES.forEach(mediaType => { if ((bid.mediaTypes && bid.mediaTypes[mediaType]) || (mediaType === NATIVE && bid.nativeOrtbRequest)) { - const data = converter.toORTB({bidderRequest, bidRequests: [bid], context: {mediaType}}); + const data = converter.toORTB({ bidderRequest, bidRequests: [bid], context: { mediaType } }); requests.push({ method: 'POST', url: bid.params.endpoint || SMAATO_ENDPOINT, data: JSON.stringify(data), options: { withCredentials: true, - crossOrigin: true}, + crossOrigin: true + }, bidderRequest }) } @@ -125,7 +126,7 @@ export const spec = { advertiserDomains: bid.adomain, networkName: bid.bidderName, agencyId: seatbid.seat, - ...(bid.ext?.dsa && {dsa: bid.ext.dsa}) + ...(bid.ext?.dsa && { dsa: bid.ext.dsa }) } }; @@ -383,7 +384,7 @@ function getNativeMainImageSize(nativeRequest) { function getBidFloor(bidRequest, mediaType, sizes) { if (typeof bidRequest.getFloor === 'function') { const size = sizes.length === 1 ? sizes[0] : '*'; - const floor = bidRequest.getFloor({currency: CURRENCY, mediaType: mediaType, size: size}); + const floor = bidRequest.getFloor({ currency: CURRENCY, mediaType: mediaType, size: size }); if (floor && !isNaN(floor.floor) && (floor.currency === CURRENCY)) { return floor.floor; } diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 9c4460b108a..46765cf217c 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -20,7 +20,7 @@ import { import { VIDEO } from '../src/mediaTypes.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/snigelBidAdapter.js b/modules/snigelBidAdapter.js index 3349ed737eb..44fa0e257c7 100644 --- a/modules/snigelBidAdapter.js +++ b/modules/snigelBidAdapter.js @@ -1,10 +1,10 @@ -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER} from '../src/mediaTypes.js'; -import {deepAccess, isArray, isFn, isPlainObject, inIframe, generateUUID} from '../src/utils.js'; -import {getStorageManager} from '../src/storageManager.js'; +import { config } from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER } from '../src/mediaTypes.js'; +import { deepAccess, isArray, isFn, isPlainObject, inIframe, generateUUID } from '../src/utils.js'; +import { getStorageManager } from '../src/storageManager.js'; import { getViewportSize } from '../libraries/viewport/viewport.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; const BIDDER_CODE = 'snigel'; const GVLID = 1076; @@ -15,7 +15,7 @@ const FLOOR_MATCH_ALL_SIZES = '*'; const SESSION_ID_KEY = '_sn_session_pba'; const getConfig = config.getConfig; -const storageManager = getStorageManager({bidderCode: BIDDER_CODE}); +const storageManager = getStorageManager({ bidderCode: BIDDER_CODE }); const refreshes = {}; const placementCounters = {}; const pageViewStart = new Date().getTime(); @@ -109,7 +109,7 @@ export const spec = { getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent, gppConsent) { const syncUrl = getSyncUrl(responses || []); if (syncUrl && syncOptions.iframeEnabled) { - return [{type: 'iframe', url: getSyncEndpoint(syncUrl, gdprConsent, uspConsent, gppConsent)}]; + return [{ type: 'iframe', url: getSyncEndpoint(syncUrl, gdprConsent, uspConsent, gppConsent) }]; } }, }; diff --git a/modules/sspBCBidAdapter.js b/modules/sspBCBidAdapter.js index 4cf08d8bb1a..ee8c8df847f 100644 --- a/modules/sspBCBidAdapter.js +++ b/modules/sspBCBidAdapter.js @@ -1,11 +1,11 @@ -import {deepAccess, getWinDimensions, getWindowTop, isArray, logInfo, logWarn} from '../src/utils.js'; -import {getDevicePixelRatio} from '../libraries/devicePixelRatio/devicePixelRatio.js'; -import {ajax} from '../src/ajax.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; - -import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; -import {getCurrencyFromBidderRequest} from '../libraries/ortb2Utils/currency.js'; +import { deepAccess, getWinDimensions, getWindowTop, isArray, logInfo, logWarn } from '../src/utils.js'; +import { getDevicePixelRatio } from '../libraries/devicePixelRatio/devicePixelRatio.js'; +import { ajax } from '../src/ajax.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; + +import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js'; const BIDDER_CODE = 'sspBC'; const BIDDER_URL = 'https://ssp.wp.pl/bidder/'; diff --git a/modules/storageControl.ts b/modules/storageControl.ts index 2b5f5db2cdd..9ee860883d2 100644 --- a/modules/storageControl.ts +++ b/modules/storageControl.ts @@ -1,5 +1,5 @@ -import {config} from '../src/config.js'; -import {metadata} from '../libraries/metadata/metadata.js'; +import { config } from '../src/config.js'; +import { metadata } from '../libraries/metadata/metadata.js'; import { ACTIVITY_PARAM_COMPONENT, ACTIVITY_PARAM_COMPONENT_NAME, @@ -13,14 +13,14 @@ import { STORAGE_TYPE_LOCALSTORAGE, type StorageDisclosure as Disclosure } from '../src/storageManager.js'; -import {logWarn, uniques} from '../src/utils.js'; -import {registerActivityControl} from '../src/activities/rules.js'; -import {ACTIVITY_ACCESS_DEVICE} from '../src/activities/activities.js'; -import {addApiMethod} from "../src/prebid.ts"; +import { logWarn, uniques } from '../src/utils.js'; +import { registerActivityControl } from '../src/activities/rules.js'; +import { ACTIVITY_ACCESS_DEVICE } from '../src/activities/activities.js'; +import { addApiMethod } from "../src/prebid.ts"; // @ts-expect-error the ts compiler is confused by build-time renaming of summary.mjs to summary.js, reassure it // eslint-disable-next-line prebid/validate-imports -import {getStorageDisclosureSummary} from "../libraries/storageDisclosure/summary.js"; -import {getGlobal} from "../src/prebidGlobal.ts"; +import { getStorageDisclosureSummary } from "../libraries/storageDisclosure/summary.js"; +import { getGlobal } from "../src/prebidGlobal.ts"; export const ENFORCE_STRICT = 'strict'; export const ENFORCE_ALIAS = 'allowAliases'; @@ -83,9 +83,9 @@ export function checkDisclosure(params, getMatchingDisclosures = getDisclosures) if (disclosures == null) { reason = `Cannot determine if storage key "${key}" is disclosed by "${component}" because the necessary metadata is missing - was it included in the build?` } else { - const {disclosureURLs, matches} = disclosures; + const { disclosureURLs, matches } = disclosures; const moduleName = params[ACTIVITY_PARAM_COMPONENT_NAME] - for (const {componentName} of matches) { + for (const { componentName } of matches) { if (componentName === moduleName) { disclosed = true; } else { @@ -113,11 +113,11 @@ export function checkDisclosure(params, getMatchingDisclosures = getDisclosures) export function storageControlRule(getEnforcement = () => enforcement, check = checkDisclosure) { return function (params) { - const {disclosed, parent, reason} = check(params); + const { disclosed, parent, reason } = check(params); if (disclosed === null) return; if (!disclosed) { const enforcement = getEnforcement() ?? ENFORCE_STRICT; - if (enforcement === ENFORCE_STRICT || (enforcement === ENFORCE_ALIAS && !parent)) return {allow: false, reason}; + if (enforcement === ENFORCE_STRICT || (enforcement === ENFORCE_ALIAS && !parent)) return { allow: false, reason }; if (reason) { logWarn('storageControl:', reason); } @@ -190,7 +190,7 @@ export function dynamicDisclosureCollector() { } } -const {hook: discloseStorageHook, getDisclosures: dynamicDisclosures} = dynamicDisclosureCollector(); +const { hook: discloseStorageHook, getDisclosures: dynamicDisclosures } = dynamicDisclosureCollector(); discloseStorageUse.before(discloseStorageHook); export type StorageDisclosure = Disclosure & { diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 276fd335e7b..9fde4f9d117 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -1,17 +1,17 @@ 'use strict'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER} from '../src/mediaTypes.js'; -import {config} from '../src/config.js'; -import {deepSetValue, getWinDimensions, getWindowSelf, isPlainObject, replaceAuctionPrice} from '../src/utils.js'; -import {getStorageManager} from '../src/storageManager.js'; -import {ajax} from '../src/ajax.js'; -import {ortbConverter} from '../libraries/ortbConverter/converter.js'; -import {getConnectionType} from '../libraries/connectionInfo/connectionUtils.js'; -import {getViewportCoordinates} from '../libraries/viewport/viewport.js'; -import {percentInView} from '../libraries/percentInView/percentInView.js'; -import {getBoundingClientRect} from '../libraries/boundingClientRect/boundingClientRect.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import { deepSetValue, getWinDimensions, getWindowSelf, isPlainObject, replaceAuctionPrice } from '../src/utils.js'; +import { getStorageManager } from '../src/storageManager.js'; +import { ajax } from '../src/ajax.js'; +import { ortbConverter } from '../libraries/ortbConverter/converter.js'; +import { getConnectionType } from '../libraries/connectionInfo/connectionUtils.js'; +import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; +import { percentInView } from '../libraries/percentInView/percentInView.js'; +import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'taboola'; const GVLID = 42; @@ -35,9 +35,9 @@ export const EVENT_ENDPOINT = 'https://beacon.bidder.taboola.com'; * 4. new user set it to 0 */ export const userData = { - storageManager: getStorageManager({bidderCode: BIDDER_CODE}), + storageManager: getStorageManager({ bidderCode: BIDDER_CODE }), getUserId: () => { - const {getFromLocalStorage, getFromCookie, getFromTRC} = userData; + const { getFromLocalStorage, getFromCookie, getFromTRC } = userData; try { return getFromLocalStorage() || getFromCookie() || getFromTRC(); @@ -46,7 +46,7 @@ export const userData = { } }, getFromCookie() { - const {cookiesAreEnabled, getCookie} = userData.storageManager; + const { cookiesAreEnabled, getCookie } = userData.storageManager; if (cookiesAreEnabled()) { const cookieData = getCookie(COOKIE_KEY); let userId; @@ -79,7 +79,7 @@ export const userData = { return value; }, getFromLocalStorage() { - const {hasLocalStorage, localStorageIsEnabled, getDataFromLocalStorage} = userData.storageManager; + const { hasLocalStorage, localStorageIsEnabled, getDataFromLocalStorage } = userData.storageManager; if (hasLocalStorage() && localStorageIsEnabled()) { return getDataFromLocalStorage(STORAGE_KEY); @@ -215,7 +215,7 @@ export const spec = { bidRequests: validBidRequests, context: { auctionId } }); - const {publisherId} = bidRequest.params; + const { publisherId } = bidRequest.params; const url = END_POINT_URL + '?publisher=' + publisherId; return { @@ -240,7 +240,7 @@ export const spec = { if (!serverResponse.body.seatbid || !serverResponse.body.seatbid.length || !serverResponse.body.seatbid[0].bid || !serverResponse.body.seatbid[0].bid.length) { return []; } else { - bids.push(...converter.fromORTB({response: serverResponse.body, request: request.data}).bids); + bids.push(...converter.fromORTB({ response: serverResponse.body, request: request.data }).bids); } return bids; }, @@ -292,16 +292,16 @@ export const spec = { return syncs; }, onTimeout: (timeoutData) => { - ajax(EVENT_ENDPOINT + '/timeout', null, JSON.stringify(timeoutData), {method: 'POST'}); + ajax(EVENT_ENDPOINT + '/timeout', null, JSON.stringify(timeoutData), { method: 'POST' }); }, onBidderError: ({ error, bidderRequest }) => { - ajax(EVENT_ENDPOINT + '/bidError', null, JSON.stringify({error, bidderRequest}), {method: 'POST'}); + ajax(EVENT_ENDPOINT + '/bidError', null, JSON.stringify({ error, bidderRequest }), { method: 'POST' }); }, }; -function getSiteProperties({publisherId}, refererInfo, ortb2) { - const {getPageUrl, getReferrer} = internal; +function getSiteProperties({ publisherId }, refererInfo, ortb2) { + const { getPageUrl, getReferrer } = internal; return { id: publisherId, name: publisherId, @@ -318,7 +318,7 @@ function getSiteProperties({publisherId}, refererInfo, ortb2) { } function fillTaboolaReqData(bidderRequest, bidRequest, data, context) { - const {refererInfo, gdprConsent = {}, uspConsent} = bidderRequest; + const { refererInfo, gdprConsent = {}, uspConsent } = bidderRequest; const site = getSiteProperties(bidRequest.params, refererInfo, bidderRequest.ortb2); const ortb2Device = bidderRequest?.ortb2?.device || {}; @@ -386,7 +386,7 @@ function fillTaboolaReqData(bidderRequest, bidRequest, data, context) { } function fillTaboolaImpData(bid, imp) { - const {tagId, position} = bid.params; + const { tagId, position } = bid.params; imp.banner = getBanners(bid, position); imp.tagid = tagId; @@ -400,7 +400,7 @@ function fillTaboolaImpData(bid, imp) { imp.bidfloorcur = CURRENCY; } } else { - const {bidfloor = null, bidfloorcur = CURRENCY} = bid.params; + const { bidfloor = null, bidfloorcur = CURRENCY } = bid.params; imp.bidfloor = bidfloor; imp.bidfloorcur = bidfloorcur; } diff --git a/modules/tappxBidAdapter.js b/modules/tappxBidAdapter.js index 561b02e6a9a..266a0186e30 100644 --- a/modules/tappxBidAdapter.js +++ b/modules/tappxBidAdapter.js @@ -6,7 +6,7 @@ import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { Renderer } from '../src/Renderer.js'; import { parseDomain } from '../src/refererDetection.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -330,7 +330,7 @@ function buildOneRequest(validBidRequests, bidderRequest) { banner.api = api; - const formatArr = bannerMediaType.sizes.map(size => ({w: size[0], h: size[1]})) + const formatArr = bannerMediaType.sizes.map(size => ({ w: size[0], h: size[1] })) banner.format = Object.assign({}, formatArr); imp.banner = banner; @@ -622,7 +622,7 @@ export function _checkParamDataType(key, value, datatype) { export function _extractPageUrl(validBidRequests, bidderRequest) { const url = bidderRequest?.refererInfo?.page || bidderRequest?.refererInfo?.topmostLocation; - return parseDomain(url, {noLeadingWww: true}); + return parseDomain(url, { noLeadingWww: true }); } registerBidder(spec); diff --git a/modules/theAdxBidAdapter.js b/modules/theAdxBidAdapter.js index 2e8b3549365..bac8645eb0b 100644 --- a/modules/theAdxBidAdapter.js +++ b/modules/theAdxBidAdapter.js @@ -9,7 +9,7 @@ import { } from '../src/adapters/bidderFactory.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/ttdBidAdapter.js b/modules/ttdBidAdapter.js index 94468a7d6bf..944c75ae616 100644 --- a/modules/ttdBidAdapter.js +++ b/modules/ttdBidAdapter.js @@ -4,7 +4,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { isNumber } from '../src/utils.js'; import { getConnectionType } from '../libraries/connectionInfo/connectionUtils.js' -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js index 8eda650ee09..1794de9ed0d 100644 --- a/modules/ucfunnelBidAdapter.js +++ b/modules/ucfunnelBidAdapter.js @@ -1,10 +1,10 @@ import { generateUUID, _each, deepAccess } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO, NATIVE} from '../src/mediaTypes.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js'; import { getStorageManager } from '../src/storageManager.js'; import { config } from '../src/config.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -20,7 +20,7 @@ const VIDEO_CONTEXT = { INSTREAM: 0, OUSTREAM: 2 } -const storage = getStorageManager({bidderCode: BIDDER_CODE}); +const storage = getStorageManager({ bidderCode: BIDDER_CODE }); export const spec = { code: BIDDER_CODE, @@ -233,7 +233,7 @@ function getFloor(bid, size, mediaTypes) { var bidFloor = bid.getFloor({ currency: CURRENCY, mediaType: getMediaType(mediaTypes), - size: (size) ? [ size[0], size[1] ] : '*', + size: (size) ? [size[0], size[1]] : '*', }); if (bidFloor?.currency === CURRENCY) { return bidFloor.floor; diff --git a/modules/underdogmediaBidAdapter.js b/modules/underdogmediaBidAdapter.js index f0fec36df1e..d78782ad3f1 100644 --- a/modules/underdogmediaBidAdapter.js +++ b/modules/underdogmediaBidAdapter.js @@ -8,12 +8,12 @@ import { logWarn, parseSizesInput } from '../src/utils.js'; -import {config} from '../src/config.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {isSlotMatchingAdUnitCode} from '../libraries/gptUtils/gptUtils.js'; +import { config } from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { isSlotMatchingAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; import { percentInView } from '../libraries/percentInView/percentInView.js'; -import {isIframe} from '../libraries/omsUtils/index.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { isIframe } from '../libraries/omsUtils/index.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'underdogmedia'; const UDM_ADAPTER_VERSION = '7.30V'; diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index 01b8760d085..e1da10b1da0 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -2,12 +2,12 @@ * Adapter to send bids to Undertone */ -import {deepAccess, parseUrl, extractDomainFromHost, getWinDimensions} from '../src/utils.js'; +import { deepAccess, parseUrl, extractDomainFromHost, getWinDimensions } from '../src/utils.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getViewportCoordinates } from '../libraries/viewport/viewport.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'undertone'; const URL = 'https://hb.undertone.com/hb'; @@ -42,7 +42,7 @@ function getGdprQueryParams(gdprConsent) { function getBannerCoords(bidRequest) { const element = getAdUnitElement(bidRequest); if (element) { - const {left, top} = getBoundingClientRect(element); + const { left, top } = getBoundingClientRect(element); const viewport = getViewportCoordinates(); return [Math.round(left + (viewport.left || 0)), Math.round(top + (viewport.top || 0))]; } diff --git a/modules/valuadBidAdapter.js b/modules/valuadBidAdapter.js index d6af61d8077..31b320c2557 100644 --- a/modules/valuadBidAdapter.js +++ b/modules/valuadBidAdapter.js @@ -11,8 +11,8 @@ import { import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; import { config } from '../src/config.js'; import { getBoundingBox, percentInView } from '../libraries/percentInView/percentInView.js'; -import {isIframe} from '../libraries/omsUtils/index.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { isIframe } from '../libraries/omsUtils/index.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'valuad'; const GVL_ID = 1478; @@ -105,7 +105,7 @@ const converter = ortbConverter({ if (!adSize) { adSize = [0, 0]; } - const size = {w: adSize[0], h: adSize[1]}; + const size = { w: adSize[0], h: adSize[1] }; const element = getAdUnitElement(bid) || document.getElementById(getGptSlotInfoForAdUnitCode(bid.adUnitCode)?.divId); const viewabilityAmount = _isViewabilityMeasurable(element) ? _getViewability(element, getWindowTop(), size) : 0; @@ -198,7 +198,7 @@ function interpretResponse(response, request) { } // Restore original call, remove logging and safe navigation - const bidResponses = converter.fromORTB({response: response.body, request: request.data}).bids; + const bidResponses = converter.fromORTB({ response: response.body, request: request.data }).bids; return bidResponses; } diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 803b407e6ab..bc7f72833f3 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -7,7 +7,7 @@ import { getStorageManager } from '../src/storageManager.js'; import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; import { getBidFromResponse } from '../libraries/processResponse/index.js'; import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'visx'; const GVLID = 154; diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js index 677ae249571..51bd244009d 100644 --- a/modules/widespaceBidAdapter.js +++ b/modules/widespaceBidAdapter.js @@ -4,7 +4,7 @@ import { deepClone, parseQueryStringParameters, parseSizesInput } from '../src/u import { getStorageManager } from '../src/storageManager.js'; import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingClientRect.js'; import { getConnectionInfo } from '../libraries/connectionInfo/connectionUtils.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'widespace'; const WS_ADAPTER_VERSION = '2.0.1'; diff --git a/modules/yandexBidAdapter.js b/modules/yandexBidAdapter.js index ef7b8910c7d..910a8e75a87 100644 --- a/modules/yandexBidAdapter.js +++ b/modules/yandexBidAdapter.js @@ -7,7 +7,7 @@ import { getBoundingClientRect } from '../libraries/boundingClientRect/boundingC import { ajax } from '../src/ajax.js'; import { config as pbjsConfig } from '../src/config.js'; import { isWebdriverEnabled } from '../libraries/webdriver/webdriver.js'; -import {getAdUnitElement} from '../src/utils/adUnits.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index f2934d32f10..89502f490c3 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -17,7 +17,7 @@ import { import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { Renderer } from '../src/Renderer.js'; -import {getDNT} from '../libraries/dnt/index.js'; +import { getDNT } from '../libraries/dnt/index.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest diff --git a/src/adRendering.ts b/src/adRendering.ts index c031a8555bd..c7b02468f7d 100644 --- a/src/adRendering.ts +++ b/src/adRendering.ts @@ -9,21 +9,21 @@ import { triggerPixel } from './utils.js'; import * as events from './events.js'; -import {AD_RENDER_FAILED_REASON, BID_STATUS, EVENTS, MESSAGES, PB_LOCATOR} from './constants.js'; -import {config} from './config.js'; -import {executeRenderer, isRendererRequired} from './Renderer.js'; -import {VIDEO} from './mediaTypes.js'; -import {auctionManager} from './auctionManager.js'; -import {getCreativeRenderer} from './creativeRenderers.js'; -import {hook} from './hook.js'; -import {fireNativeTrackers} from './native.js'; +import { AD_RENDER_FAILED_REASON, BID_STATUS, EVENTS, MESSAGES, PB_LOCATOR } from './constants.js'; +import { config } from './config.js'; +import { executeRenderer, isRendererRequired } from './Renderer.js'; +import { VIDEO } from './mediaTypes.js'; +import { auctionManager } from './auctionManager.js'; +import { getCreativeRenderer } from './creativeRenderers.js'; +import { hook } from './hook.js'; +import { fireNativeTrackers } from './native.js'; import adapterManager from './adapterManager.js'; -import {useMetrics} from './utils/perfMetrics.js'; -import {filters} from './targeting.js'; -import {EVENT_TYPE_WIN, parseEventTrackers, TRACKER_METHOD_IMG} from './eventTrackers.js'; -import type {Bid} from "./bidfactory.ts"; -import {yieldsIf} from "./utils/yield.ts"; -import {PbPromise} from "./utils/promise.ts"; +import { useMetrics } from './utils/perfMetrics.js'; +import { filters } from './targeting.js'; +import { EVENT_TYPE_WIN, parseEventTrackers, TRACKER_METHOD_IMG } from './eventTrackers.js'; +import type { Bid } from "./bidfactory.ts"; +import { yieldsIf } from "./utils/yield.ts"; +import { PbPromise } from "./utils/promise.ts"; const { AD_RENDER_FAILED, AD_RENDER_SUCCEEDED, STALE_RENDER, BID_WON, EXPIRED_RENDER } = EVENTS; const { EXCEPTION } = AD_RENDER_FAILED_REASON; @@ -117,7 +117,7 @@ type AdRenderSucceededData = { * (Note: Invocation of this function indicates that the render function did not generate an error, it does not guarantee that tracking for this event has occurred yet.) */ export function emitAdRenderSucceeded({ doc, bid, id }) { - const data: AdRenderSucceededData = { doc, bid, adId: id}; + const data: AdRenderSucceededData = { doc, bid, adId: id }; adapterManager.callAdRenderSucceededBidder(bid.adapterCode || bid.bidder, bid); @@ -171,7 +171,7 @@ export function handleCreativeEvent(data, bidResponse) { } } -export function handleNativeMessage(data, bidResponse, {resizeFn, fireTrackers = fireNativeTrackers}) { +export function handleNativeMessage(data, bidResponse, { resizeFn, fireTrackers = fireNativeTrackers }) { switch (data.action) { case 'resizeNativeHeight': resizeFn(data.width, data.height); @@ -202,7 +202,7 @@ type RenderOptions = { } export const getRenderingData = hook('sync', function (bidResponse: Bid, options?: RenderOptions): Record { - const {ad, adUrl, cpm, originalCpm, width, height, instl} = bidResponse + const { ad, adUrl, cpm, originalCpm, width, height, instl } = bidResponse const repl = { AUCTION_PRICE: originalCpm || cpm, CLICKTHROUGH: options?.clickUrl || '' @@ -216,7 +216,7 @@ export const getRenderingData = hook('sync', function (bidResponse: Bid, options }; }) -export const doRender = hook('sync', function({renderFn, resizeFn, bidResponse, options, doc, isMainDocument = doc === document && !inIframe()}) { +export const doRender = hook('sync', function({ renderFn, resizeFn, bidResponse, options, doc, isMainDocument = doc === document && !inIframe() }) { const videoBid = (FEATURES.VIDEO && bidResponse.mediaType === VIDEO) if (isMainDocument || videoBid) { emitAdRenderFail({ @@ -228,8 +228,8 @@ export const doRender = hook('sync', function({renderFn, resizeFn, bidResponse, return; } const data = getRenderingData(bidResponse, options); - renderFn(Object.assign({adId: bidResponse.adId}, data)); - const {width, height} = data; + renderFn(Object.assign({ adId: bidResponse.adId }, data)); + const { width, height } = data; if ((width ?? height) != null) { resizeFn(width, height); } @@ -237,17 +237,17 @@ export const doRender = hook('sync', function({renderFn, resizeFn, bidResponse, doRender.before(function (next, args) { // run renderers from a high priority hook to allow the video module to insert itself between this and "normal" rendering. - const {bidResponse, doc} = args; + const { bidResponse, doc } = args; if (isRendererRequired(bidResponse.renderer)) { executeRenderer(bidResponse.renderer, bidResponse, doc); - emitAdRenderSucceeded({doc, bid: bidResponse, id: bidResponse.adId}) + emitAdRenderSucceeded({ doc, bid: bidResponse, id: bidResponse.adId }) next.bail(); } else { next(args); } }, 100) -export function handleRender({renderFn, resizeFn, adId, options, bidResponse, doc}) { +export function handleRender({ renderFn, resizeFn, adId, options, bidResponse, doc }) { deferRendering(bidResponse, () => { if (bidResponse == null) { emitAdRenderFail({ @@ -273,7 +273,7 @@ export function handleRender({renderFn, resizeFn, adId, options, bidResponse, do } try { - doRender({renderFn, resizeFn, bidResponse, options, doc}); + doRender({ renderFn, resizeFn, bidResponse, options, doc }); } catch (e) { emitAdRenderFail({ reason: AD_RENDER_FAILED_REASON.EXCEPTION, @@ -334,7 +334,7 @@ config.getConfig('auctionOptions', (opts) => { export const renderAdDirect = yieldsIf(() => !legacyRender, function renderAdDirect(doc, adId, options) { let bid; function fail(reason, message) { - emitAdRenderFail(Object.assign({id: adId, bid}, {reason, message})); + emitAdRenderFail(Object.assign({ id: adId, bid }, { reason, message })); } function resizeFn(width, height) { const frame = doc.defaultView?.frameElement; @@ -349,7 +349,7 @@ export const renderAdDirect = yieldsIf(() => !legacyRender, function renderAdDir } } } - const messageHandler = creativeMessageHandler({resizeFn}); + const messageHandler = creativeMessageHandler({ resizeFn }); function waitForDocumentReady(doc) { return new PbPromise((resolve) => { @@ -365,7 +365,7 @@ export const renderAdDirect = yieldsIf(() => !legacyRender, function renderAdDir if (adData.ad && legacyRender) { doc.write(adData.ad); doc.close(); - emitAdRenderSucceeded({doc, bid, id: bid.adId}); + emitAdRenderSucceeded({ doc, bid, id: bid.adId }); } else { PbPromise.all([ getCreativeRenderer(bid), @@ -375,7 +375,7 @@ export const renderAdDirect = yieldsIf(() => !legacyRender, function renderAdDir mkFrame: createIframe, }, doc.defaultView)) .then( - () => emitAdRenderSucceeded({doc, bid, id: bid.adId}), + () => emitAdRenderSucceeded({ doc, bid, id: bid.adId }), (e) => { fail(e?.reason || AD_RENDER_FAILED_REASON.EXCEPTION, e?.message) e?.stack && logError(e); @@ -391,7 +391,7 @@ export const renderAdDirect = yieldsIf(() => !legacyRender, function renderAdDir fail(AD_RENDER_FAILED_REASON.MISSING_DOC_OR_ADID, `missing ${adId ? 'doc' : 'adId'}`); } else { bid = auctionManager.findBidByAdId(adId) - handleRender({renderFn, resizeFn, adId, options: {clickUrl: options?.clickThrough}, bidResponse: bid, doc}); + handleRender({ renderFn, resizeFn, adId, options: { clickUrl: options?.clickThrough }, bidResponse: bid, doc }); } } catch (e) { fail(EXCEPTION, e.message); diff --git a/src/adapters/bidderFactory.ts b/src/adapters/bidderFactory.ts index 1d97253e9e6..bacd954f641 100644 --- a/src/adapters/bidderFactory.ts +++ b/src/adapters/bidderFactory.ts @@ -4,12 +4,12 @@ import adapterManager, { type BidRequest, type ClientBidderRequest } from '../adapterManager.js'; -import {config} from '../config.js'; -import {BannerBid, Bid, BidResponse, createBid} from '../bidfactory.js'; -import {type SyncType, userSync} from '../userSync.js'; -import {nativeBidIsValid} from '../native.js'; -import {isValidVideoBid} from '../video.js'; -import {EVENTS, REJECTION_REASON, DEBUG_MODE} from '../constants.js'; +import { config } from '../config.js'; +import { BannerBid, Bid, BidResponse, createBid } from '../bidfactory.js'; +import { type SyncType, userSync } from '../userSync.js'; +import { nativeBidIsValid } from '../native.js'; +import { isValidVideoBid } from '../video.js'; +import { EVENTS, REJECTION_REASON, DEBUG_MODE } from '../constants.js'; import * as events from '../events.js'; import { @@ -28,20 +28,20 @@ import { getParameterByName, debugTurnedOn } from '../utils.js'; -import {hook} from '../hook.js'; -import {auctionManager} from '../auctionManager.js'; -import {bidderSettings} from '../bidderSettings.js'; -import {useMetrics} from '../utils/perfMetrics.js'; -import {isActivityAllowed} from '../activities/rules.js'; -import {activityParams} from '../activities/activityParams.js'; -import {MODULE_TYPE_BIDDER} from '../activities/modules.js'; -import {ACTIVITY_TRANSMIT_TID, ACTIVITY_TRANSMIT_UFPD} from '../activities/activities.js'; -import type {AnyFunction, Wraps} from "../types/functions.d.ts"; -import type {BidderCode, StorageDisclosure} from "../types/common.d.ts"; -import type {Ajax, AjaxOptions, XHR} from "../ajax.ts"; -import type {AddBidResponse} from "../auction.ts"; -import type {MediaType} from "../mediaTypes.ts"; -import {CONSENT_GDPR, CONSENT_GPP, CONSENT_USP, type ConsentData} from "../consentHandler.ts"; +import { hook } from '../hook.js'; +import { auctionManager } from '../auctionManager.js'; +import { bidderSettings } from '../bidderSettings.js'; +import { useMetrics } from '../utils/perfMetrics.js'; +import { isActivityAllowed } from '../activities/rules.js'; +import { activityParams } from '../activities/activityParams.js'; +import { MODULE_TYPE_BIDDER } from '../activities/modules.js'; +import { ACTIVITY_TRANSMIT_TID, ACTIVITY_TRANSMIT_UFPD } from '../activities/activities.js'; +import type { AnyFunction, Wraps } from "../types/functions.d.ts"; +import type { BidderCode, StorageDisclosure } from "../types/common.d.ts"; +import type { Ajax, AjaxOptions, XHR } from "../ajax.ts"; +import type { AddBidResponse } from "../auction.ts"; +import type { MediaType } from "../mediaTypes.ts"; +import { CONSENT_GDPR, CONSENT_GPP, CONSENT_USP, type ConsentData } from "../consentHandler.ts"; /** * This file aims to support Adapters during the Prebid 0.x -> 1.x transition. @@ -197,7 +197,7 @@ export function registerBidder(spec: BidderSpec) { } } -export const guardTids: any = memoize(({bidderCode}) => { +export const guardTids: any = memoize(({ bidderCode }) => { const tidsAllowed = isActivityAllowed(ACTIVITY_TRANSMIT_TID, activityParams(MODULE_TYPE_BIDDER, bidderCode)); function get(target, prop, receiver) { if (TIDS.hasOwnProperty(prop)) { @@ -215,7 +215,7 @@ export const guardTids: any = memoize(({bidderCode}) => { }); return proxy; } - const bidRequest = memoize((br) => privateAccessProxy(br, {get}), (arg) => arg.bidId); + const bidRequest = memoize((br) => privateAccessProxy(br, { get }), (arg) => arg.bidId); /** * Return a view on bidd(er) requests where auctionId/transactionId are nulled if the bidder is not allowed `transmitTid`. * @@ -326,7 +326,7 @@ export function newBidder(spec: BidderSpec) { } adapterManager.callBidderError(spec.code, error, bidderRequest) events.emit(EVENTS.BIDDER_ERROR, { error, bidderRequest }); - logError(`Server call for ${spec.code} failed: ${errorMessage} ${error.status}. Continuing without bids.`, {bidRequests: validBidRequests}); + logError(`Server call for ${spec.code} failed: ${errorMessage} ${error.status}. Continuing without bids.`, { bidRequests: validBidRequests }); }, onBid: (bidResponse) => { const bidRequest = bidRequestMap[bidResponse.requestId]; @@ -404,7 +404,7 @@ export const processBidderRequests = hook('async', function, ajax: Ajax, wrapCallback: (fn: T) => Wraps, - {onRequest, onResponse, onError, onBid, onCompletion}: { + { onRequest, onResponse, onError, onBid, onCompletion }: { /** * invoked once for each HTTP request built by the adapter - with the raw request */ @@ -615,7 +615,7 @@ declare module '../bidfactory' { } // check that the bid has a width and height set -function validBidSize(adUnitCode, bid: BannerBid, {index = auctionManager.index} = {}) { +function validBidSize(adUnitCode, bid: BannerBid, { index = auctionManager.index } = {}) { if ((bid.width || parseInt(bid.width, 10) === 0) && (bid.height || parseInt(bid.height, 10) === 0)) { bid.width = parseInt(bid.width, 10); bid.height = parseInt(bid.height, 10); @@ -637,7 +637,7 @@ function validBidSize(adUnitCode, bid: BannerBid, {index = auctionManager.index} // if a banner impression has one valid size, we assign that size to any bid // response that does not explicitly set width or height if (parsedSizes.length === 1) { - const [ width, height ] = parsedSizes[0].split('x'); + const [width, height] = parsedSizes[0].split('x'); bid.width = parseInt(width, 10); bid.height = parseInt(height, 10); return true; @@ -647,7 +647,7 @@ function validBidSize(adUnitCode, bid: BannerBid, {index = auctionManager.index} } // Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored. -export function isValid(adUnitCode: string, bid: Bid, {index = auctionManager.index} = {}) { +export function isValid(adUnitCode: string, bid: Bid, { index = auctionManager.index } = {}) { function hasValidKeys() { const bidKeys = Object.keys(bid); return COMMON_BID_RESPONSE_KEYS.every(key => bidKeys.includes(key) && ![undefined, null].includes(bid[key])); @@ -672,15 +672,15 @@ export function isValid(adUnitCode: string, bid: Bid, {index = auctionManager.in return false; } - if (FEATURES.NATIVE && bid.mediaType === 'native' && !nativeBidIsValid(bid, {index})) { + if (FEATURES.NATIVE && bid.mediaType === 'native' && !nativeBidIsValid(bid, { index })) { logError(errorMessage('Native bid missing some required properties.')); return false; } - if (FEATURES.VIDEO && bid.mediaType === 'video' && !isValidVideoBid(bid, {index})) { + if (FEATURES.VIDEO && bid.mediaType === 'video' && !isValidVideoBid(bid, { index })) { logError(errorMessage(`Video bid does not have required vastUrl or renderer property`)); return false; } - if (bid.mediaType === 'banner' && !validBidSize(adUnitCode, bid, {index})) { + if (bid.mediaType === 'banner' && !validBidSize(adUnitCode, bid, { index })) { logError(errorMessage(`Banner bids require a width and height`)); return false; } diff --git a/src/auction.ts b/src/auction.ts index a6aa0c85665..4f805603c55 100644 --- a/src/auction.ts +++ b/src/auction.ts @@ -10,32 +10,32 @@ import { parseUrl, timestamp } from './utils.js'; -import {getPriceBucketString} from './cpmBucketManager.js'; -import {isNativeResponse, setNativeResponseProperties} from './native.js'; -import {batchAndStore, storeLocally} from './videoCache.js'; -import {Renderer} from './Renderer.js'; -import {config} from './config.js'; -import {userSync} from './userSync.js'; -import {hook, ignoreCallbackArg} from './hook.js'; -import {OUTSTREAM} from './video.js'; -import {AUDIO, VIDEO} from './mediaTypes.js'; -import {auctionManager} from './auctionManager.js'; -import {bidderSettings} from './bidderSettings.js'; +import { getPriceBucketString } from './cpmBucketManager.js'; +import { isNativeResponse, setNativeResponseProperties } from './native.js'; +import { batchAndStore, storeLocally } from './videoCache.js'; +import { Renderer } from './Renderer.js'; +import { config } from './config.js'; +import { userSync } from './userSync.js'; +import { hook, ignoreCallbackArg } from './hook.js'; +import { OUTSTREAM } from './video.js'; +import { AUDIO, VIDEO } from './mediaTypes.js'; +import { auctionManager } from './auctionManager.js'; +import { bidderSettings } from './bidderSettings.js'; import * as events from './events.js'; -import adapterManager, {activityParams, type BidderRequest, type BidRequest} from './adapterManager.js'; -import {EVENTS, GRANULARITY_OPTIONS, JSON_MAPPING, REJECTION_REASON, S2S, TARGETING_KEYS} from './constants.js'; -import {defer, PbPromise} from './utils/promise.js'; -import {type Metrics, useMetrics} from './utils/perfMetrics.js'; -import {adjustCpm} from './utils/cpm.js'; -import {getGlobal} from './prebidGlobal.js'; -import {ttlCollection} from './utils/ttlCollection.js'; -import {getMinBidCacheTTL, onMinBidCacheTTLChange} from './bidTTL.js'; -import type {Bid, BidResponse} from "./bidfactory.ts"; -import type {AdUnitCode, BidderCode, Identifier, ORTBFragments} from './types/common.d.ts'; -import type {TargetingMap} from "./targeting.ts"; -import type {AdUnit, AdUnitDefinition} from "./adUnits.ts"; -import type {MediaType} from "./mediaTypes.ts"; -import type {VideoContext} from "./video.ts"; +import adapterManager, { activityParams, type BidderRequest, type BidRequest } from './adapterManager.js'; +import { EVENTS, GRANULARITY_OPTIONS, JSON_MAPPING, REJECTION_REASON, S2S, TARGETING_KEYS } from './constants.js'; +import { defer, PbPromise } from './utils/promise.js'; +import { type Metrics, useMetrics } from './utils/perfMetrics.js'; +import { adjustCpm } from './utils/cpm.js'; +import { getGlobal } from './prebidGlobal.js'; +import { ttlCollection } from './utils/ttlCollection.js'; +import { getMinBidCacheTTL, onMinBidCacheTTLChange } from './bidTTL.js'; +import type { Bid, BidResponse } from "./bidfactory.ts"; +import type { AdUnitCode, BidderCode, Identifier, ORTBFragments } from './types/common.d.ts'; +import type { TargetingMap } from "./targeting.ts"; +import type { AdUnit, AdUnitDefinition } from "./adUnits.ts"; +import type { MediaType } from "./mediaTypes.ts"; +import type { VideoContext } from "./video.ts"; import { isActivityAllowed } from './activities/rules.js'; import { ACTIVITY_ADD_BID_RESPONSE } from './activities/activities.js'; import { MODULE_TYPE_BIDDER } from './activities/modules.ts'; @@ -164,13 +164,13 @@ declare module './config' { auctionOptions?: AuctionOptionsConfig; priceGranularity?: (typeof GRANULARITY_OPTIONS)[keyof typeof GRANULARITY_OPTIONS]; customPriceBucket?: PriceBucketConfig; - mediaTypePriceGranularity?: {[K in MediaType]?: PriceBucketConfig} & {[K in VideoContext as `${typeof VIDEO}-${K}`]?: PriceBucketConfig}; + mediaTypePriceGranularity?: { [K in MediaType]?: PriceBucketConfig } & { [K in VideoContext as `${typeof VIDEO}-${K}`]?: PriceBucketConfig }; } } export const beforeInitAuction = hook('sync', (auction) => {}) -export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels, auctionId, ortb2Fragments, metrics}: AuctionOptions) { +export function newAuction({ adUnits, adUnitCodes, callback, cbTimeout, labels, auctionId, ortb2Fragments, metrics }: AuctionOptions) { metrics = useMetrics(metrics); const _adUnits = adUnits; const _labels = labels; @@ -503,7 +503,7 @@ export type AddBidResponse = { reject(adUnitCode: AdUnitCode, bid: BidResponse, reason: typeof REJECTION_REASON[keyof typeof REJECTION_REASON]) : void; } -export function auctionCallbacks(auctionDone, auctionInstance, {index = auctionManager.index} = {}) { +export function auctionCallbacks(auctionDone, auctionInstance, { index = auctionManager.index } = {}) { let outstandingBidsAdded = 0; let allAdapterCalledDone = false; const bidderRequestsDone = new Set(); @@ -612,7 +612,7 @@ export function addBidToAuction(auctionInstance, bidResponse: Bid) { } // Video bids may fail if the cache is down, or there's trouble on the network. -function tryAddVideoAudioBid(auctionInstance, bidResponse, afterBidAdded, {index = auctionManager.index} = {}) { +function tryAddVideoAudioBid(auctionInstance, bidResponse, afterBidAdded, { index = auctionManager.index } = {}) { let addBid = true; const videoMediaType = index.getMediaTypes({ @@ -729,7 +729,7 @@ declare module './bidfactory' { /** * Add timing properties to a bid response */ -function addBidTimingProperties(bidResponse: Partial, {index = auctionManager.index} = {}) { +function addBidTimingProperties(bidResponse: Partial, { index = auctionManager.index } = {}) { const bidderRequest = index.getBidderRequest(bidResponse); const start = (bidderRequest && bidderRequest.start) || bidResponse.requestTimestamp; @@ -743,10 +743,10 @@ function addBidTimingProperties(bidResponse: Partial, {index = auctionManag /** * Augment `bidResponse` with properties that are common across all bids - including rejected bids. */ -function addCommonResponseProperties(bidResponse: Partial, adUnitCode: string, {index = auctionManager.index} = {}) { +function addCommonResponseProperties(bidResponse: Partial, adUnitCode: string, { index = auctionManager.index } = {}) { const adUnit = index.getAdUnit(bidResponse); - addBidTimingProperties(bidResponse, {index}) + addBidTimingProperties(bidResponse, { index }) Object.assign(bidResponse, { cpm: parseFloat(bidResponse.cpm) || 0, @@ -762,7 +762,7 @@ function addCommonResponseProperties(bidResponse: Partial, adUnitCode: stri /** * Add additional bid response properties that are universal for all _accepted_ bids. */ -function getPreparedBidForAuction(bid: Partial, {index = auctionManager.index} = {}): Bid { +function getPreparedBidForAuction(bid: Partial, { index = auctionManager.index } = {}): Bid { // Let listeners know that now is the time to adjust the bid, if they want to. // // CAREFUL: Publishers rely on certain bid properties to be available (like cpm), @@ -845,7 +845,7 @@ export function getMediaTypeGranularity(mediaType, mediaTypes, mediaTypePriceGra * @param {object} obj.index * @returns {string} granularity */ -export const getPriceGranularity = (bid, {index = auctionManager.index} = {}) => { +export const getPriceGranularity = (bid, { index = auctionManager.index } = {}) => { // Use the config value 'mediaTypeGranularity' if it has been set for mediaType, else use 'priceGranularity' const mediaTypeGranularity = getMediaTypeGranularity(bid.mediaType, index.getMediaTypes(bid), config.getConfig('mediaTypePriceGranularity')); const granularity = (typeof bid.mediaType === 'string' && mediaTypeGranularity) ? ((typeof mediaTypeGranularity === 'string') ? mediaTypeGranularity : 'custom') : config.getConfig('priceGranularity'); @@ -1050,7 +1050,7 @@ export function getStandardBidderSettings(mediaType, bidderCode) { return standardSettings; } -export function getKeyValueTargetingPairs(bidderCode, custBidObj: Bid, {index = auctionManager.index} = {}) { +export function getKeyValueTargetingPairs(bidderCode, custBidObj: Bid, { index = auctionManager.index } = {}) { if (!custBidObj) { return {}; } diff --git a/src/fpd/enrichment.ts b/src/fpd/enrichment.ts index 2780ba2d09d..4d3f8327e63 100644 --- a/src/fpd/enrichment.ts +++ b/src/fpd/enrichment.ts @@ -1,6 +1,6 @@ -import {hook} from '../hook.js'; -import {getRefererInfo, parseDomain} from '../refererDetection.js'; -import {findRootDomain} from './rootDomain.js'; +import { hook } from '../hook.js'; +import { getRefererInfo, parseDomain } from '../refererDetection.js'; +import { findRootDomain } from './rootDomain.js'; import { deepSetValue, deepAccess, @@ -12,14 +12,14 @@ import { mergeDeep, memoize } from '../utils.js'; -import {config} from '../config.js'; -import {getHighEntropySUA, getLowEntropySUA} from './sua.js'; -import {PbPromise} from '../utils/promise.js'; -import {CLIENT_SECTIONS, clientSectionChecker, hasSection} from './oneClient.js'; -import {isActivityAllowed} from '../activities/rules.js'; -import {activityParams} from '../activities/activityParams.js'; -import {ACTIVITY_ACCESS_DEVICE} from '../activities/activities.js'; -import {MODULE_TYPE_PREBID} from '../activities/modules.js'; +import { config } from '../config.js'; +import { getHighEntropySUA, getLowEntropySUA } from './sua.js'; +import { PbPromise } from '../utils/promise.js'; +import { CLIENT_SECTIONS, clientSectionChecker, hasSection } from './oneClient.js'; +import { isActivityAllowed } from '../activities/rules.js'; +import { activityParams } from '../activities/activityParams.js'; +import { ACTIVITY_ACCESS_DEVICE } from '../activities/activities.js'; +import { MODULE_TYPE_PREBID } from '../activities/modules.js'; import { getViewportSize } from '../../libraries/viewport/viewport.js'; export const dep = { @@ -152,7 +152,7 @@ const ENRICHMENTS = { const h = getWinDimensions().screen.height; // vpw and vph are the viewport dimensions of the browser window - const {width: vpw, height: vph} = getViewportSize(); + const { width: vpw, height: vph } = getViewportSize(); const device = { w, @@ -218,7 +218,7 @@ export const getMetaTagKeywords = memoize(() => { // Enrichment of properties common across dooh, app and site - will be dropped into whatever // section is appropriate function clientEnrichment(ortb2, ri) { - const domain = parseDomain(ri.page, {noLeadingWww: true}); + const domain = parseDomain(ri.page, { noLeadingWww: true }); const keywords = new Set(); if (config.getConfig('firstPartyData.keywords.meta') ?? true) { (getMetaTagKeywords() ?? []).forEach(key => keywords.add(key)); diff --git a/src/native.ts b/src/native.ts index 007b96a3a4c..c8e27fc6fcc 100644 --- a/src/native.ts +++ b/src/native.ts @@ -12,7 +12,7 @@ import { triggerPixel } from './utils.js'; -import {auctionManager} from './auctionManager.js'; +import { auctionManager } from './auctionManager.js'; import { NATIVE_ASSET_TYPES, NATIVE_IMAGE_TYPES, @@ -20,17 +20,17 @@ import { NATIVE_KEYS_THAT_ARE_NOT_ASSETS, PREBID_NATIVE_DATA_KEYS_TO_ORTB } from './constants.js'; -import {NATIVE} from './mediaTypes.js'; -import {getRenderingData} from './adRendering.js'; -import {getCreativeRendererSource, PUC_MIN_VERSION} from './creativeRenderers.js'; -import {EVENT_TYPE_IMPRESSION, EVENT_TYPE_VIEWABLE, parseEventTrackers, TRACKER_METHOD_IMG, TRACKER_METHOD_JS} from './eventTrackers.js'; -import type {Link, NativeRequest, NativeResponse} from "./types/ortb/native.d.ts"; -import type {Size} from "./types/common.d.ts"; -import type {Ext} from "./types/ortb/common.d.ts"; -import type {BidResponse, NativeBidResponse} from "./bidfactory.ts"; -import type {AdUnit} from "./adUnits.ts"; - -type LegacyAssets = Omit<{[K in keyof (typeof NATIVE_KEYS)]: unknown}, (typeof NATIVE_KEYS_THAT_ARE_NOT_ASSETS)[number]>; +import { NATIVE } from './mediaTypes.js'; +import { getRenderingData } from './adRendering.js'; +import { getCreativeRendererSource, PUC_MIN_VERSION } from './creativeRenderers.js'; +import { EVENT_TYPE_IMPRESSION, EVENT_TYPE_VIEWABLE, parseEventTrackers, TRACKER_METHOD_IMG, TRACKER_METHOD_JS } from './eventTrackers.js'; +import type { Link, NativeRequest, NativeResponse } from "./types/ortb/native.d.ts"; +import type { Size } from "./types/common.d.ts"; +import type { Ext } from "./types/ortb/common.d.ts"; +import type { BidResponse, NativeBidResponse } from "./bidfactory.ts"; +import type { AdUnit } from "./adUnits.ts"; + +type LegacyAssets = Omit<{ [K in keyof (typeof NATIVE_KEYS)]: unknown }, (typeof NATIVE_KEYS_THAT_ARE_NOT_ASSETS)[number]>; type LegacyImageAssets = { icon: unknown, image: unknown }; type LegacyImageAssetResponse = { @@ -293,7 +293,7 @@ export const hasNonNativeBidder = adUnit => * bid Native bid to validate * @return {Boolean} If object is valid */ -export function nativeBidIsValid(bid, {index = auctionManager.index} = {}) { +export function nativeBidIsValid(bid, { index = auctionManager.index } = {}) { const adUnit = index.getAdUnit(bid); if (!adUnit) { return false; } const ortbRequest = adUnit.nativeOrtbRequest @@ -355,9 +355,9 @@ export function fireNativeTrackers(message, bidResponse) { return message.action; } -export function fireImpressionTrackers(nativeResponse, bidResponse, {runMarkup = (mkup) => insertHtmlIntoIframe(mkup), fetchURL = triggerPixel} = {}) { +export function fireImpressionTrackers(nativeResponse, bidResponse, { runMarkup = (mkup) => insertHtmlIntoIframe(mkup), fetchURL = triggerPixel } = {}) { const filteredEventTrackers = filterEventTrackers(nativeResponse, bidResponse); - let {[TRACKER_METHOD_IMG]: img = [], [TRACKER_METHOD_JS]: js = []} = parseEventTrackers( + let { [TRACKER_METHOD_IMG]: img = [], [TRACKER_METHOD_JS]: js = [] } = parseEventTrackers( filteredEventTrackers || [] )[EVENT_TYPE_IMPRESSION] || {}; @@ -376,7 +376,7 @@ export function fireImpressionTrackers(nativeResponse, bidResponse, {runMarkup = } } -export function fireClickTrackers(nativeResponse, assetId = null, {fetchURL = triggerPixel} = {}) { +export function fireClickTrackers(nativeResponse, assetId = null, { fetchURL = triggerPixel } = {}) { // legacy click tracker if (!assetId) { (nativeResponse.link?.clicktrackers || []).forEach(url => fetchURL(url)); @@ -438,7 +438,7 @@ function getNativeAssets(nativeProps, keys, ext = false) { if (ext === false && key === 'ext') { assets.push(...getNativeAssets(value, keys, true)); } else if (ext || NATIVE_KEYS.hasOwnProperty(key)) { - assets.push({key, value: getAssetValue(value)}); + assets.push({ key, value: getAssetValue(value) }); } }); return assets; @@ -458,7 +458,7 @@ export function getNativeRenderingData(bid, adUnit, keys) { return data; } -function assetsMessage(data, adObject, keys, {index = auctionManager.index} = {}) { +function assetsMessage(data, adObject, keys, { index = auctionManager.index } = {}) { const msg: any = { message: 'assetResponse', adId: data.adId, @@ -472,7 +472,7 @@ function assetsMessage(data, adObject, keys, {index = auctionManager.index} = {} msg.renderer = getCreativeRendererSource(adObject); msg.rendererVersion = PUC_MIN_VERSION; if (keys != null) { - renderData.assets = renderData.assets.filter(({key}) => keys.includes(key)) + renderData.assets = renderData.assets.filter(({ key }) => keys.includes(key)) } } else { renderData = getNativeRenderingData(adObject, index.getAdUnit(adObject), keys); diff --git a/src/prebid.ts b/src/prebid.ts index 6b30ca192ca..c2d21b9c4eb 100644 --- a/src/prebid.ts +++ b/src/prebid.ts @@ -1,6 +1,6 @@ /** @module pbjs */ -import {getGlobal, type PrebidJS} from './prebidGlobal.js'; +import { getGlobal, type PrebidJS } from './prebidGlobal.js'; import { deepAccess, deepClone, @@ -24,22 +24,22 @@ import { uniques, unsupportedBidderMessage } from './utils.js'; -import {listenMessagesFromCreative} from './secureCreatives.js'; -import {userSync} from './userSync.js'; -import {config} from './config.js'; -import {auctionManager} from './auctionManager.js'; -import {isBidUsable, targeting} from './targeting.js'; -import {hook, wrapHook} from './hook.js'; -import {loadSession} from './debugging.js'; -import {storageCallbacks} from './storageManager.js'; -import adapterManager, {type AliasBidderOptions, type BidRequest, getS2SBidderSet} from './adapterManager.js'; -import {BID_STATUS, EVENTS, NATIVE_KEYS} from './constants.js'; -import type {Event, EventHandler, EventIDs} from "./events.js"; +import { listenMessagesFromCreative } from './secureCreatives.js'; +import { userSync } from './userSync.js'; +import { config } from './config.js'; +import { auctionManager } from './auctionManager.js'; +import { isBidUsable, targeting } from './targeting.js'; +import { hook, wrapHook } from './hook.js'; +import { loadSession } from './debugging.js'; +import { storageCallbacks } from './storageManager.js'; +import adapterManager, { type AliasBidderOptions, type BidRequest, getS2SBidderSet } from './adapterManager.js'; +import { BID_STATUS, EVENTS, NATIVE_KEYS } from './constants.js'; +import type { Event, EventHandler, EventIDs } from "./events.js"; import * as events from './events.js'; -import {type Metrics, newMetrics, useMetrics} from './utils/perfMetrics.js'; -import {type Defer, defer, PbPromise} from './utils/promise.js'; -import {enrichFPD} from './fpd/enrichment.js'; -import {allConsent} from './consentHandler.js'; +import { type Metrics, newMetrics, useMetrics } from './utils/perfMetrics.js'; +import { type Defer, defer, PbPromise } from './utils/promise.js'; +import { enrichFPD } from './fpd/enrichment.js'; +import { allConsent } from './consentHandler.js'; import { insertLocatorFrame, markBidAsRendered, @@ -47,24 +47,24 @@ import { renderAdDirect, renderIfDeferred } from './adRendering.js'; -import {getHighestCpm} from './utils/reducers.js'; -import {fillVideoDefaults, ORTB_VIDEO_PARAMS} from './video.js'; -import {ORTB_BANNER_PARAMS} from './banner.js'; -import {BANNER, VIDEO} from './mediaTypes.js'; -import {delayIfPrerendering} from './utils/prerendering.js'; -import {type BidAdapter, type BidderSpec, newBidder} from './adapters/bidderFactory.js'; -import {normalizeFPD} from './fpd/normalize.js'; -import type {Bid} from "./bidfactory.ts"; -import type {AdUnit, AdUnitDefinition, BidderParams} from "./adUnits.ts"; -import type {AdUnitCode, BidderCode, ByAdUnit, Identifier, ORTBFragments} from "./types/common.d.ts"; -import type {ORTBRequest} from "./types/ortb/request.d.ts"; -import type {DeepPartial} from "./types/objects.d.ts"; -import type {AnyFunction, Wraps} from "./types/functions.d.ts"; -import type {BidderScopedSettings, BidderSettings} from "./bidderSettings.ts"; -import {fillAudioDefaults, ORTB_AUDIO_PARAMS} from './audio.ts'; - -import {getGlobalVarName} from "./buildOptions.ts"; -import {yieldAll} from "./utils/yield.ts"; +import { getHighestCpm } from './utils/reducers.js'; +import { fillVideoDefaults, ORTB_VIDEO_PARAMS } from './video.js'; +import { ORTB_BANNER_PARAMS } from './banner.js'; +import { BANNER, VIDEO } from './mediaTypes.js'; +import { delayIfPrerendering } from './utils/prerendering.js'; +import { type BidAdapter, type BidderSpec, newBidder } from './adapters/bidderFactory.js'; +import { normalizeFPD } from './fpd/normalize.js'; +import type { Bid } from "./bidfactory.ts"; +import type { AdUnit, AdUnitDefinition, BidderParams } from "./adUnits.ts"; +import type { AdUnitCode, BidderCode, ByAdUnit, Identifier, ORTBFragments } from "./types/common.d.ts"; +import type { ORTBRequest } from "./types/ortb/request.d.ts"; +import type { DeepPartial } from "./types/objects.d.ts"; +import type { AnyFunction, Wraps } from "./types/functions.d.ts"; +import type { BidderScopedSettings, BidderSettings } from "./bidderSettings.ts"; +import { fillAudioDefaults, ORTB_AUDIO_PARAMS } from './audio.ts'; + +import { getGlobalVarName } from "./buildOptions.ts"; +import { yieldAll } from "./utils/yield.ts"; const pbjsInstance = getGlobal(); const { triggerUserSyncs } = userSync; @@ -172,14 +172,14 @@ function validateBannerMediaType(adUnit: AdUnit) { banner.format = format; try { formatSizes = format - .filter(({w, h, wratio, hratio}) => { + .filter(({ w, h, wratio, hratio }) => { if ((w ?? h) != null && (wratio ?? hratio) != null) { logWarn(`Ad unit banner.format specifies both w/h and wratio/hratio`, adUnit); return false; } return (w != null && h != null) || (wratio != null && hratio != null); }) - .map(({w, h, wratio, hratio}) => [w ?? wratio, h ?? hratio]); + .map(({ w, h, wratio, hratio }) => [w ?? wratio, h ?? hratio]); } catch (e) { logError(`Invalid format definition on ad unit ${adUnit.code}`, format); } @@ -352,7 +352,7 @@ function validateAdUnit(adUnitDef: AdUnitDefinition): AdUnit { return null; } if (adUnit.ortb2Imp != null && (bids == null || bids.length === 0)) { - adUnit.bids = [{bidder: null}]; // the 'null' bidder is treated as an s2s-only placeholder by adapterManager + adUnit.bids = [{ bidder: null }]; // the 'null' bidder is treated as an s2s-only placeholder by adapterManager logMessage(msg(`defines 'adUnit.ortb2Imp' with no 'adUnit.bids'; it will be seen only by S2S adapters`)); } @@ -785,17 +785,17 @@ export const requestBids = (function() { adUnitCodes = adUnitCodes.filter(uniques); return Object.assign({ adUnitCodes - }, adUnits.reduce(({included, excluded}, adUnit) => { + }, adUnits.reduce(({ included, excluded }, adUnit) => { (adUnitCodes.includes(adUnit.code) ? included : excluded).push(adUnit); - return {included, excluded}; - }, {included: [], excluded: []})) + return { included, excluded }; + }, { included: [], excluded: [] })) } } const delegate = hook('async', function (reqBidOptions: PrivRequestBidsOptions): void { let { bidsBackHandler, timeout, adUnits, adUnitCodes, labels, auctionId, ttlBuffer, ortb2, metrics, defer } = reqBidOptions ?? {}; const cbTimeout = timeout || config.getConfig('bidderTimeout'); - ({included: adUnits, adUnitCodes} = filterAdUnits(adUnits, adUnitCodes)); + ({ included: adUnits, adUnitCodes } = filterAdUnits(adUnits, adUnitCodes)); let ortb2Fragments = { global: mergeDeep({}, config.getAnyConfig('ortb2') || {}, ortb2 || {}), bidder: Object.fromEntries(Object.entries(config.getBidderConfig()).map(([bidder, cfg]) => [bidder, deepClone(cfg.ortb2)]).filter(([_, ortb2]) => ortb2 != null)) @@ -804,7 +804,7 @@ export const requestBids = (function() { enrichFPD(PbPromise.resolve(ortb2Fragments.global)).then(global => { ortb2Fragments.global = global; - return startAuction({bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes, labels, auctionId, ttlBuffer, ortb2Fragments, metrics, defer}); + return startAuction({ bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes, labels, auctionId, ttlBuffer, ortb2Fragments, metrics, defer }); }) }, 'requestBids'); @@ -821,7 +821,7 @@ export const requestBids = (function() { const metrics = newMetrics(); metrics.checkpoint('requestBids'); - const {included, excluded, adUnitCodes} = filterAdUnits(adUnits, options.adUnitCodes); + const { included, excluded, adUnitCodes } = filterAdUnits(adUnits, options.adUnitCodes); events.emit(REQUEST_BIDS, Object.assign(options, { adUnits: included, @@ -837,7 +837,7 @@ export const requestBids = (function() { // what it means for an event handler to modify adUnitCodes - so don't allow it adUnitCodes, metrics, - defer: defer({promiseFactory: (r) => new Promise(r)}) + defer: defer({ promiseFactory: (r) => new Promise(r) }) }); delegate.call(this, req); return req.defer.promise; @@ -1151,7 +1151,7 @@ type MarkWinningBidAsUsedOptions = ({ /** * Mark the winning bid as used, should only be used in conjunction with video */ -function markWinningBidAsUsed({adId, adUnitCode, analytics = false, events = false}: MarkWinningBidAsUsedOptions) { +function markWinningBidAsUsed({ adId, adUnitCode, analytics = false, events = false }: MarkWinningBidAsUsedOptions) { let bids; if (adUnitCode && adId == null) { bids = targeting.getWinningBids(adUnitCode); @@ -1263,7 +1263,7 @@ addApiMethod('processQueue', processQueue, false); * Manually trigger billing for a winning bid, idendified either by ad ID or ad unit code. * Used in conjunction with `adUnit.deferBilling`. */ -function triggerBilling({adId, adUnitCode}: { +function triggerBilling({ adId, adUnitCode }: { adId?: string; adUnitCode?: AdUnitCode }) { diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 0c609b66608..4c81217b215 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -3,9 +3,9 @@ access to a publisher page from creative payloads. */ -import {getAllAssetsMessage, getAssetMessage} from './native.js'; -import {BID_STATUS, MESSAGES} from './constants.js'; -import {isApnGetTagDefined, isGptPubadsDefined, logError, logWarn} from './utils.js'; +import { getAllAssetsMessage, getAssetMessage } from './native.js'; +import { BID_STATUS, MESSAGES } from './constants.js'; +import { isApnGetTagDefined, isGptPubadsDefined, logError, logWarn } from './utils.js'; import { deferRendering, handleCreativeEvent, @@ -13,10 +13,10 @@ import { handleRender, markWinner } from './adRendering.js'; -import {getCreativeRendererSource, PUC_MIN_VERSION} from './creativeRenderers.js'; -import {PbPromise} from './utils/promise.js'; -import {getAdUnitElement} from './utils/adUnits.js'; -import {auctionManager} from './auctionManager.js'; +import { getCreativeRendererSource, PUC_MIN_VERSION } from './creativeRenderers.js'; +import { PbPromise } from './utils/promise.js'; +import { getAdUnitElement } from './utils/adUnits.js'; +import { auctionManager } from './auctionManager.js'; const { REQUEST, RESPONSE, NATIVE, EVENT } = MESSAGES; @@ -57,7 +57,7 @@ export function getReplier(ev) { function ensureAdId(adId, reply) { return function (data, ...args) { - return reply(Object.assign({}, data, {adId}), ...args); + return reply(Object.assign({}, data, { adId }), ...args); } } @@ -81,7 +81,7 @@ function getResizer(adId, bidResponse) { // the first is the one that was requested and is tied to the element // the second is the one that is being rendered (sometimes different, e.g. in some paapi setups) return function (width, height) { - resizeRemoteCreative({...bidResponse, width, height, adId}); + resizeRemoteCreative({ ...bidResponse, width, height, adId }); } } function handleRenderRequest(reply, message, bidResponse) { @@ -118,7 +118,7 @@ function handleNativeRequest(reply, data, adObject) { deferRendering(adObject, () => reply(getAllAssetsMessage(data, adObject))); break; default: - handleNativeMessage(data, adObject, {resizeFn: getResizer(data.adId, adObject)}); + handleNativeMessage(data, adObject, { resizeFn: getResizer(data.adId, adObject) }); markWinner(adObject); } } @@ -151,7 +151,7 @@ export function resizeAnchor(ins, width, height) { // wait until GPT has set dimensions on the ins, otherwise our changes will be overridden const resizer = setInterval(() => { let done = false; - Object.entries({width, height}) + Object.entries({ width, height }) .forEach(([dimension, newValue]) => { if (/\d+px/.test(ins.style[dimension])) { ins.style[dimension] = getDimension(newValue); @@ -166,7 +166,7 @@ export function resizeAnchor(ins, width, height) { }) } -export function resizeRemoteCreative({instl, element, adId, adUnitCode, width, height}) { +export function resizeRemoteCreative({ instl, element, adId, adUnitCode, width, height }) { // do not resize interstitials - the creative frame takes the full screen and sizing of the ad should // be handled within it. if (instl) return; @@ -189,7 +189,7 @@ export function resizeRemoteCreative({instl, element, adId, adUnitCode, width, h function getElementByAdUnit(elmType) { const id = getElementIdBasedOnAdServer(adId, adUnitCode); - const parentDivEle = id == null ? getAdUnitElement({element, adUnitCode}) : document.getElementById(id); + const parentDivEle = id == null ? getAdUnitElement({ element, adUnitCode }) : document.getElementById(id); return parentDivEle && parentDivEle.querySelector(elmType); } diff --git a/src/targeting.ts b/src/targeting.ts index 636c5d5787c..7547665eb1f 100644 --- a/src/targeting.ts +++ b/src/targeting.ts @@ -1,10 +1,10 @@ -import {auctionManager} from './auctionManager.js'; -import {getBufferedTTL} from './bidTTL.js'; -import {bidderSettings} from './bidderSettings.js'; -import {config} from './config.js'; -import {BID_STATUS, DEFAULT_TARGETING_KEYS, EVENTS, JSON_MAPPING, TARGETING_KEYS} from './constants.js'; +import { auctionManager } from './auctionManager.js'; +import { getBufferedTTL } from './bidTTL.js'; +import { bidderSettings } from './bidderSettings.js'; +import { config } from './config.js'; +import { BID_STATUS, DEFAULT_TARGETING_KEYS, EVENTS, JSON_MAPPING, TARGETING_KEYS } from './constants.js'; import * as events from './events.js'; -import {hook} from './hook.js'; +import { hook } from './hook.js'; import { deepAccess, deepClone, @@ -21,11 +21,11 @@ import { timestamp, uniques, } from './utils.js'; -import {getHighestCpm, getOldestHighestCpmBid} from './utils/reducers.js'; -import type {Bid} from './bidfactory.ts'; -import type {AdUnitCode, ByAdUnit, Identifier} from './types/common.d.ts'; -import type {DefaultTargeting} from './auction.ts'; -import {lock} from "./targeting/lock.ts"; +import { getHighestCpm, getOldestHighestCpmBid } from './utils/reducers.js'; +import type { Bid } from './bidfactory.ts'; +import type { AdUnitCode, ByAdUnit, Identifier } from './types/common.d.ts'; +import type { DefaultTargeting } from './auction.ts'; +import { lock } from "./targeting/lock.ts"; var pbTargetingKeys = []; @@ -323,7 +323,7 @@ export function newTargeting(auctionManager) { }); logMessage(`Attempting to set targeting-map for slot: ${slot.getSlotElementId()} with targeting-map:`, targetingSet[targetId]); const targetingMap = Object.assign({}, resetMap, targetingSet[targetId]); - slot.setConfig({targeting: targetingMap} as any); + slot.setConfig({ targeting: targetingMap } as any); lock.lock(targetingSet[targetId]); }) }) @@ -395,7 +395,7 @@ export function newTargeting(auctionManager) { // pt${n} keys should not be uppercased keywordsObj[key] = astTargeting[targetId][key]; } - window.apntag.setKeywords(targetId, keywordsObj, {overrideKeyValue: true}); + window.apntag.setKeywords(targetId, keywordsObj, { overrideKeyValue: true }); } }) } @@ -423,7 +423,7 @@ export function newTargeting(auctionManager) { (deals || allowedSendAllBidTargeting.indexOf(key) !== -1))); if (targetingValue) { - result.push({[bid.adUnitCode]: targetingValue}) + result.push({ [bid.adUnitCode]: targetingValue }) } } return result; @@ -537,7 +537,7 @@ export function newTargeting(auctionManager) { } }); - return {filteredBids, customKeysByUnit}; + return { filteredBids, customKeysByUnit }; } // warn about conflicting configuration @@ -732,11 +732,11 @@ export function newTargeting(auctionManager) { if (customKeysForUnit) { Object.keys(customKeysForUnit).forEach(key => { - if (key && customKeysForUnit[key]) targeting.push({[key]: customKeysForUnit[key]}); + if (key && customKeysForUnit[key]) targeting.push({ [key]: customKeysForUnit[key] }); }) } - acc.push({[newBid.adUnitCode]: targeting}); + acc.push({ [newBid.adUnitCode]: targeting }); return acc; }, []); @@ -746,7 +746,7 @@ export function newTargeting(auctionManager) { return keys.reduce((targeting, key) => { const value = bid.adserverTargeting[key]; if (value) { - targeting.push({[`${key}_${bid.bidderCode}`.substring(0, MAX_DFP_KEYLENGTH)]: [bid.adserverTargeting[key]]}) + targeting.push({ [`${key}_${bid.bidderCode}`.substring(0, MAX_DFP_KEYLENGTH)]: [bid.adserverTargeting[key]] }) } return targeting; }, []); @@ -755,7 +755,7 @@ export function newTargeting(auctionManager) { function getVersionTargeting(adUnitCodes) { let version = config.getConfig('targetingControls.version'); if (version === false) return []; - return adUnitCodes.map(au => ({[au]: [{[TARGETING_KEYS.VERSION]: [version ?? DEFAULT_HB_VER]}]})); + return adUnitCodes.map(au => ({ [au]: [{ [TARGETING_KEYS.VERSION]: [version ?? DEFAULT_HB_VER] }] })); } function getAdUnitTargeting(adUnitCodes) { @@ -769,7 +769,7 @@ export function newTargeting(auctionManager) { return Object.keys(aut) .map(function(key) { if (isStr(aut[key])) aut[key] = aut[key].split(',').map(s => s.trim()); - if (!isArray(aut[key])) aut[key] = [ aut[key] ]; + if (!isArray(aut[key])) aut[key] = [aut[key]]; return { [key]: aut[key] }; }); } @@ -779,7 +779,7 @@ export function newTargeting(auctionManager) { .reduce((result, adUnit) => { const targetingValues = getTargetingValues(adUnit); - if (targetingValues)result.push({[adUnit.code]: targetingValues}); + if (targetingValues)result.push({ [adUnit.code]: targetingValues }); return result; }, []); } diff --git a/src/utils/adUnits.ts b/src/utils/adUnits.ts index 96e412910ab..d9f4196e19c 100644 --- a/src/utils/adUnits.ts +++ b/src/utils/adUnits.ts @@ -1,6 +1,6 @@ -import type {AdUnitDefinition} from "../adUnits.ts"; -import type {BidRequest} from "../adapterManager.ts"; -import type {Bid} from "../bidfactory.ts"; +import type { AdUnitDefinition } from "../adUnits.ts"; +import type { BidRequest } from "../adapterManager.ts"; +import type { Bid } from "../bidfactory.ts"; export function getAdUnitElement(bidRequest: BidRequest): HTMLElement export function getAdUnitElement(bidResponse: Bid): HTMLElement diff --git a/test/spec/libraries/placementPositionInfo_spec.js b/test/spec/libraries/placementPositionInfo_spec.js index 56991fd2430..bfd886b8898 100644 --- a/test/spec/libraries/placementPositionInfo_spec.js +++ b/test/spec/libraries/placementPositionInfo_spec.js @@ -44,7 +44,7 @@ describe('placementPositionInfo', function () { percentInViewStub = sandbox.stub(percentInViewLib, 'getViewability'); cleanObjStub = sandbox.stub(utils, 'cleanObj').callsFake(obj => obj); sandbox.stub(winDimensions, 'getWinDimensions').returns(mockWindow); - viewportOffset = {x: 0, y: 0}; + viewportOffset = { x: 0, y: 0 }; sandbox.stub(percentInViewLib, 'getViewportOffset').callsFake(() => viewportOffset); }); @@ -401,7 +401,7 @@ describe('placementPositionInfo', function () { describe('iframe coordinate translation', function () { beforeEach(() => { - sandbox.stub(adUnits, 'getAdUnitElement').returns({id: 'test'}) + sandbox.stub(adUnits, 'getAdUnitElement').returns({ id: 'test' }) mockWindow.innerHeight = 1000; mockDocument.body = { scrollHeight: 2000, offsetHeight: 1800 @@ -409,7 +409,7 @@ describe('placementPositionInfo', function () { mockDocument.documentElement = { clientHeight: 1900, scrollHeight: 2100, offsetHeight: 1950 } }); it('should apply iframe offset when running inside a friendly iframe', function () { - viewportOffset = {y: 200}; + viewportOffset = { y: 200 }; getBoundingClientRectStub.callsFake((el) => { return { top: 100, bottom: 200, height: 100 }; @@ -425,7 +425,7 @@ describe('placementPositionInfo', function () { }); it('should calculate correct distance when element is below viewport with iframe offset', function () { - viewportOffset = {y: 500}; + viewportOffset = { y: 500 }; getBoundingClientRectStub.callsFake((el) => { return { top: 600, bottom: 700, height: 100 }; @@ -441,7 +441,7 @@ describe('placementPositionInfo', function () { }); it('should calculate negative distance when element is above viewport with iframe offset', function () { - viewportOffset = {y: -600}; + viewportOffset = { y: -600 }; getBoundingClientRectStub.callsFake((el) => { return { top: 100, bottom: 200, height: 100 }; diff --git a/test/spec/libraries/storageDisclosure_spec.js b/test/spec/libraries/storageDisclosure_spec.js index 8020b41a233..98a98700484 100644 --- a/test/spec/libraries/storageDisclosure_spec.js +++ b/test/spec/libraries/storageDisclosure_spec.js @@ -1,4 +1,4 @@ -import {getStorageDisclosureSummary} from '../../../libraries/storageDisclosure/summary.js'; +import { getStorageDisclosureSummary } from '../../../libraries/storageDisclosure/summary.js'; describe('storageDisclosure', () => { let moduleMeta; @@ -37,7 +37,7 @@ describe('storageDisclosure', () => { disclosures: { url1: { disclosures: [ - {identifier: 'foo'} + { identifier: 'foo' } ] } } @@ -46,7 +46,7 @@ describe('storageDisclosure', () => { disclosures: { url2: { disclosures: [ - {identifier: 'bar'} + { identifier: 'bar' } ] } } @@ -70,7 +70,7 @@ describe('storageDisclosure', () => { const disclosures = { url: { disclosures: [ - {identifier: 'foo'} + { identifier: 'foo' } ] } } diff --git a/test/spec/modules/33acrossIdSystem_spec.js b/test/spec/modules/33acrossIdSystem_spec.js index ec793bad020..6c7c98d197c 100644 --- a/test/spec/modules/33acrossIdSystem_spec.js +++ b/test/spec/modules/33acrossIdSystem_spec.js @@ -530,7 +530,7 @@ describe('33acrossIdSystem', () => { storeFpid: false, hem: '33acrossIdHmValue+' }, - enabledStorageTypes: [ 'html5' ], + enabledStorageTypes: ['html5'], storage: {} }); @@ -1542,7 +1542,7 @@ describe('33acrossIdSystem', () => { pid: '12345', storeFpid: false }, - enabledStorageTypes: [ 'html5' ], + enabledStorageTypes: ['html5'], storage: {} }); diff --git a/test/spec/modules/adkernelBidAdapter_spec.js b/test/spec/modules/adkernelBidAdapter_spec.js index ec2c3a5dc3c..34afb59ec4a 100644 --- a/test/spec/modules/adkernelBidAdapter_spec.js +++ b/test/spec/modules/adkernelBidAdapter_spec.js @@ -1,14 +1,14 @@ -import {expect} from 'chai'; -import {spec} from 'modules/adkernelBidAdapter'; +import { expect } from 'chai'; +import { spec } from 'modules/adkernelBidAdapter'; import * as utils from 'src/utils'; -import {NATIVE, BANNER, VIDEO} from 'src/mediaTypes'; -import {config} from 'src/config'; -import {parseDomain} from '../../../src/refererDetection.js'; +import { NATIVE, BANNER, VIDEO } from 'src/mediaTypes'; +import { config } from 'src/config'; +import { parseDomain } from '../../../src/refererDetection.js'; describe('Adkernel adapter', function () { const bid1_zone1 = { bidder: 'adkernel', - params: {zoneId: 1, host: 'rtb.adkernel.com'}, + params: { zoneId: 1, host: 'rtb.adkernel.com' }, adUnitCode: 'ad-unit-1', bidId: 'Bid_01', bidderRequestId: 'req-001', @@ -25,7 +25,7 @@ describe('Adkernel adapter', function () { } }; const bid2_zone2 = { bidder: 'adkernel', - params: {zoneId: 2, host: 'rtb.adkernel.com'}, + params: { zoneId: 2, host: 'rtb.adkernel.com' }, adUnitCode: 'ad-unit-2', bidId: 'Bid_02', bidderRequestId: 'req-001', @@ -39,13 +39,13 @@ describe('Adkernel adapter', function () { { source: 'crwdcntrl.net', uids: [ - {atype: 1, id: '97d09fbba28542b7acbb6317c9534945a702b74c5993c352f332cfe83f40cdd9'} + { atype: 1, id: '97d09fbba28542b7acbb6317c9534945a702b74c5993c352f332cfe83f40cdd9' } ] } ] }; const bid3_host2 = { bidder: 'adkernel', - params: {zoneId: 1, host: 'rtb-private.adkernel.com'}, + params: { zoneId: 1, host: 'rtb-private.adkernel.com' }, adUnitCode: 'ad-unit-2', bidId: 'Bid_02', bidderRequestId: 'req-001', @@ -57,7 +57,7 @@ describe('Adkernel adapter', function () { } }; const bid_without_zone = { bidder: 'adkernel', - params: {host: 'rtb-private.adkernel.com'}, + params: { host: 'rtb-private.adkernel.com' }, adUnitCode: 'ad-unit-1', bidId: 'Bid_W', bidderRequestId: 'req-002', @@ -69,7 +69,7 @@ describe('Adkernel adapter', function () { } }; const bid_without_host = { bidder: 'adkernel', - params: {zoneId: 1}, + params: { zoneId: 1 }, adUnitCode: 'ad-unit-1', bidId: 'Bid_W', bidderRequestId: 'req-002', @@ -81,7 +81,7 @@ describe('Adkernel adapter', function () { } }; const bid_with_wrong_zoneId = { bidder: 'adkernel', - params: {zoneId: 'wrong id', host: 'rtb.adkernel.com'}, + params: { zoneId: 'wrong id', host: 'rtb.adkernel.com' }, adUnitCode: 'ad-unit-2', bidId: 'Bid_02', bidderRequestId: 'req-002', @@ -115,10 +115,10 @@ describe('Adkernel adapter', function () { adUnitCode: 'ad-unit-1' }; const bid_multiformat = { bidder: 'adkernel', - params: {zoneId: 1, host: 'rtb.adkernel.com'}, + params: { zoneId: 1, host: 'rtb.adkernel.com' }, mediaTypes: { - banner: {sizes: [[300, 250], [300, 200]]}, - video: {context: 'instream', playerSize: [[640, 480]]} + banner: { sizes: [[300, 250], [300, 200]] }, + video: { context: 'instream', playerSize: [[640, 480]] } }, adUnitCode: 'ad-unit-1', transactionId: 'f82c64b8-c602-42a4-9791-4a268f6559ed', @@ -128,7 +128,7 @@ describe('Adkernel adapter', function () { }; const bid_native = { bidder: 'adkernel', - params: {zoneId: 1, host: 'rtb.adkernel.com'}, + params: { zoneId: 1, host: 'rtb.adkernel.com' }, mediaTypes: { native: { title: { @@ -143,7 +143,7 @@ describe('Adkernel adapter', function () { }, icon: { required: true, - aspect_ratios: [{min_width: 50, min_height: 50}] + aspect_ratios: [{ min_width: 50, min_height: 50 }] }, image: { required: true, @@ -176,25 +176,24 @@ describe('Adkernel adapter', function () { ver: '1.2', assets: [ { - id: 0, required: 1, title: {len: 80} - }, { - id: 1, required: 1, data: {type: 2}}, + id: 0, required: 1, title: { len: 80 } + }, { id: 1, required: 1, data: { type: 2 } }, { - id: 2, required: 1, data: {type: 10} + id: 2, required: 1, data: { type: 10 } }, { - id: 3, required: 1, img: {type: 1, wmin: 50, hmin: 50} + id: 3, required: 1, img: { type: 1, wmin: 50, hmin: 50 } }, { - id: 4, required: 1, img: {type: 3, w: 300, h: 200} + id: 4, required: 1, img: { type: 3, w: 300, h: 200 } }, { - id: 5, required: 0, data: {type: 3} + id: 5, required: 0, data: { type: 3 } }, { - id: 6, required: 0, data: {type: 6} + id: 6, required: 0, data: { type: 6 } }, { - id: 7, required: 0, data: {type: 12} + id: 7, required: 0, data: { type: 12 } }, { - id: 8, required: 0, data: {type: 1} + id: 8, required: 0, data: { type: 1 } }, { - id: 9, required: 0, data: {type: 11} + id: 9, required: 0, data: { type: 11 } } ], privacy: 1 @@ -223,7 +222,7 @@ describe('Adkernel adapter', function () { }] }], ext: { - adk_usersync: [{type: 1, url: 'https://adk.sync.com/sync'}] + adk_usersync: [{ type: 1, url: 'https://adk.sync.com/sync' }] } }; const videoBidResponse = { id: '47ce4badcf7482', @@ -258,7 +257,7 @@ describe('Adkernel adapter', function () { const usersyncOnlyResponse = { id: 'nobid1', ext: { - adk_usersync: [{type: 2, url: 'https://adk.sync.com/sync'}] + adk_usersync: [{ type: 2, url: 'https://adk.sync.com/sync' }] } }; const nativeResponse = { id: '56fbc713-b737-4651-9050-13376aed9818', @@ -271,15 +270,15 @@ describe('Adkernel adapter', function () { adm: JSON.stringify({ native: { assets: [ - {id: 0, title: {text: 'Title'}}, - {id: 3, data: {value: 'Description'}}, - {id: 4, data: {value: 'Additional description'}}, - {id: 1, img: {url: 'http://rtb.com/thumbnail?i=pTuOlf5KHUo_0&imgt=icon', w: 50, h: 50}}, - {id: 2, img: {url: 'http://rtb.com/thumbnail?i=pTuOlf5KHUo_0', w: 300, h: 200}}, - {id: 5, data: {value: 'Sponsor.com'}}, - {id: 14, data: {value: 'displayurl.com'}} + { id: 0, title: { text: 'Title' } }, + { id: 3, data: { value: 'Description' } }, + { id: 4, data: { value: 'Additional description' } }, + { id: 1, img: { url: 'http://rtb.com/thumbnail?i=pTuOlf5KHUo_0&imgt=icon', w: 50, h: 50 } }, + { id: 2, img: { url: 'http://rtb.com/thumbnail?i=pTuOlf5KHUo_0', w: 300, h: 200 } }, + { id: 5, data: { value: 'Sponsor.com' } }, + { id: 14, data: { value: 'displayurl.com' } } ], - link: {url: 'http://rtb.com/click?i=pTuOlf5KHUo_0'}, + link: { url: 'http://rtb.com/click?i=pTuOlf5KHUo_0' }, imptrackers: ['http://rtb.com/win?i=pTuOlf5KHUo_0&f=imp'] } }), @@ -337,7 +336,7 @@ describe('Adkernel adapter', function () { }); function buildBidderRequest(url = 'https://example.com/index.html', params = {}) { - return Object.assign({}, params, {refererInfo: {page: url, domain: parseDomain(url), reachedTop: true}, timeout: 3000, bidderCode: 'adkernel'}); + return Object.assign({}, params, { refererInfo: { page: url, domain: parseDomain(url), reachedTop: true }, timeout: 3000, bidderCode: 'adkernel' }); } const DEFAULT_BIDDER_REQUEST = buildBidderRequest(); @@ -395,7 +394,7 @@ describe('Adkernel adapter', function () { it('should have w/h', function () { expect(bidRequest.imp[0].banner).to.have.property('format'); - expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}, {w: 300, h: 200}]); + expect(bidRequest.imp[0].banner.format).to.be.eql([{ w: 300, h: 250 }, { w: 300, h: 200 }]); }); it('should respect secure connection', function () { @@ -437,21 +436,22 @@ describe('Adkernel adapter', function () { it('should contain gdpr-related information if consent is configured', function () { const [_, bidRequests] = buildRequest([bid1_zone1], buildBidderRequest('https://example.com/index.html', { - gdprConsent: {gdprApplies: true, consentString: 'test-consent-string', vendorData: {}}, + gdprConsent: { gdprApplies: true, consentString: 'test-consent-string', vendorData: {} }, uspConsent: '1YNN', - gppConsent: {gppString: 'DBABMA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA', applicableSections: [2]}} + gppConsent: { gppString: 'DBABMA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA', applicableSections: [2] } + } )); const bidRequest = bidRequests[0]; expect(bidRequest).to.have.property('regs'); - expect(bidRequest.regs.ext).to.be.eql({'gdpr': 1, 'us_privacy': '1YNN'}); + expect(bidRequest.regs.ext).to.be.eql({ 'gdpr': 1, 'us_privacy': '1YNN' }); expect(bidRequest.regs.gpp).to.be.eql('DBABMA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA'); expect(bidRequest.regs.gpp_sid).to.be.eql([2]); expect(bidRequest).to.have.property('user'); - expect(bidRequest.user.ext).to.be.eql({'consent': 'test-consent-string'}); + expect(bidRequest.user.ext).to.be.eql({ 'consent': 'test-consent-string' }); }); it('should contain coppa if configured', function () { - config.setConfig({coppa: true}); + config.setConfig({ coppa: true }); const [_, bidRequests] = buildRequest([bid1_zone1]); const bidRequest = bidRequests[0]; expect(bidRequest).to.have.property('regs'); @@ -459,10 +459,10 @@ describe('Adkernel adapter', function () { }); it('should\'t contain consent string if gdpr isn\'t applied', function () { - const [_, bidRequests] = buildRequest([bid1_zone1], buildBidderRequest('https://example.com/index.html', {gdprConsent: {gdprApplies: false}})); + const [_, bidRequests] = buildRequest([bid1_zone1], buildBidderRequest('https://example.com/index.html', { gdprConsent: { gdprApplies: false } })); const bidRequest = bidRequests[0]; expect(bidRequest).to.have.property('regs'); - expect(bidRequest.regs.ext).to.be.eql({'gdpr': 0}); + expect(bidRequest.regs.ext).to.be.eql({ 'gdpr': 0 }); expect(bidRequest).to.not.have.property('user'); }); @@ -543,7 +543,7 @@ describe('Adkernel adapter', function () { expect(bidRequests[0].imp[1].id).to.be.not.eql(bidRequests[0].imp[0].id); }); it('should collect ads back to same requestId', function() { - const bids = spec.interpretResponse({body: multiformat_response}, pbRequests[0]); + const bids = spec.interpretResponse({ body: multiformat_response }, pbRequests[0]); expect(bids).to.have.length(2); expect(bids[0].requestId).to.be.eql('Bid_01'); expect(bids[0].mediaType).to.be.eql('banner'); @@ -649,7 +649,7 @@ describe('Adkernel adapter', function () { describe('responses processing', function () { it('should return fully-initialized banner bid-response', function () { const [pbRequests, _] = buildRequest([bid1_zone1]); - const resp = spec.interpretResponse({body: bannerBidResponse}, pbRequests[0])[0]; + const resp = spec.interpretResponse({ body: bannerBidResponse }, pbRequests[0])[0]; expect(resp).to.have.property('requestId', 'Bid_01'); expect(resp).to.have.property('cpm', 3.01); expect(resp).to.have.property('width', 300); @@ -666,7 +666,7 @@ describe('Adkernel adapter', function () { it('should return fully-initialized video bid-response', function () { const [pbRequests, _] = buildRequest([bid_video]); - const resp = spec.interpretResponse({body: videoBidResponse}, pbRequests[0])[0]; + const resp = spec.interpretResponse({ body: videoBidResponse }, pbRequests[0])[0]; expect(resp).to.have.property('requestId', 'Bid_Video'); expect(resp.mediaType).to.equal(VIDEO); expect(resp.cpm).to.equal(0.00145); @@ -677,7 +677,7 @@ describe('Adkernel adapter', function () { it('should support vast xml in adm', function () { const [pbRequests, _] = buildRequest([bid_video]); - const resp = spec.interpretResponse({body: videoBidResponseWithAdm}, pbRequests[0])[0]; + const resp = spec.interpretResponse({ body: videoBidResponseWithAdm }, pbRequests[0])[0]; expect(resp).to.have.property('requestId', 'Bid_Video'); expect(resp.mediaType).to.equal(VIDEO); expect(resp.cpm).to.equal(0.00145); @@ -689,27 +689,27 @@ describe('Adkernel adapter', function () { it('should add nurl as pixel for banner response', function () { const [pbRequests, _] = buildRequest([bid1_zone1]); - const resp = spec.interpretResponse({body: bannerBidResponse}, pbRequests[0])[0]; + const resp = spec.interpretResponse({ body: bannerBidResponse }, pbRequests[0])[0]; const expectedNurl = bannerBidResponse.seatbid[0].bid[0].nurl + '&px=1'; expect(resp.ad).to.have.string(expectedNurl); }); it('should handle bidresponse with user-sync only', function () { const [pbRequests, _] = buildRequest([bid1_zone1]); - const resp = spec.interpretResponse({body: usersyncOnlyResponse}, pbRequests[0]); + const resp = spec.interpretResponse({ body: usersyncOnlyResponse }, pbRequests[0]); expect(resp).to.have.length(0); }); it('should perform usersync', function () { - let syncs = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, []); + let syncs = spec.getUserSyncs({ iframeEnabled: true, pixelEnabled: true }, []); expect(syncs).to.have.length(0); - syncs = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: false}, [{body: bannerBidResponse}]); + syncs = spec.getUserSyncs({ iframeEnabled: false, pixelEnabled: false }, [{ body: bannerBidResponse }]); expect(syncs).to.have.length(0); - syncs = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, [{body: bannerBidResponse}]); + syncs = spec.getUserSyncs({ iframeEnabled: true, pixelEnabled: true }, [{ body: bannerBidResponse }]); expect(syncs).to.have.length(1); expect(syncs[0]).to.have.property('type', 'iframe'); expect(syncs[0]).to.have.property('url', 'https://adk.sync.com/sync'); - syncs = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, [{body: usersyncOnlyResponse}]); + syncs = spec.getUserSyncs({ iframeEnabled: false, pixelEnabled: true }, [{ body: usersyncOnlyResponse }]); expect(syncs).to.have.length(1); expect(syncs[0]).to.have.property('type', 'image'); expect(syncs[0]).to.have.property('url', 'https://adk.sync.com/sync'); @@ -735,21 +735,21 @@ describe('Adkernel adapter', function () { const request = JSON.parse(bidRequests[0].imp[0].native.request); expect(request).to.have.property('ver', '1.2'); expect(request.assets).to.have.length(10); - expect(request.assets[0]).to.be.eql({id: 0, required: 1, title: {len: 80}}); - expect(request.assets[1]).to.be.eql({id: 1, required: 1, data: {type: 2}}); - expect(request.assets[2]).to.be.eql({id: 2, required: 1, data: {type: 10}}); - expect(request.assets[3]).to.be.eql({id: 3, required: 1, img: {wmin: 50, hmin: 50, type: 1}}); - expect(request.assets[4]).to.be.eql({id: 4, required: 1, img: {w: 300, h: 200, type: 3}}); - expect(request.assets[5]).to.be.eql({id: 5, required: 0, data: {type: 3}}); - expect(request.assets[6]).to.be.eql({id: 6, required: 0, data: {type: 6}}); - expect(request.assets[7]).to.be.eql({id: 7, required: 0, data: {type: 12}}); - expect(request.assets[8]).to.be.eql({id: 8, required: 0, data: {type: 1}}); - expect(request.assets[9]).to.be.eql({id: 9, required: 0, data: {type: 11}}); + expect(request.assets[0]).to.be.eql({ id: 0, required: 1, title: { len: 80 } }); + expect(request.assets[1]).to.be.eql({ id: 1, required: 1, data: { type: 2 } }); + expect(request.assets[2]).to.be.eql({ id: 2, required: 1, data: { type: 10 } }); + expect(request.assets[3]).to.be.eql({ id: 3, required: 1, img: { wmin: 50, hmin: 50, type: 1 } }); + expect(request.assets[4]).to.be.eql({ id: 4, required: 1, img: { w: 300, h: 200, type: 3 } }); + expect(request.assets[5]).to.be.eql({ id: 5, required: 0, data: { type: 3 } }); + expect(request.assets[6]).to.be.eql({ id: 6, required: 0, data: { type: 6 } }); + expect(request.assets[7]).to.be.eql({ id: 7, required: 0, data: { type: 12 } }); + expect(request.assets[8]).to.be.eql({ id: 8, required: 0, data: { type: 1 } }); + expect(request.assets[9]).to.be.eql({ id: 9, required: 0, data: { type: 11 } }); }); it('native response processing', () => { const [pbRequests, _] = buildRequest([bid_native]); - const resp = spec.interpretResponse({body: nativeResponse}, pbRequests[0])[0]; + const resp = spec.interpretResponse({ body: nativeResponse }, pbRequests[0])[0]; expect(resp).to.have.property('requestId', 'Bid_01'); expect(resp).to.have.property('cpm', 2.25); expect(resp).to.have.property('currency', 'EUR'); @@ -765,15 +765,15 @@ describe('Adkernel adapter', function () { expect(resp.native.ortb).to.be.eql({ assets: [ - {id: 0, title: {text: 'Title'}}, - {id: 3, data: {value: 'Description'}}, - {id: 4, data: {value: 'Additional description'}}, - {id: 1, img: {url: 'http://rtb.com/thumbnail?i=pTuOlf5KHUo_0&imgt=icon', w: 50, h: 50}}, - {id: 2, img: {url: 'http://rtb.com/thumbnail?i=pTuOlf5KHUo_0', w: 300, h: 200}}, - {id: 5, data: {value: 'Sponsor.com'}}, - {id: 14, data: {value: 'displayurl.com'}} + { id: 0, title: { text: 'Title' } }, + { id: 3, data: { value: 'Description' } }, + { id: 4, data: { value: 'Additional description' } }, + { id: 1, img: { url: 'http://rtb.com/thumbnail?i=pTuOlf5KHUo_0&imgt=icon', w: 50, h: 50 } }, + { id: 2, img: { url: 'http://rtb.com/thumbnail?i=pTuOlf5KHUo_0', w: 300, h: 200 } }, + { id: 5, data: { value: 'Sponsor.com' } }, + { id: 14, data: { value: 'displayurl.com' } } ], - link: {url: 'http://rtb.com/click?i=pTuOlf5KHUo_0'}, + link: { url: 'http://rtb.com/click?i=pTuOlf5KHUo_0' }, imptrackers: ['http://rtb.com/win?i=pTuOlf5KHUo_0&f=imp'] }); }); @@ -788,7 +788,7 @@ describe('Adkernel adapter', function () { }); it('should trigger pixel for nurl', () => { const [pbRequests, _] = buildRequest([bid_video]); - const bid = spec.interpretResponse({body: videoBidResponseWithAdm}, pbRequests[0])[0]; + const bid = spec.interpretResponse({ body: videoBidResponseWithAdm }, pbRequests[0])[0]; spec.onBidWon(bid); expect(utils.triggerPixel.callCount).to.equal(1); }); diff --git a/test/spec/modules/bidViewability_spec.js b/test/spec/modules/bidViewability_spec.js index 04858f261e7..da2430e9d33 100644 --- a/test/spec/modules/bidViewability_spec.js +++ b/test/spec/modules/bidViewability_spec.js @@ -3,7 +3,7 @@ import { config } from 'src/config.js'; import * as events from 'src/events.js'; import * as utils from 'src/utils.js'; import * as sinon from 'sinon'; -import {expect, spy} from 'chai'; +import { expect, spy } from 'chai'; import * as prebidGlobal from 'src/prebidGlobal.js'; import { EVENTS } from 'src/constants.js'; import adapterManager, { gdprDataHandler, uspDataHandler } from 'src/adapterManager.js'; @@ -79,7 +79,7 @@ describe('#bidViewability', function() { return (adUnitCode) => ('AD-' + slot.getAdUnitPath()) === adUnitCode; } }); - const newWinningBid = Object.assign({}, PBJS_WINNING_BID, {adUnitCode: 'AD-' + PBJS_WINNING_BID.adUnitCode}); + const newWinningBid = Object.assign({}, PBJS_WINNING_BID, { adUnitCode: 'AD-' + PBJS_WINNING_BID.adUnitCode }); // Needs pbjs.getWinningBids to be implemented with match winningBidsArray.push(newWinningBid); const wb = bidViewability.getMatchingWinningBidForGPTSlot(gptSlot); @@ -131,7 +131,7 @@ describe('#bidViewability', function() { }); it('fire pixels if mentioned in module config', function() { - const moduleConfig = {firePixels: true}; + const moduleConfig = { firePixels: true }; bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); PBJS_WINNING_BID.vurls.forEach((url, i) => { const call = triggerPixelSpy.getCall(i); @@ -142,7 +142,7 @@ describe('#bidViewability', function() { it('USP: should include the us_privacy key when USP Consent is available', function () { const uspDataHandlerStub = sinon.stub(uspDataHandler, 'getConsentData'); uspDataHandlerStub.returns('1YYY'); - const moduleConfig = {firePixels: true}; + const moduleConfig = { firePixels: true }; bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); PBJS_WINNING_BID.vurls.forEach((url, i) => { const call = triggerPixelSpy.getCall(i); @@ -155,7 +155,7 @@ describe('#bidViewability', function() { }); it('USP: should not include the us_privacy key when USP Consent is not available', function () { - const moduleConfig = {firePixels: true}; + const moduleConfig = { firePixels: true }; bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); PBJS_WINNING_BID.vurls.forEach((url, i) => { const call = triggerPixelSpy.getCall(i); @@ -173,7 +173,7 @@ describe('#bidViewability', function() { consentString: 'consent', addtlConsent: 'moreConsent' }); - const moduleConfig = {firePixels: true}; + const moduleConfig = { firePixels: true }; bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); PBJS_WINNING_BID.vurls.forEach((url, i) => { const call = triggerPixelSpy.getCall(i); @@ -188,7 +188,7 @@ describe('#bidViewability', function() { }); it('GDPR: should not include the GDPR keys when GDPR Consent is not available', function () { - const moduleConfig = {firePixels: true}; + const moduleConfig = { firePixels: true }; bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); PBJS_WINNING_BID.vurls.forEach((url, i) => { const call = triggerPixelSpy.getCall(i); @@ -207,7 +207,7 @@ describe('#bidViewability', function() { gdprApplies: true, consentString: 'consent' }); - const moduleConfig = {firePixels: true}; + const moduleConfig = { firePixels: true }; bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); PBJS_WINNING_BID.vurls.forEach((url, i) => { const call = triggerPixelSpy.getCall(i); diff --git a/test/spec/modules/concertBidAdapter_spec.js b/test/spec/modules/concertBidAdapter_spec.js index cf22b23e9ae..54150aab322 100644 --- a/test/spec/modules/concertBidAdapter_spec.js +++ b/test/spec/modules/concertBidAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import sinon from 'sinon'; import { spec, storage } from 'modules/concertBidAdapter.js'; import { hook } from 'src/hook.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; import * as adUnits from 'src/utils/adUnits'; describe('ConcertAdapter', function () { @@ -302,7 +302,7 @@ describe('ConcertAdapter', function () { }); it('should return empty bids if there are no bids from the server', function() { - const bids = spec.interpretResponse({ body: {bids: []} }, bidRequest); + const bids = spec.interpretResponse({ body: { bids: [] } }, bidRequest); expect(bids).to.have.lengthOf(0); }); }); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 3b1595f824d..a4c2a02f0b2 100644 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -1,18 +1,18 @@ -import {expect} from 'chai'; -import {spec, storage} from 'modules/criteoBidAdapter.js'; +import { expect } from 'chai'; +import { spec, storage } from 'modules/criteoBidAdapter.js'; import * as utils from 'src/utils.js'; import * as refererDetection from 'src/refererDetection.js'; import * as ajax from 'src/ajax.js'; -import {config} from '../../../src/config.js'; -import {BANNER, NATIVE, VIDEO} from '../../../src/mediaTypes.js'; -import {addFPDToBidderRequest} from '../../helpers/fpd.js'; +import { config } from '../../../src/config.js'; +import { BANNER, NATIVE, VIDEO } from '../../../src/mediaTypes.js'; +import { addFPDToBidderRequest } from '../../helpers/fpd.js'; import 'modules/userId/index.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; import 'modules/consentManagementGpp.js'; -import {hook} from '../../../src/hook.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; +import { hook } from '../../../src/hook.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; describe('The Criteo bidding adapter', function () { let sandbox, ajaxStub, logWarnStub; @@ -80,7 +80,7 @@ describe('The Criteo bidding adapter', function () { const gppConsent = { gppString: 'gpp_string', - applicableSections: [ 1, 2 ] + applicableSections: [1, 2] }; const gdprConsent = { @@ -1182,7 +1182,7 @@ describe('The Criteo bidding adapter', function () { } }; - const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest({...bidderRequest, ortb2})).data; + const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest({ ...bidderRequest, ortb2 })).data; expect(ortbRequest.regs.ext.gpp).to.equal('gpp_consent_string'); expect(ortbRequest.regs.ext.gpp_sid).to.deep.equal([0, 1, 2]); }); @@ -1222,7 +1222,7 @@ describe('The Criteo bidding adapter', function () { } }; - const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest({...bidderRequest, ortb2})).data; + const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest({ ...bidderRequest, ortb2 })).data; expect(ortbRequest.regs.ext.dsa).to.deep.equal(dsa); }); @@ -1235,7 +1235,7 @@ describe('The Criteo bidding adapter', function () { bidder: 'criteo', ortb2: { source: { - ext: {schain: expectedSchain} + ext: { schain: expectedSchain } } }, adUnitCode: 'bid-123', @@ -1255,7 +1255,7 @@ describe('The Criteo bidding adapter', function () { ...bidderRequest, ortb2: { source: { - ext: {schain: expectedSchain} + ext: { schain: expectedSchain } } } }; @@ -1547,8 +1547,8 @@ describe('The Criteo bidding adapter', function () { segtax: 3 }, segment: [ - {'id': '1001'}, - {'id': '1002'} + { 'id': '1001' }, + { 'id': '1002' } ] }] }, @@ -1566,8 +1566,8 @@ describe('The Criteo bidding adapter', function () { segtax: 3 }, segment: [ - {'id': '1001'}, - {'id': '1002'} + { 'id': '1001' }, + { 'id': '1002' } ] }], ext: { @@ -1606,13 +1606,13 @@ describe('The Criteo bidding adapter', function () { user: userData }; - const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest({...bidderRequest, ortb2})).data; - expect(ortbRequest.user).to.deep.equal({...userData, ext: {...userData.ext, consent: 'consentDataString'}}); + const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest({ ...bidderRequest, ortb2 })).data; + expect(ortbRequest.user).to.deep.equal({ ...userData, ext: { ...userData.ext, consent: 'consentDataString' } }); expect(ortbRequest.site).to.deep.equal({ ...siteData, page: refererUrl, domain: 'criteo.com', - publisher: {...ortbRequest.site.publisher, domain: 'criteo.com'} + publisher: { ...ortbRequest.site.publisher, domain: 'criteo.com' } }); expect(ortbRequest.imp[0].ext.bidfloor).to.equal(0.75); expect(ortbRequest.imp[0].ext.data.someContextAttribute).to.equal('abc') @@ -1621,7 +1621,7 @@ describe('The Criteo bidding adapter', function () { it('should properly build a request when coppa flag is true', async function () { const bidRequests = []; const bidderRequest = {}; - config.setConfig({coppa: true}); + config.setConfig({ coppa: true }); const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)).data; expect(ortbRequest.regs.coppa).to.equal(1); }); @@ -1629,7 +1629,7 @@ describe('The Criteo bidding adapter', function () { it('should properly build a request when coppa flag is false', async function () { const bidRequests = []; const bidderRequest = {}; - config.setConfig({coppa: false}); + config.setConfig({ coppa: false }); const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)).data; expect(ortbRequest.regs.coppa).to.equal(0); }); @@ -1676,8 +1676,8 @@ describe('The Criteo bidding adapter', function () { const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)).data; expect(ortbRequest.imp[0].ext.floors).to.deep.equal({ 'banner': { - '300x250': {'currency': 'USD', 'floor': 1}, - '728x90': {'currency': 'USD', 'floor': 2} + '300x250': { 'currency': 'USD', 'floor': 1 }, + '728x90': { 'currency': 'USD', 'floor': 2 } } }); }); @@ -1703,8 +1703,8 @@ describe('The Criteo bidding adapter', function () { const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)).data; expect(ortbRequest.imp[0].ext.floors).to.deep.equal({ 'banner': { - '300x250': {'currency': 'EUR', 'floor': 1}, - '728x90': {'currency': 'EUR', 'floor': 1} + '300x250': { 'currency': 'EUR', 'floor': 1 }, + '728x90': { 'currency': 'EUR', 'floor': 1 } } }); }); @@ -1744,8 +1744,8 @@ describe('The Criteo bidding adapter', function () { const ortbRequest = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)).data; expect(ortbRequest.imp[0].ext.floors).to.deep.equal({ 'video': { - '300x250': {'currency': 'USD', 'floor': 1}, - '728x90': {'currency': 'USD', 'floor': 2} + '300x250': { 'currency': 'USD', 'floor': 1 }, + '728x90': { 'currency': 'USD', 'floor': 2 } } }); }); @@ -1811,14 +1811,14 @@ describe('The Criteo bidding adapter', function () { expect(ortbRequest.imp[0].ext.data.someContextAttribute).to.deep.equal('abc'); expect(ortbRequest.imp[0].ext.floors).to.deep.equal({ 'banner': { - '300x250': {'currency': 'USD', 'floor': 1}, - '728x90': {'currency': 'USD', 'floor': 2} + '300x250': { 'currency': 'USD', 'floor': 1 }, + '728x90': { 'currency': 'USD', 'floor': 2 } }, 'video': { - '640x480': {'currency': 'EUR', 'floor': 3.2} + '640x480': { 'currency': 'EUR', 'floor': 3.2 } }, 'native': { - '*': {'currency': 'YEN', 'floor': 4.99} + '*': { 'currency': 'YEN', 'floor': 4.99 } } }); }); @@ -1944,21 +1944,21 @@ describe('The Criteo bidding adapter', function () { }); it('should interpret correctly gzip configuration given as a string', async function() { - bidderConfigStub.returns({criteo: {gzipEnabled: 'false'}}); + bidderConfigStub.returns({ criteo: { gzipEnabled: 'false' } }); const request = spec.buildRequests(defaultBidRequests, await addFPDToBidderRequest(bidderRequest)); expect(request.options.endpointCompression).to.be.false; }); it('should interpret correctly gzip configuration given as a boolean', async function () { - bidderConfigStub.returns({criteo: {gzipEnabled: false}}); + bidderConfigStub.returns({ criteo: { gzipEnabled: false } }); const request = spec.buildRequests(defaultBidRequests, await addFPDToBidderRequest(bidderRequest)); expect(request.options.endpointCompression).to.be.false; }); it('should default to true when it receives an invalid configuration', async function () { - bidderConfigStub.returns({criteo: {gzipEnabled: 'randomString'}}); + bidderConfigStub.returns({ criteo: { gzipEnabled: 'randomString' } }); const request = spec.buildRequests(defaultBidRequests, await addFPDToBidderRequest(bidderRequest)); expect(request.options.endpointCompression).to.be.true; @@ -2114,9 +2114,9 @@ describe('The Criteo bidding adapter', function () { it('should return an empty array when parsing a well-formed no bid response', async function () { const bidRequests = []; - const response = {seatbid: []}; + const response = { seatbid: [] }; const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); - const bids = spec.interpretResponse({body: response}, request); + const bids = spec.interpretResponse({ body: response }, request); expect(bids).to.have.lengthOf(0); }); @@ -2135,7 +2135,7 @@ describe('The Criteo bidding adapter', function () { }]; const response = mockResponse('test-bidId', BANNER); const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); - const bids = spec.interpretResponse({body: response}, request); + const bids = spec.interpretResponse({ body: response }, request); expect(bids).to.have.lengthOf(1); expect(bids[0].mediaType).to.equal(BANNER); expect(bids[0].requestId).to.equal('test-bidId'); @@ -2173,7 +2173,7 @@ describe('The Criteo bidding adapter', function () { }]; const response = mockResponse('test-bidId', VIDEO); const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); - const bids = spec.interpretResponse({body: response}, request); + const bids = spec.interpretResponse({ body: response }, request); expect(bids).to.have.lengthOf(1); expect(bids[0].mediaType).to.equal(VIDEO); expect(bids[0].requestId).to.equal('test-bidId'); @@ -2209,7 +2209,7 @@ describe('The Criteo bidding adapter', function () { }]; const response = mockResponse('test-bidId', VIDEO); const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); - const bids = spec.interpretResponse({body: response}, request); + const bids = spec.interpretResponse({ body: response }, request); expect(bids).to.have.lengthOf(1); expect(bids[0].mediaType).to.equal(VIDEO); expect(bids[0].requestId).to.equal('test-bidId'); @@ -2238,7 +2238,7 @@ describe('The Criteo bidding adapter', function () { }]; const response = mockResponse('test-bidId', NATIVE); const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); - const bids = spec.interpretResponse({body: response}, request); + const bids = spec.interpretResponse({ body: response }, request); expect(bids).to.have.lengthOf(1); expect(bids[0].mediaType).to.equal(NATIVE); expect(bids[0].requestId).to.equal('test-bidId'); @@ -2289,7 +2289,7 @@ describe('The Criteo bidding adapter', function () { }]; const response = mockResponse('test-bidId2', BANNER); const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); - const bids = spec.interpretResponse({body: response}, request); + const bids = spec.interpretResponse({ body: response }, request); expect(bids).to.have.lengthOf(1); expect(bids[0].mediaType).to.equal(BANNER); expect(bids[0].requestId).to.equal('test-bidId2'); @@ -2338,7 +2338,7 @@ describe('The Criteo bidding adapter', function () { }]; const response = mockResponse('test-bidId', VIDEO); const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); - const bids = spec.interpretResponse({body: response}, request); + const bids = spec.interpretResponse({ body: response }, request); expect(bids).to.have.lengthOf(1); expect(bids[0].mediaType).to.equal(VIDEO); expect(bids[0].requestId).to.equal('test-bidId'); @@ -2378,7 +2378,7 @@ describe('The Criteo bidding adapter', function () { }]; const response = mockResponse('test-bidId', NATIVE); const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); - const bids = spec.interpretResponse({body: response}, request); + const bids = spec.interpretResponse({ body: response }, request); expect(bids).to.have.lengthOf(1); expect(bids[0].mediaType).to.equal(NATIVE); expect(bids[0].requestId).to.equal('test-bidId'); @@ -2458,7 +2458,7 @@ describe('The Criteo bidding adapter', function () { }; const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); - const bids = spec.interpretResponse({body: response}, request); + const bids = spec.interpretResponse({ body: response }, request); expect(bids).to.have.lengthOf(1); @@ -2627,7 +2627,7 @@ describe('The Criteo bidding adapter', function () { ]; for (const nativeParams of nativeParamsWithoutSendId) { - let transformedBidRequests = {...bidRequests}; + let transformedBidRequests = { ...bidRequests }; transformedBidRequests = [Object.assign(transformedBidRequests[0], nativeParams), Object.assign(transformedBidRequests[1], nativeParams)]; spec.buildRequests(transformedBidRequests, await addFPDToBidderRequest(bidderRequest)); } diff --git a/test/spec/modules/debugging_mod_spec.js b/test/spec/modules/debugging_mod_spec.js index 488543de582..ee8089b7a10 100644 --- a/test/spec/modules/debugging_mod_spec.js +++ b/test/spec/modules/debugging_mod_spec.js @@ -1,5 +1,5 @@ -import {expect} from 'chai'; -import {makebidInterceptor} from '../../../modules/debugging/bidInterceptor.js'; +import { expect } from 'chai'; +import { makebidInterceptor } from '../../../modules/debugging/bidInterceptor.js'; import { makeBidderBidInterceptor, disableDebugging, @@ -7,9 +7,9 @@ import { sessionLoader, } from '../../../modules/debugging/debugging.js'; import '../../../modules/debugging/index.js'; -import {makePbsInterceptor} from '../../../modules/debugging/pbsInterceptor.js'; -import {config} from '../../../src/config.js'; -import {hook} from '../../../src/hook.js'; +import { makePbsInterceptor } from '../../../modules/debugging/pbsInterceptor.js'; +import { config } from '../../../src/config.js'; +import { hook } from '../../../src/hook.js'; import { addBidderRequestsBound, addBidderRequestsHook, @@ -17,18 +17,18 @@ import { addBidResponseHook, } from '../../../modules/debugging/legacy.js'; import * as utils from '../../../src/utils.js'; -import {addBidderRequests, addBidResponse} from '../../../src/auction.js'; -import {prefixLog} from '../../../src/utils.js'; -import {createBid} from '../../../src/bidfactory.js'; -import {VIDEO, BANNER, NATIVE} from '../../../src/mediaTypes.js'; -import {Renderer} from '../../../src/Renderer.js'; +import { addBidderRequests, addBidResponse } from '../../../src/auction.js'; +import { prefixLog } from '../../../src/utils.js'; +import { createBid } from '../../../src/bidfactory.js'; +import { VIDEO, BANNER, NATIVE } from '../../../src/mediaTypes.js'; +import { Renderer } from '../../../src/Renderer.js'; describe('bid interceptor', () => { let interceptor, mockSetTimeout; beforeEach(() => { mockSetTimeout = sinon.stub().callsFake((fn) => fn()); - const BidInterceptor = makebidInterceptor({utils, VIDEO, BANNER, NATIVE, Renderer}) - interceptor = new BidInterceptor({setTimeout: mockSetTimeout, logger: prefixLog('TEST')}); + const BidInterceptor = makebidInterceptor({ utils, VIDEO, BANNER, NATIVE, Renderer }) + interceptor = new BidInterceptor({ setTimeout: mockSetTimeout, logger: prefixLog('TEST') }); }); function setRules(...rules) { @@ -48,8 +48,8 @@ describe('bid interceptor', () => { set: new Set(), }).forEach(([test, arg]) => { it(`should filter out ${test}`, () => { - const valid = [{key1: 'value'}, {key2: 'value'}]; - const ser = interceptor.serializeConfig([...valid, {outer: {inner: arg}}]); + const valid = [{ key1: 'value' }, { key2: 'value' }]; + const ser = interceptor.serializeConfig([...valid, { outer: { inner: arg } }]); expect(ser).to.eql(valid); }); }); @@ -57,33 +57,33 @@ describe('bid interceptor', () => { describe('match()', () => { Object.entries({ - value: {key: 'value'}, - regex: {key: /^value$/}, + value: { key: 'value' }, + regex: { key: /^value$/ }, 'function': (o) => o.key === 'value' }).forEach(([test, matcher]) => { describe(`by ${test}`, () => { it('should work on matching top-level properties', () => { - setRules({when: matcher}); - const rule = interceptor.match({key: 'value'}); + setRules({ when: matcher }); + const rule = interceptor.match({ key: 'value' }); expect(rule).to.not.eql(null); }); it('should work on matching nested properties', () => { - setRules({when: {outer: {inner: matcher}}}); - const rule = interceptor.match({outer: {inner: {key: 'value'}}}); + setRules({ when: { outer: { inner: matcher } } }); + const rule = interceptor.match({ outer: { inner: { key: 'value' } } }); expect(rule).to.not.eql(null); }); it('should not work on non-matching inputs', () => { - setRules({when: matcher}); - expect(interceptor.match({key: 'different-value'})).to.not.be.ok; - expect(interceptor.match({differentKey: 'value'})).to.not.be.ok; + setRules({ when: matcher }); + expect(interceptor.match({ key: 'different-value' })).to.not.be.ok; + expect(interceptor.match({ differentKey: 'value' })).to.not.be.ok; }); }); }); it('should respect rule order', () => { - setRules({when: {key: 'value'}}, {when: {}}, {when: {}}); + setRules({ when: { key: 'value' } }, { when: {} }, { when: {} }); const rule = interceptor.match({}); expect(rule.no).to.equal(2); }); @@ -91,11 +91,11 @@ describe('bid interceptor', () => { it('should pass extra arguments to property function matchers', () => { const matchDef = { key: sinon.stub(), - outer: {inner: {key: sinon.stub()}} + outer: { inner: { key: sinon.stub() } } }; const extraArgs = [{}, {}]; - setRules({when: matchDef}); - interceptor.match({key: {}, outer: {inner: {key: {}}}}, ...extraArgs); + setRules({ when: matchDef }); + interceptor.match({ key: {}, outer: { inner: { key: {} } } }, ...extraArgs); [matchDef.key, matchDef.outer.inner.key].forEach((fn) => { expect(fn.calledOnceWith(sinon.match.any, ...extraArgs.map(sinon.match.same))).to.be.true; }); @@ -103,7 +103,7 @@ describe('bid interceptor', () => { it('should pass extra arguments to single-function matcher', () => { const matchDef = sinon.stub(); - setRules({when: matchDef}); + setRules({ when: matchDef }); const args = [{}, {}, {}]; interceptor.match(...args); expect(matchDef.calledOnceWith(...args.map(sinon.match.same))).to.be.true; @@ -111,8 +111,8 @@ describe('bid interceptor', () => { }); describe('rule', () => { - function matchingRule({replace, options}) { - setRules({when: {}, then: replace, options: options}); + function matchingRule({ replace, options }) { + setRules({ when: {}, then: replace, options: options }); return interceptor.match({}); } @@ -127,27 +127,27 @@ describe('bid interceptor', () => { }); Object.entries({ - value: {key: 'value'}, - 'function': () => ({key: 'value'}) + value: { key: 'value' }, + 'function': () => ({ key: 'value' }) }).forEach(([test, replDef]) => { describe(`by ${test}`, () => { it('should merge top-level properties with replace definition', () => { - const result = matchingRule({replace: replDef}).replace({}); + const result = matchingRule({ replace: replDef }).replace({}); expect(result).to.include.keys(REQUIRED_KEYS); expect(result.key).to.equal('value'); }); it('should merge nested properties with replace definition', () => { - const result = matchingRule({replace: {outer: {inner: replDef}}}).replace({}); + const result = matchingRule({ replace: { outer: { inner: replDef } } }).replace({}); expect(result).to.include.keys(REQUIRED_KEYS); - expect(result.outer.inner).to.eql({key: 'value'}); + expect(result.outer.inner).to.eql({ key: 'value' }); }); it('should respect array vs object definitions', () => { - const result = matchingRule({replace: {item: [replDef]}}).replace({}); + const result = matchingRule({ replace: { item: [replDef] } }).replace({}); expect(result.item).to.be.an('array'); expect(result.item.length).to.equal(1); - expect(result.item[0]).to.eql({key: 'value'}); + expect(result.item[0]).to.eql({ key: 'value' }); }); }); }); @@ -155,17 +155,17 @@ describe('bid interceptor', () => { it('should pass extra arguments to single function replacer', () => { const replDef = sinon.stub(); const args = [{}, {}, {}]; - matchingRule({replace: replDef}).replace(...args); + matchingRule({ replace: replDef }).replace(...args); expect(replDef.calledOnceWith(...args.map(sinon.match.same))).to.be.true; }); it('should pass extra arguments to function property replacers', () => { const replDef = { key: sinon.stub(), - outer: {inner: {key: sinon.stub()}} + outer: { inner: { key: sinon.stub() } } }; const args = [{}, {}, {}]; - matchingRule({replace: replDef}).replace(...args); + matchingRule({ replace: replDef }).replace(...args); [replDef.key, replDef.outer.inner.key].forEach((repl) => { expect(repl.calledOnceWith(...args.map(sinon.match.same))).to.be.true; }); @@ -174,15 +174,15 @@ describe('bid interceptor', () => { describe('.options', () => { it('should include default rule options', () => { - const optDef = {someOption: 'value'}; - const ruleOptions = matchingRule({options: optDef}).options; + const optDef = { someOption: 'value' }; + const ruleOptions = matchingRule({ options: optDef }).options; expect(ruleOptions).to.include(optDef); expect(ruleOptions).to.include(interceptor.DEFAULT_RULE_OPTIONS); }); it('should override defaults', () => { - const optDef = {delay: 123}; - const ruleOptions = matchingRule({options: optDef}).options; + const optDef = { delay: 123 }; + const ruleOptions = matchingRule({ options: optDef }).options; expect(ruleOptions).to.eql(optDef); }); }); @@ -192,8 +192,8 @@ describe('bid interceptor', () => { let done, addBid; function intercept(args = {}) { - const bidRequest = {bids: args.bids || []}; - return interceptor.intercept(Object.assign({bidRequest, done, addBid}, args)); + const bidRequest = { bids: args.bids || [] }; + return interceptor.intercept(Object.assign({ bidRequest, done, addBid }, args)); } beforeEach(() => { @@ -205,7 +205,7 @@ describe('bid interceptor', () => { it('should return untouched bids and bidRequest', () => { const bids = [{}, {}]; const bidRequest = {}; - const result = intercept({bids, bidRequest}); + const result = intercept({ bids, bidRequest }); expect(result.bids).to.equal(bids); expect(result.bidRequest).to.equal(bidRequest); }); @@ -228,34 +228,34 @@ describe('bid interceptor', () => { const DELAY_2 = 321; const REQUEST = { bids: [ - {id: 1, match: false}, - {id: 2, match: 1}, - {id: 3, match: 2} + { id: 1, match: false }, + { id: 2, match: 1 }, + { id: 3, match: 2 } ] }; beforeEach(() => { match1 = sinon.stub().callsFake((bid) => bid.match === 1); match2 = sinon.stub().callsFake((bid) => bid.match === 2); - repl1 = sinon.stub().returns({replace: 1}); - repl2 = sinon.stub().returns({replace: 2}); + repl1 = sinon.stub().returns({ replace: 1 }); + repl2 = sinon.stub().returns({ replace: 2 }); setRules( - {when: match1, then: repl1, options: {delay: DELAY_1}}, - {when: match2, then: repl2, options: {delay: DELAY_2}}, + { when: match1, then: repl1, options: { delay: DELAY_1 } }, + { when: match2, then: repl2, options: { delay: DELAY_2 } }, ); }); it('should return only non-matching bids', () => { - const {bids, bidRequest} = intercept({bidRequest: REQUEST}); + const { bids, bidRequest } = intercept({ bidRequest: REQUEST }); expect(bids).to.eql([REQUEST.bids[0]]); expect(bidRequest.bids).to.eql([REQUEST.bids[0]]); }); it('should call addBid for each matching bid', () => { - intercept({bidRequest: REQUEST}); + intercept({ bidRequest: REQUEST }); expect(addBid.callCount).to.equal(2); - expect(addBid.calledWith(sinon.match({replace: 1, isDebug: true}), REQUEST.bids[1])).to.be.true; - expect(addBid.calledWith(sinon.match({replace: 2, isDebug: true}), REQUEST.bids[2])).to.be.true; + expect(addBid.calledWith(sinon.match({ replace: 1, isDebug: true }), REQUEST.bids[1])).to.be.true; + expect(addBid.calledWith(sinon.match({ replace: 2, isDebug: true }), REQUEST.bids[2])).to.be.true; [DELAY_1, DELAY_2].forEach((delay) => { expect(mockSetTimeout.calledWith(sinon.match.any, delay)).to.be.true; }); @@ -263,20 +263,20 @@ describe('bid interceptor', () => { it('should not call onBid when then is null', () => { setRules({ - when: {id: 2}, + when: { id: 2 }, then: null }); - intercept({bidRequest: REQUEST}); + intercept({ bidRequest: REQUEST }); sinon.assert.notCalled(addBid); }) it('should call done()', () => { - intercept({bidRequest: REQUEST}); + intercept({ bidRequest: REQUEST }); expect(done.calledOnce).to.be.true; }); it('should pass bid and bidRequest to match and replace functions', () => { - intercept({bidRequest: REQUEST}); + intercept({ bidRequest: REQUEST }); Object.entries({ 1: [match1, repl1], 2: [match2, repl2] @@ -294,7 +294,7 @@ describe('Debugging config', () => { it('should behave gracefully when sessionStorage throws', () => { const logError = sinon.stub(); const getStorage = () => { throw new Error() }; - getConfig({enabled: false}, {getStorage, logger: {logError}, hook, utils}); + getConfig({ enabled: false }, { getStorage, logger: { logError }, hook, utils }); expect(logError.called).to.be.true; }); }); @@ -302,12 +302,12 @@ describe('Debugging config', () => { describe('bidderBidInterceptor', () => { let next, interceptBids, onCompletion, interceptResult, done, addBid, wrapCallback, wrapped, bidderBidInterceptor; - function interceptorArgs({spec = {}, bids = [], bidRequest = {}, ajax = {}, cbs = {}} = {}) { - return [next, interceptBids, spec, bids, bidRequest, ajax, wrapCallback, Object.assign({onCompletion}, cbs)]; + function interceptorArgs({ spec = {}, bids = [], bidRequest = {}, ajax = {}, cbs = {} } = {}) { + return [next, interceptBids, spec, bids, bidRequest, ajax, wrapCallback, Object.assign({ onCompletion }, cbs)]; } beforeEach(() => { - bidderBidInterceptor = makeBidderBidInterceptor({utils}); + bidderBidInterceptor = makeBidderBidInterceptor({ utils }); next = sinon.spy(); wrapped = false; wrapCallback = sinon.stub().callsFake(cb => { @@ -327,14 +327,14 @@ describe('bidderBidInterceptor', () => { return interceptResult; }); onCompletion = sinon.spy(); - interceptResult = {bids: [], bidRequest: {}}; + interceptResult = { bids: [], bidRequest: {} }; }); it('should pass to interceptBid an addBid that triggers onBid', () => { const onBid = sinon.stub().callsFake(() => { expect(wrapped).to.be.true; }); - bidderBidInterceptor(...interceptorArgs({cbs: {onBid}})); + bidderBidInterceptor(...interceptorArgs({ cbs: { onBid } })); const bid = { bidder: 'bidder' }; @@ -352,7 +352,7 @@ describe('bidderBidInterceptor', () => { it('should call onResponse', () => { const onResponse = sinon.stub(); - bidderBidInterceptor(...interceptorArgs({cbs: {onResponse}})); + bidderBidInterceptor(...interceptorArgs({ cbs: { onResponse } })); sinon.assert.called(onResponse); }) @@ -363,9 +363,9 @@ describe('bidderBidInterceptor', () => { }); describe('with remaining bids', () => { - const REMAINING_BIDS = [{id: 1}, {id: 2}]; + const REMAINING_BIDS = [{ id: 1 }, { id: 2 }]; beforeEach(() => { - interceptResult = {bids: REMAINING_BIDS, bidRequest: {bids: REMAINING_BIDS}}; + interceptResult = { bids: REMAINING_BIDS, bidRequest: { bids: REMAINING_BIDS } }; }); it('should call next', () => { @@ -374,7 +374,7 @@ describe('bidderBidInterceptor', () => { onRequest: {}, onBid: {} }; - const args = interceptorArgs({cbs: callbacks}); + const args = interceptorArgs({ cbs: callbacks }); const expectedNextArgs = [ args[2], interceptResult.bids, @@ -402,7 +402,7 @@ describe('bidderBidInterceptor', () => { }); describe('pbsBidInterceptor', () => { - const EMPTY_INT_RES = {bids: [], bidRequest: {bids: []}}; + const EMPTY_INT_RES = { bids: [], bidRequest: { bids: [] } }; let next, interceptBids, s2sBidRequest, bidRequests, ajax, onResponse, onError, onBid, interceptResults, addBids, dones, reqIdx; @@ -420,22 +420,22 @@ describe('pbsBidInterceptor', () => { return interceptResults[reqIdx++]; }); s2sBidRequest = {}; - bidRequests = [{bids: []}, {bids: []}]; + bidRequests = [{ bids: [] }, { bids: [] }]; interceptResults = [EMPTY_INT_RES, EMPTY_INT_RES]; }); - const pbsBidInterceptor = makePbsInterceptor({createBid, utils}); + const pbsBidInterceptor = makePbsInterceptor({ createBid, utils }); function callInterceptor() { - return pbsBidInterceptor(next, interceptBids, s2sBidRequest, bidRequests, ajax, {onResponse, onError, onBid}); + return pbsBidInterceptor(next, interceptBids, s2sBidRequest, bidRequests, ajax, { onResponse, onError, onBid }); } it('passes addBids that trigger onBid', () => { callInterceptor(); bidRequests.forEach((_, i) => { - const bid = {adUnitCode: i, prop: i}; - const bidRequest = {req: i}; + const bid = { adUnitCode: i, prop: i }; + const bidRequest = { req: i }; addBids[i](bid, bidRequest); - expect(onBid.calledWith({adUnit: i, bid: sinon.match(bid)})); + expect(onBid.calledWith({ adUnit: i, bid: sinon.match(bid) })); }); }); @@ -460,21 +460,21 @@ describe('pbsBidInterceptor', () => { let matchingBids; beforeEach(() => { matchingBids = [ - [{bidId: 1, matching: true}, {bidId: 2, matching: true}], + [{ bidId: 1, matching: true }, { bidId: 2, matching: true }], [], - [{bidId: 3, matching: true}] + [{ bidId: 3, matching: true }] ]; - interceptResults = matchingBids.map((bids) => ({bids, bidRequest: {bids}})); + interceptResults = matchingBids.map((bids) => ({ bids, bidRequest: { bids } })); s2sBidRequest = { ad_units: [ - {bids: [{bid_id: 1, matching: true}, {bid_id: 3, matching: true}, {bid_id: 100}, {bid_id: 101}]}, - {bids: [{bid_id: 2, matching: true}, {bid_id: 110}, {bid_id: 111}]}, - {bids: [{bid_id: 120}]} + { bids: [{ bid_id: 1, matching: true }, { bid_id: 3, matching: true }, { bid_id: 100 }, { bid_id: 101 }] }, + { bids: [{ bid_id: 2, matching: true }, { bid_id: 110 }, { bid_id: 111 }] }, + { bids: [{ bid_id: 120 }] } ] }; bidRequests = matchingBids.map((mBids, i) => [ - {bidId: 100 + (i * 10)}, - {bidId: 101 + (i * 10)}, + { bidId: 100 + (i * 10) }, + { bidId: 101 + (i * 10) }, ...mBids ]); }); @@ -504,7 +504,7 @@ describe('pbsBidInterceptor', () => { const passedBidReqs = next.args[0][1]; interceptResults .filter((r) => r.bids.length > 0) - .forEach(({bidRequest}, i) => { + .forEach(({ bidRequest }, i) => { expect(passedBidReqs[i]).to.equal(bidRequest); }); }); @@ -545,20 +545,20 @@ describe('bid overrides', function () { }); afterEach(function () { - disableDebugging({hook, logger}); + disableDebugging({ hook, logger }); }); it('should happen when enabled with setConfig', function () { getConfig({ enabled: true - }, {config, hook, logger, utils}); + }, { config, hook, logger, utils }); expect(addBidResponse.getHooks().some(hook => hook.hook === addBidResponseBound)).to.equal(true); expect(addBidderRequests.getHooks().some(hook => hook.hook === addBidderRequestsBound)).to.equal(true); }); it('should happen when configuration found in sessionStorage', function () { sessionLoader({ - storage: {getItem: () => ('{"enabled": true}')}, + storage: { getItem: () => ('{"enabled": true}') }, config, hook, logger @@ -610,7 +610,7 @@ describe('bid overrides', function () { const next = (adUnitCode, bid) => { bids.push(bid); }; - addBidResponseHook.bind({overrides, logger})(next, bid.adUnitCode, bid); + addBidResponseHook.bind({ overrides, logger })(next, bid.adUnitCode, bid); }); } @@ -719,7 +719,7 @@ describe('bid overrides', function () { const next = (b) => { bidderRequests = b; }; - addBidderRequestsHook.bind({overrides, logger})(next, mockBidRequests); + addBidderRequestsHook.bind({ overrides, logger })(next, mockBidRequests); } it('should allow us to exclude bidders', function () { diff --git a/test/spec/modules/gamAdServerVideo_spec.js b/test/spec/modules/gamAdServerVideo_spec.js index 43fef33d8d3..fba726d2bf1 100644 --- a/test/spec/modules/gamAdServerVideo_spec.js +++ b/test/spec/modules/gamAdServerVideo_spec.js @@ -901,7 +901,7 @@ describe('The DFP video support module', function () { ); server.respondWith(gamWrapper); - const result = getVastXml({url, adUnit: {}, bid: {}, params: {iu: '/19968336/prebid_cache_video_adunit'}}, []).then(() => { + const result = getVastXml({ url, adUnit: {}, bid: {}, params: { iu: '/19968336/prebid_cache_video_adunit' } }, []).then(() => { const request = server.requests[0]; const url = new URL(request.url); return url.searchParams.get('us_privacy'); @@ -913,7 +913,7 @@ describe('The DFP video support module', function () { function obtainUsPrivacyInGamVideoUrl() { const url = 'https://pubads.g.doubleclick.net/gampad/ads' - return new URLSearchParams(buildDfpVideoUrl({url, adUnit: {}, bid: {}, params: {iu: '/19968336/prebid_cache_video_adunit'}})).get('us_privacy'); + return new URLSearchParams(buildDfpVideoUrl({ url, adUnit: {}, bid: {}, params: { iu: '/19968336/prebid_cache_video_adunit' } })).get('us_privacy'); } function mockGpp(gpp) { diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 95b4228e95a..4c61d6a3752 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -316,7 +316,8 @@ describe('gumgumAdapter', function () { }); it('should set the global placement id (gpid) if in adserver property', function () { - const req = { ...bidRequests[0], + const req = { + ...bidRequests[0], ortb2Imp: { ext: { gpid: '/17037559/jeusol/jeusol_D_1', @@ -327,7 +328,8 @@ describe('gumgumAdapter', function () { } } } - } } + } + } const bidRequest = spec.buildRequests([req])[0]; expect(bidRequest.data).to.have.property('gpid'); expect(bidRequest.data.gpid).to.equal('/17037559/jeusol/jeusol_D_1'); @@ -850,7 +852,7 @@ describe('gumgumAdapter', function () { model: 'iPhone 12 Pro Max', os: 'iOS', osv: '17.4', - ext: {fiftyonedegrees_deviceId: '17595-133085-133468-18092'}, + ext: { fiftyonedegrees_deviceId: '17595-133085-133468-18092' }, ip: '127.0.0.1', ipv6: '51dc:5e20:fd6a:c955:66be:03b4:dfa3:35b2', sua: suaObject @@ -1065,7 +1067,7 @@ describe('gumgumAdapter', function () { it('request size that matches response size for in-slot', function () { const request = { ...bidRequest }; const body = { ...serverResponse }; - const expectedSize = [[ 320, 50 ], [300, 600], [300, 250]]; + const expectedSize = [[320, 50], [300, 600], [300, 250]]; let result; request.pi = 3; body.ad.width = 300; diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 39a9321fca9..837225f1844 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -553,7 +553,7 @@ describe('IndexexchangeAdapter', function () { } }, nativeOrtbRequest: { - assets: [{id: 0, required: 0, img: {type: 1}}, {id: 1, required: 1, title: {len: 140}}, {id: 2, required: 1, data: {type: 2}}, {id: 3, required: 1, img: {type: 3}}, {id: 4, required: false, video: {mimes: ['video/mp4', 'video/webm'], minduration: 0, maxduration: 120, protocols: [2, 3, 5, 6]}}] + assets: [{ id: 0, required: 0, img: { type: 1 } }, { id: 1, required: 1, title: { len: 140 } }, { id: 2, required: 1, data: { type: 2 } }, { id: 3, required: 1, img: { type: 3 } }, { id: 4, required: false, video: { mimes: ['video/mp4', 'video/webm'], minduration: 0, maxduration: 120, protocols: [2, 3, 5, 6] } }] }, adUnitCode: 'div-gpt-ad-1460505748562-0', transactionId: '273f49a8-7549-4218-a23c-e7ba59b47230', @@ -912,7 +912,7 @@ describe('IndexexchangeAdapter', function () { '33acrossId': { envelope: 'v1.5fs.1000.fjdiosmclds' }, 'criteoID': { envelope: 'testcriteoID' }, 'euidID': { envelope: 'testeuid' }, - pairId: {envelope: 'testpairId'} + pairId: { envelope: 'testpairId' } }; const DEFAULT_USERID_PAYLOAD = [ @@ -1930,12 +1930,15 @@ describe('IndexexchangeAdapter', function () { dsaparams: [1] }] } - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: { - ext: { - dsa: deepClone(dsa) + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { + ortb2: { + regs: { + ext: { + dsa: deepClone(dsa) + } + } } - } - }})[0]; + })[0]; const r = extractPayload(request); expect(r.regs.ext.dsa.dsarequired).to.equal(dsa.dsarequired); @@ -1951,12 +1954,15 @@ describe('IndexexchangeAdapter', function () { datatopub: '2', transparency: 20 } - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: { - ext: { - dsa: deepClone(dsa) + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { + ortb2: { + regs: { + ext: { + dsa: deepClone(dsa) + } + } } - } - }})[0]; + })[0]; const r = extractPayload(request); expect(r.regs).to.be.undefined; @@ -1976,18 +1982,21 @@ describe('IndexexchangeAdapter', function () { dsaparams: ['1'] }] } - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: { - ext: { - dsa: deepClone(dsa) + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { + ortb2: { + regs: { + ext: { + dsa: deepClone(dsa) + } + } } - } - }})[0]; + })[0]; const r = extractPayload(request); expect(r.regs).to.be.undefined; }); it('should set gpp and gpp_sid field when defined', function () { - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: {gpp: 'gpp', gpp_sid: [1]}} })[0]; + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: { regs: { gpp: 'gpp', gpp_sid: [1] } } })[0]; const r = extractPayload(request); expect(r.regs.gpp).to.equal('gpp'); @@ -1995,13 +2004,13 @@ describe('IndexexchangeAdapter', function () { expect(r.regs.gpp_sid).to.include(1); }); it('should not set gpp, gpp_sid and dsa field when not defined', function () { - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: {}} })[0]; + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: { regs: {} } })[0]; const r = extractPayload(request); expect(r.regs).to.be.undefined; }); it('should not set gpp and gpp_sid field when fields arent strings or array defined', function () { - const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: {regs: {gpp: 1, gpp_sid: 'string'}} })[0]; + const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2: { regs: { gpp: 1, gpp_sid: 'string' } } })[0]; const r = extractPayload(request); expect(r.regs).to.be.undefined; @@ -2502,22 +2511,23 @@ describe('IndexexchangeAdapter', function () { sua: { platform: { brand: 'macOS', - version: [ '12', '6', '1' ] + version: ['12', '6', '1'] }, browsers: [ { brand: 'Chromium', - version: [ '107', '0', '5249', '119' ] + version: ['107', '0', '5249', '119'] }, { brand: 'Google Chrome', - version: [ '107', '0', '5249', '119' ] + version: ['107', '0', '5249', '119'] }, ], mobile: 0, model: '' } - }}; + } + }; const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2 })[0]; const payload = extractPayload(request); @@ -2526,8 +2536,7 @@ describe('IndexexchangeAdapter', function () { }); it('should not set device sua if not available in fpd', function () { - const ortb2 = { - device: {}}; + const ortb2 = { device: {} }; const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2 })[0]; const payload = extractPayload(request); @@ -4240,7 +4249,7 @@ describe('IndexexchangeAdapter', function () { }; bidderRequestWithFledgeEnabled = spec.buildRequests(DEFAULT_BANNER_VALID_BID_WITH_FLEDGE_ENABLED, {})[0]; - bidderRequestWithFledgeEnabled.paapi = {enabled: true}; + bidderRequestWithFledgeEnabled.paapi = { enabled: true }; bidderRequestWithoutFledgeEnabled = spec.buildRequests(DEFAULT_BANNER_VALID_BID, {})[0]; }); @@ -5169,7 +5178,8 @@ describe('IndexexchangeAdapter', function () { device: { ip: '192.168.1.1', ipv6: '2001:0db8:85a3:0000:0000:8a2e:0370:7334' - }}; + } + }; const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2 })[0]; const payload = extractPayload(request); expect(payload.device.ip).to.equal('192.168.1.1') @@ -5177,7 +5187,7 @@ describe('IndexexchangeAdapter', function () { }); it('should not add device.ip if neither ip nor ipv6 exists', () => { - const ortb2 = {device: {}}; + const ortb2 = { device: {} }; const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2 })[0]; const payload = extractPayload(request); expect(payload.device.ip).to.be.undefined; @@ -5204,7 +5214,7 @@ describe('IndexexchangeAdapter', function () { }); it('should not add device.geo if it does not exist', () => { - const ortb2 = {device: {}}; + const ortb2 = { device: {} }; const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID, { ortb2 })[0]; const payload = extractPayload(request); expect(payload.device.geo).to.be.undefined; @@ -5217,13 +5227,13 @@ describe('IndexexchangeAdapter', function () { const el = document.createElement('div'); el.id = adUnitCode; document.body.appendChild(el); - expect(getDivIdFromAdUnit(adUnitCode, {code: adUnitCode})).to.equal(adUnitCode); + expect(getDivIdFromAdUnit(adUnitCode, { code: adUnitCode })).to.equal(adUnitCode); document.body.removeChild(el); }); it('retrieves divId from GPT once and caches result', () => { const adUnitCode = 'div-ad2'; - const stub = sinon.stub(gptUtils, 'getGptSlotInfoForAdUnitCode').returns({divId: 'gpt-div'}); + const stub = sinon.stub(gptUtils, 'getGptSlotInfoForAdUnitCode').returns({ divId: 'gpt-div' }); const first = getDivIdFromAdUnit(adUnitCode, {}); const second = getDivIdFromAdUnit(adUnitCode, {}); expect(first).to.equal('gpt-div'); diff --git a/test/spec/modules/logicadBidAdapter_spec.js b/test/spec/modules/logicadBidAdapter_spec.js index 715c4007fd6..489cdf834da 100644 --- a/test/spec/modules/logicadBidAdapter_spec.js +++ b/test/spec/modules/logicadBidAdapter_spec.js @@ -1,5 +1,5 @@ -import {expect} from 'chai'; -import {spec} from '../../../modules/logicadBidAdapter.js'; +import { expect } from 'chai'; +import { spec } from '../../../modules/logicadBidAdapter.js'; import * as utils from 'src/utils.js'; describe('LogicadAdapter', function () { @@ -379,10 +379,10 @@ describe('LogicadAdapter', function () { describe('getUserSyncs', function () { it('should perform usersync', function () { - let syncs = spec.getUserSyncs({pixelEnabled: false}, [serverResponse]); + let syncs = spec.getUserSyncs({ pixelEnabled: false }, [serverResponse]); expect(syncs).to.have.length(0); - syncs = spec.getUserSyncs({pixelEnabled: true}, [serverResponse]); + syncs = spec.getUserSyncs({ pixelEnabled: true }, [serverResponse]); expect(syncs).to.have.length(1); expect(syncs[0]).to.have.property('type', 'image'); diff --git a/test/spec/modules/luceadBidAdapter_spec.js b/test/spec/modules/luceadBidAdapter_spec.js index 91e50f9452d..71087fbdcb3 100755 --- a/test/spec/modules/luceadBidAdapter_spec.js +++ b/test/spec/modules/luceadBidAdapter_spec.js @@ -119,7 +119,7 @@ describe('Lucead Adapter', () => { ] }; - const serverResponse = {body: serverResponseBody}; + const serverResponse = { body: serverResponseBody }; const bidRequest = { data: JSON.stringify({ @@ -128,7 +128,7 @@ describe('Lucead Adapter', () => { 'bid_requests': [{ 'bid_id': '2d663fdd390b49', 'sizes': [[300, 250], [300, 150]], - 'media_types': {'banner': {'sizes': [[300, 250], [300, 150]]}}, + 'media_types': { 'banner': { 'sizes': [[300, 250], [300, 150]] } }, 'placement_id': '1' }], }), @@ -153,20 +153,22 @@ describe('Lucead Adapter', () => { }); it('should return bid empty response', function () { - const serverResponse = {body: {bids: [{cpm: 0}]}}; - const bidRequest = {data: '{}'}; + const serverResponse = { body: { bids: [{ cpm: 0 }] } }; + const bidRequest = { data: '{}' }; const result = spec.interpretResponse(serverResponse, bidRequest); expect(result.bids[0].ad).to.be.equal(''); expect(result.bids[0].cpm).to.be.equal(0); }); it('should add advertiserDomains', function () { - const bidRequest = {data: JSON.stringify({ - bidder: 'lucead', - params: { - placementId: '1', - } - })}; + const bidRequest = { + data: JSON.stringify({ + bidder: 'lucead', + params: { + placementId: '1', + } + }) + }; const result = spec.interpretResponse(serverResponse, bidRequest); expect(Object.keys(result.bids[0].meta)).to.include.members(['advertiserDomains']); diff --git a/test/spec/modules/mediaforceBidAdapter_spec.js b/test/spec/modules/mediaforceBidAdapter_spec.js index a0cb4b57a38..fae28156b08 100644 --- a/test/spec/modules/mediaforceBidAdapter_spec.js +++ b/test/spec/modules/mediaforceBidAdapter_spec.js @@ -1,7 +1,7 @@ -import {assert} from 'chai'; -import {spec, resolveFloor} from 'modules/mediaforceBidAdapter.js'; +import { assert } from 'chai'; +import { spec, resolveFloor } from 'modules/mediaforceBidAdapter.js'; import * as utils from '../../../src/utils.js'; -import {BANNER, NATIVE, VIDEO} from '../../../src/mediaTypes.js'; +import { BANNER, NATIVE, VIDEO } from '../../../src/mediaTypes.js'; describe('mediaforce bid adapter', function () { let sandbox; @@ -43,7 +43,7 @@ describe('mediaforce bid adapter', function () { it('should return false when valid params are not passed', function () { const bid = utils.deepClone(defaultBid); - bid.params = {placement_id: '', publisher_id: ''}; + bid.params = { placement_id: '', publisher_id: '' }; assert.equal(spec.isBidRequestValid(bid), false); }); @@ -54,7 +54,7 @@ describe('mediaforce bid adapter', function () { sizes: [[300, 250]] } }; - bid.params = {publisher_id: 2, placement_id: '123'}; + bid.params = { publisher_id: 2, placement_id: '123' }; assert.equal(spec.isBidRequestValid(bid), true); }); }); @@ -142,7 +142,7 @@ describe('mediaforce bid adapter', function () { }, site: { id: defaultBid.params.publisher_id, - publisher: {id: defaultBid.params.publisher_id}, + publisher: { id: defaultBid.params.publisher_id }, ref: encodeURIComponent(refererInfo.ref), page: pageUrl, }, @@ -161,14 +161,14 @@ describe('mediaforce bid adapter', function () { transactionId: defaultBid.ortb2Imp.ext.tid, } }, - banner: {w: 300, h: 250}, + banner: { w: 300, h: 250 }, native: { ver: '1.2', request: { assets: [ - {id: 1, title: {len: 800}, required: 1}, - {id: 3, img: {w: 300, h: 250, type: 3}, required: 1}, - {id: 5, data: {type: 1}, required: 0} + { id: 1, title: { len: 800 }, required: 1 }, + { id: 3, img: { w: 300, h: 250, type: 3 }, required: 1 }, + { id: 5, data: { type: 1 }, required: 0 } ], context: 1, plcmttype: 1, @@ -212,10 +212,10 @@ describe('mediaforce bid adapter', function () { placement_id: '203', transactionId: '8df76688-1618-417a-87b1-60ad046841c9' } - ].map(({publisher_id, placement_id, transactionId}) => { + ].map(({ publisher_id, placement_id, transactionId }) => { return { bidder: 'mediaforce', - params: {publisher_id, placement_id}, + params: { publisher_id, placement_id }, mediaTypes: { banner: { sizes: [[300, 250], [600, 400]] @@ -329,7 +329,7 @@ describe('mediaforce bid adapter', function () { const [request] = spec.buildRequests([bid]); const data = JSON.parse(request.data); - assert.deepEqual(data.imp[0].banner, {w: 300, h: 600, format: [{w: 300, h: 250}]}); + assert.deepEqual(data.imp[0].banner, { w: 300, h: 600, format: [{ w: 300, h: 250 }] }); }); it('should skip banner with empty sizes', function () { @@ -369,7 +369,7 @@ describe('mediaforce bid adapter', function () { }, site: { id: 'pub123', - publisher: {id: 'pub123'}, + publisher: { id: 'pub123' }, ref: encodeURIComponent(refererInfo.ref), page: pageUrl, }, @@ -388,7 +388,7 @@ describe('mediaforce bid adapter', function () { transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' } }, - banner: {w: 300, h: 250, format: [{w: 600, h: 400}]}, + banner: { w: 300, h: 250, format: [{ w: 600, h: 400 }] }, }, { tagid: '203', secure: secure, @@ -398,7 +398,7 @@ describe('mediaforce bid adapter', function () { transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' } }, - banner: {w: 300, h: 250, format: [{w: 600, h: 400}]}, + banner: { w: 300, h: 250, format: [{ w: 600, h: 400 }] }, }, { tagid: '203', secure: secure, @@ -408,7 +408,7 @@ describe('mediaforce bid adapter', function () { transactionId: '8df76688-1618-417a-87b1-60ad046841c9' } }, - banner: {w: 300, h: 250, format: [{w: 600, h: 400}]}, + banner: { w: 300, h: 250, format: [{ w: 600, h: 400 }] }, }] } }, @@ -425,7 +425,7 @@ describe('mediaforce bid adapter', function () { }, site: { id: 'pub124', - publisher: {id: 'pub124'}, + publisher: { id: 'pub124' }, ref: encodeURIComponent(refererInfo.ref), page: pageUrl, }, @@ -444,7 +444,7 @@ describe('mediaforce bid adapter', function () { transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' } }, - banner: {w: 300, h: 250, format: [{w: 600, h: 400}]}, + banner: { w: 300, h: 250, format: [{ w: 600, h: 400 }] }, }] } } @@ -526,20 +526,20 @@ describe('mediaforce bid adapter', function () { ext: { advertiser_name: 'MediaForce', native: { - link: {url: nativeLink}, + link: { url: nativeLink }, assets: [{ id: 1, - title: {text: titleText}, + title: { text: titleText }, required: 1 }, { id: 3, img: imgData }, { id: 5, - data: {value: sponsoredByValue} + data: { value: sponsoredByValue } }, { id: 4, - data: {value: bodyValue} + data: { value: bodyValue } }], imptrackers: [nativeTracker], ver: '1' @@ -602,20 +602,20 @@ describe('mediaforce bid adapter', function () { const bodyValue = 'Drivers With No Tickets In 3 Years Should Do This On June'; const adm = JSON.stringify({ native: { - link: {url: nativeLink}, + link: { url: nativeLink }, assets: [{ id: 1, - title: {text: titleText}, + title: { text: titleText }, required: 1 }, { id: 3, img: imgData }, { id: 5, - data: {value: sponsoredByValue} + data: { value: sponsoredByValue } }, { id: 4, - data: {value: bodyValue} + data: { value: bodyValue } }], imptrackers: [nativeTracker], ver: '1' diff --git a/test/spec/modules/mediafuseBidAdapter_spec.js b/test/spec/modules/mediafuseBidAdapter_spec.js index d2142a5c14e..c1ca2e918f7 100644 --- a/test/spec/modules/mediafuseBidAdapter_spec.js +++ b/test/spec/modules/mediafuseBidAdapter_spec.js @@ -5,7 +5,7 @@ import * as bidderFactory from 'src/adapters/bidderFactory.js'; import { auctionManager } from 'src/auctionManager.js'; import { deepClone } from 'src/utils.js'; import { config } from 'src/config.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; const ENDPOINT = 'https://ib.adnxs.com/ut/v3/prebid'; @@ -98,7 +98,7 @@ describe('MediaFuseAdapter', function () { const payload = JSON.parse(request.data); expect(payload.tags[0].private_sizes).to.exist; - expect(payload.tags[0].private_sizes).to.deep.equal([{width: 300, height: 250}]); + expect(payload.tags[0].private_sizes).to.deep.equal([{ width: 300, height: 250 }]); }); it('should add publisher_id in request', function() { @@ -177,7 +177,7 @@ describe('MediaFuseAdapter', function () { it('should populate the ad_types array on outstream requests', function () { const bidRequest = Object.assign({}, bidRequests[0]); bidRequest.mediaTypes = {}; - bidRequest.mediaTypes.video = {context: 'outstream'}; + bidRequest.mediaTypes.video = { context: 'outstream' }; const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); @@ -313,7 +313,7 @@ describe('MediaFuseAdapter', function () { expect(payload.user).to.exist; expect(payload.user).to.deep.equal({ external_uid: '123', - segments: [{id: 123}, {id: 987, value: 876}] + segments: [{ id: 123 }, { id: 987, value: 876 }] }); }); @@ -396,22 +396,22 @@ describe('MediaFuseAdapter', function () { { mediaType: 'native', nativeParams: { - title: {required: true}, - body: {required: true}, - body2: {required: true}, - image: {required: true, sizes: [100, 100]}, - icon: {required: true}, - cta: {required: false}, - rating: {required: true}, - sponsoredBy: {required: true}, - privacyLink: {required: true}, - displayUrl: {required: true}, - address: {required: true}, - downloads: {required: true}, - likes: {required: true}, - phone: {required: true}, - price: {required: true}, - salePrice: {required: true} + title: { required: true }, + body: { required: true }, + body2: { required: true }, + image: { required: true, sizes: [100, 100] }, + icon: { required: true }, + cta: { required: false }, + rating: { required: true }, + sponsoredBy: { required: true }, + privacyLink: { required: true }, + displayUrl: { required: true }, + address: { required: true }, + downloads: { required: true }, + likes: { required: true }, + phone: { required: true }, + price: { required: true }, + salePrice: { required: true } } } ); @@ -420,22 +420,22 @@ describe('MediaFuseAdapter', function () { const payload = JSON.parse(request.data); expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - title: {required: true}, - description: {required: true}, - desc2: {required: true}, - main_image: {required: true, sizes: [{ width: 100, height: 100 }]}, - icon: {required: true}, - ctatext: {required: false}, - rating: {required: true}, - sponsored_by: {required: true}, - privacy_link: {required: true}, - displayurl: {required: true}, - address: {required: true}, - downloads: {required: true}, - likes: {required: true}, - phone: {required: true}, - price: {required: true}, - saleprice: {required: true}, + title: { required: true }, + description: { required: true }, + desc2: { required: true }, + main_image: { required: true, sizes: [{ width: 100, height: 100 }] }, + icon: { required: true }, + ctatext: { required: false }, + rating: { required: true }, + sponsored_by: { required: true }, + privacy_link: { required: true }, + displayurl: { required: true }, + address: { required: true }, + downloads: { required: true }, + likes: { required: true }, + phone: { required: true }, + price: { required: true }, + saleprice: { required: true }, privacy_supported: true }); expect(payload.tags[0].hb_source).to.equal(1); @@ -455,14 +455,14 @@ describe('MediaFuseAdapter', function () { let request = spec.buildRequests([bidRequest]); let payload = JSON.parse(request.data); - expect(payload.tags[0].sizes).to.deep.equal([{width: 150, height: 100}, {width: 300, height: 250}]); + expect(payload.tags[0].sizes).to.deep.equal([{ width: 150, height: 100 }, { width: 300, height: 250 }]); delete bidRequest.sizes; request = spec.buildRequests([bidRequest]); payload = JSON.parse(request.data); - expect(payload.tags[0].sizes).to.deep.equal([{width: 1, height: 1}]); + expect(payload.tags[0].sizes).to.deep.equal([{ width: 1, height: 1 }]); }); it('should convert keyword params to proper form and attaches to request', function () { @@ -479,7 +479,7 @@ describe('MediaFuseAdapter', function () { singleValNum: 123, emptyStr: '', emptyArr: [''], - badValue: {'foo': 'bar'} // should be dropped + badValue: { 'foo': 'bar' } // should be dropped } } } @@ -554,7 +554,7 @@ describe('MediaFuseAdapter', function () { bidderRequest.bids = bidRequests; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.options).to.deep.equal({withCredentials: true}); + expect(request.options).to.deep.equal({ withCredentials: true }); const payload = JSON.parse(request.data); expect(payload.gdpr_consent).to.exist; @@ -708,7 +708,7 @@ describe('MediaFuseAdapter', function () { .returns(true); const request = spec.buildRequests([bidRequest]); - expect(request.options.customHeaders).to.deep.equal({'X-Is-Test': 1}); + expect(request.options.customHeaders).to.deep.equal({ 'X-Is-Test': 1 }); config.getConfig.restore(); }); @@ -942,7 +942,7 @@ describe('MediaFuseAdapter', function () { adUnitCode: 'code' }] }; - const result = spec.interpretResponse({ body: response }, {bidderRequest}); + const result = spec.interpretResponse({ body: response }, { bidderRequest }); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); @@ -993,7 +993,7 @@ describe('MediaFuseAdapter', function () { }; let bidderRequest; - const result = spec.interpretResponse({ body: response }, {bidderRequest}); + const result = spec.interpretResponse({ body: response }, { bidderRequest }); expect(result.length).to.equal(0); }); @@ -1026,7 +1026,7 @@ describe('MediaFuseAdapter', function () { }] } - const result = spec.interpretResponse({ body: response }, {bidderRequest}); + const result = spec.interpretResponse({ body: response }, { bidderRequest }); expect(result[0]).to.have.property('vastXml'); expect(result[0]).to.have.property('vastImpUrl'); expect(result[0]).to.have.property('mediaType', 'video'); @@ -1061,7 +1061,7 @@ describe('MediaFuseAdapter', function () { }] } - const result = spec.interpretResponse({ body: response }, {bidderRequest}); + const result = spec.interpretResponse({ body: response }, { bidderRequest }); expect(result[0]).to.have.property('vastUrl'); expect(result[0]).to.have.property('vastImpUrl'); expect(result[0]).to.have.property('mediaType', 'video'); @@ -1110,7 +1110,7 @@ describe('MediaFuseAdapter', function () { }] } - const result = spec.interpretResponse({ body: response1 }, {bidderRequest}); + const result = spec.interpretResponse({ body: response1 }, { bidderRequest }); expect(result[0].native.title).to.equal('Native Creative'); expect(result[0].native.body).to.equal('Cool description great stuff'); expect(result[0].native.cta).to.equal('Do it'); @@ -1138,7 +1138,7 @@ describe('MediaFuseAdapter', function () { }] }; - const result = spec.interpretResponse({ body: outstreamResponse }, {bidderRequest}); + const result = spec.interpretResponse({ body: outstreamResponse }, { bidderRequest }); expect(result[0].renderer.config).to.deep.equal( bidderRequest.bids[0].renderer.options ); @@ -1154,7 +1154,7 @@ describe('MediaFuseAdapter', function () { adUnitCode: 'code' }] } - const result = spec.interpretResponse({ body: responseAdvertiserId }, {bidderRequest}); + const result = spec.interpretResponse({ body: responseAdvertiserId }, { bidderRequest }); expect(Object.keys(result[0].meta)).to.include.members(['advertiserId']); }); @@ -1168,7 +1168,7 @@ describe('MediaFuseAdapter', function () { adUnitCode: 'code' }] } - const result = spec.interpretResponse({ body: responseBrandId }, {bidderRequest}); + const result = spec.interpretResponse({ body: responseBrandId }, { bidderRequest }); expect(Object.keys(result[0].meta)).to.include.members(['brandId']); }); @@ -1182,7 +1182,7 @@ describe('MediaFuseAdapter', function () { adUnitCode: 'code' }] } - const result = spec.interpretResponse({ body: responseAdvertiserId }, {bidderRequest}); + const result = spec.interpretResponse({ body: responseAdvertiserId }, { bidderRequest }); expect(Object.keys(result[0].meta)).to.include.members(['advertiserDomains']); expect(Object.keys(result[0].meta.advertiserDomains)).to.deep.equal([]); }); diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index d20206895f4..6368a1abfca 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -1,11 +1,11 @@ -import {expect, assert} from 'chai'; -import {spec, EVENTS} from '../../../modules/medianetBidAdapter.js'; -import {POST_ENDPOINT} from '../../../libraries/medianetUtils/constants.js'; +import { expect, assert } from 'chai'; +import { spec, EVENTS } from '../../../modules/medianetBidAdapter.js'; +import { POST_ENDPOINT } from '../../../libraries/medianetUtils/constants.js'; import { makeSlot } from '../integration/faker/googletag.js'; import { config } from '../../../src/config.js'; -import {server} from '../../mocks/xhr.js'; -import {resetWinDimensions} from '../../../src/utils.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; +import { server } from '../../mocks/xhr.js'; +import { resetWinDimensions } from '../../../src/utils.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; import * as adUnits from 'src/utils/adUnits'; getGlobal().version = getGlobal().version || 'version'; @@ -145,7 +145,7 @@ const VALID_BID_REQUEST_WITH_ORTB2 = [{ 'ortb2Imp': { 'ext': { tid: '277b631f-92f5-4844-8b19-ea13c095d3f1', - 'data': {'pbadslot': '/12345/my-gpt-tag-0'} + 'data': { 'pbadslot': '/12345/my-gpt-tag-0' } } }, 'auctionsCount': 1 @@ -174,7 +174,7 @@ const VALID_BID_REQUEST_WITH_ORTB2 = [{ 'ortb2Imp': { 'ext': { tid: 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', - 'data': {'pbadslot': '/12345/my-gpt-tag-0'} + 'data': { 'pbadslot': '/12345/my-gpt-tag-0' } } }, 'auctionsCount': 1 @@ -1512,7 +1512,7 @@ const SERVER_RESPONSE_PAAPI = { 'callbackURL': 'https://test.com/paapi/v1/abcd' }, 'perBuyerSignals': { - 'https://buyer.test.media.net': [ 'test_buyer_signals' ] + 'https://buyer.test.media.net': ['test_buyer_signals'] }, 'perBuyerTimeouts': { '*': 200 @@ -1572,7 +1572,7 @@ const SERVER_RESPONSE_PAAPI_ORTB = { 'callbackURL': 'https://test.com/paapi/v1/abcd' }, 'perBuyerSignals': { - 'https://buyer.test.media.net': [ 'test_buyer_signals' ] + 'https://buyer.test.media.net': ['test_buyer_signals'] }, 'perBuyerTimeouts': { '*': 200 @@ -2162,7 +2162,7 @@ describe('Media.net bid adapter', function () { getBoundingClientRect: () => boundingRect }) - const bidRequest = [{...VALID_BID_REQUEST[0], adUnitCode: code}] + const bidRequest = [{ ...VALID_BID_REQUEST[0], adUnitCode: code }] const bidReq = spec.buildRequests(bidRequest, VALID_AUCTIONDATA); const data = JSON.parse(bidReq.data); expect(data.imp[0].ext.visibility).to.equal(2); @@ -2312,7 +2312,7 @@ describe('Media.net bid adapter', function () { }); it('should send bidderError data correctly', function () { const error = { - reason: {message: 'Failed to fetch', status: 500}, + reason: { message: 'Failed to fetch', status: 500 }, timedOut: true, status: 0 } @@ -2326,7 +2326,7 @@ describe('Media.net bid adapter', function () { }]; sandbox.stub(window.navigator, 'sendBeacon').returns(false); - spec.onBidderError({error, bidderRequest: {bids}}); + spec.onBidderError({ error, bidderRequest: { bids } }); const reqBody = new URLSearchParams(server.requests[0].requestBody); assert.equal(server.requests[0].method, 'POST'); diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index e6c5f752418..d269a99d74d 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -1,9 +1,9 @@ -import {expect} from 'chai'; +import { expect } from 'chai'; import { spec, storage } from 'modules/mgidBidAdapter.js'; import { version } from 'package.json'; import * as utils from '../../../src/utils.js'; -import {USERSYNC_DEFAULT_CONFIG} from '../../../src/userSync.js'; -import {config} from '../../../src/config.js'; +import { USERSYNC_DEFAULT_CONFIG } from '../../../src/userSync.js'; +import { config } from '../../../src/config.js'; describe('Mgid bid adapter', function () { let sandbox; @@ -61,7 +61,7 @@ describe('Mgid bid adapter', function () { it('should return false when valid params are not passed', function () { const bid = Object.assign({}, sbid); delete bid.params; - bid.params = {accountId: '', placementId: ''}; + bid.params = { accountId: '', placementId: '' }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); @@ -74,7 +74,7 @@ describe('Mgid bid adapter', function () { sizes: [[300, 250]] } }; - bid.params = {accountId: 2, placementId: 1}; + bid.params = { accountId: 2, placementId: 1 }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); @@ -87,7 +87,7 @@ describe('Mgid bid adapter', function () { sizes: [[300, 250]] } }; - bid.params = {accountId: 2, placementId: 1}; + bid.params = { accountId: 2, placementId: 1 }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); @@ -100,7 +100,7 @@ describe('Mgid bid adapter', function () { sizes: [[300, 250]] } }; - bid.params = {accountId: 2, placementId: 1}; + bid.params = { accountId: 2, placementId: 1 }; expect(spec.isBidRequestValid(bid)).to.equal(true); }); @@ -112,21 +112,21 @@ describe('Mgid bid adapter', function () { sizes: [[300, 250]] } }; - bid.params = {accountId: '0', placementId: '00'}; + bid.params = { accountId: '0', placementId: '00' }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); it('should return false when valid mediaTypes are not passed', function () { const bid = Object.assign({}, sbid); delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; + bid.params = { accountId: '1', placementId: '1' }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); it('should return false when valid mediaTypes.banner are not passed', function () { const bid = Object.assign({}, sbid); delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; + bid.params = { accountId: '1', placementId: '1' }; bid.mediaTypes = { }; expect(spec.isBidRequestValid(bid)).to.equal(false); @@ -135,7 +135,7 @@ describe('Mgid bid adapter', function () { it('should return false when valid mediaTypes.banner.sizes are not passed', function () { const bid = Object.assign({}, sbid); delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; + bid.params = { accountId: '1', placementId: '1' }; bid.mediaTypes = { sizes: [] }; @@ -145,7 +145,7 @@ describe('Mgid bid adapter', function () { it('should return false when valid mediaTypes.banner.sizes are not valid', function () { const bid = Object.assign({}, sbid); delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; + bid.params = { accountId: '1', placementId: '1' }; bid.mediaTypes = { sizes: [300, 250] }; @@ -156,7 +156,7 @@ describe('Mgid bid adapter', function () { const bid = Object.assign({}, sbid); delete bid.params; bid.adUnitCode = 'div'; - bid.params = {accountId: '1', placementId: '1'}; + bid.params = { accountId: '1', placementId: '1' }; bid.mediaTypes = { banner: { sizes: [[300, 250]] @@ -167,7 +167,7 @@ describe('Mgid bid adapter', function () { it('should return false when valid mediaTypes.native is not object', function () { const bid = Object.assign({}, sbid); - bid.params = {accountId: '1', placementId: '1'}; + bid.params = { accountId: '1', placementId: '1' }; bid.mediaTypes = { native: [] }; @@ -177,7 +177,7 @@ describe('Mgid bid adapter', function () { it('should return false when mediaTypes.native is empty object', function () { const bid = Object.assign({}, sbid); delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; + bid.params = { accountId: '1', placementId: '1' }; bid.mediaTypes = { native: {} }; @@ -187,7 +187,7 @@ describe('Mgid bid adapter', function () { it('should return false when mediaTypes.native is invalid object', function () { const bid = Object.assign({}, sbid); delete bid.params; - bid.params = {accountId: '1', placementId: '1'}; + bid.params = { accountId: '1', placementId: '1' }; bid.mediaTypes = { native: { image: { @@ -200,19 +200,19 @@ describe('Mgid bid adapter', function () { it('should return false when mediaTypes.native has unsupported required asset', function () { const bid = Object.assign({}, sbid); - bid.params = {accountId: '2', placementId: '1'}; + bid.params = { accountId: '2', placementId: '1' }; bid.mediaTypes = { native: { - title: {required: true}, - image: {required: false, sizes: [80, 80]}, - sponsored: {required: false}, + title: { required: true }, + image: { required: false, sizes: [80, 80] }, + sponsored: { required: false }, }, }; bid.nativeParams = { - title: {required: true}, - image: {required: false, sizes: [80, 80]}, - sponsored: {required: false}, - unsupported: {required: true}, + title: { required: true }, + image: { required: false, sizes: [80, 80] }, + sponsored: { required: false }, + unsupported: { required: true }, }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); @@ -220,18 +220,18 @@ describe('Mgid bid adapter', function () { it('should return true when mediaTypes.native all assets needed', function () { const bid = Object.assign({}, sbid); bid.adUnitCode = 'div'; - bid.params = {accountId: '2', placementId: '1'}; + bid.params = { accountId: '2', placementId: '1' }; bid.mediaTypes = { native: { - title: {required: true}, - image: {required: false, sizes: [80, 80]}, - sponsored: {required: false}, + title: { required: true }, + image: { required: false, sizes: [80, 80] }, + sponsored: { required: false }, }, }; bid.nativeParams = { - title: {required: true}, - image: {required: false, sizes: [80, 80]}, - sponsored: {required: false}, + title: { required: true }, + image: { required: false, sizes: [80, 80] }, + sponsored: { required: false }, }; expect(spec.isBidRequestValid(bid)).to.equal(true); }); @@ -333,7 +333,7 @@ describe('Mgid bid adapter', function () { }, }; afterEach(function () { - config.setConfig({coppa: undefined}) + config.setConfig({ coppa: undefined }) }) it('should return undefined if no validBidRequests passed', function () { @@ -356,7 +356,7 @@ describe('Mgid bid adapter', function () { getDataFromLocalStorageStub.restore(); }); it('should proper handle gdpr', function () { - config.setConfig({coppa: 1}) + config.setConfig({ coppa: 1 }) const bid = Object.assign({}, abid); bid.mediaTypes = { banner: { @@ -364,12 +364,12 @@ describe('Mgid bid adapter', function () { } }; const bidRequests = [bid]; - const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'gdpr', gdprApplies: true}, uspConsent: 'usp', gppConsent: {gppString: 'gpp'}}); + const request = spec.buildRequests(bidRequests, { gdprConsent: { consentString: 'gdpr', gdprApplies: true }, uspConsent: 'usp', gppConsent: { gppString: 'gpp' } }); expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); expect(request.method).deep.equal('POST'); const data = JSON.parse(request.data); - expect(data.user).deep.equal({ext: {consent: 'gdpr'}}); - expect(data.regs).deep.equal({ext: {gdpr: 1, us_privacy: 'usp'}, gpp: 'gpp', coppa: 1}); + expect(data.user).deep.equal({ ext: { consent: 'gdpr' } }); + expect(data.regs).deep.equal({ ext: { gdpr: 1, us_privacy: 'usp' }, gpp: 'gpp', coppa: 1 }); }); it('should handle refererInfo', function () { const bid = Object.assign({}, abid); @@ -382,7 +382,7 @@ describe('Mgid bid adapter', function () { const domain = 'site.com' const page = `http://${domain}/site.html` const ref = 'http://ref.com/ref.html' - const request = spec.buildRequests(bidRequests, {refererInfo: {page, ref}}); + const request = spec.buildRequests(bidRequests, { refererInfo: { page, ref } }); expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); expect(request.method).deep.equal('POST'); const data = JSON.parse(request.data); @@ -404,7 +404,7 @@ describe('Mgid bid adapter', function () { const bidRequests = [bid]; const request = spec.buildRequests(bidRequests); const data = JSON.parse(request.data); - expect(data.source).to.deep.equal({ext: {schain: bid.ortb2.source.ext.schain}}); + expect(data.source).to.deep.equal({ ext: { schain: bid.ortb2.source.ext.schain } }); }); it('should handle userId', function () { const bid = Object.assign({}, abid); @@ -414,7 +414,7 @@ describe('Mgid bid adapter', function () { } }; const bidRequests = [bid]; - const bidderRequest = {userId: 'userid'}; + const bidderRequest = { userId: 'userid' }; const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.url).deep.equal('https://prebid.mgid.com/prebid/1'); expect(request.method).deep.equal('POST'); @@ -458,7 +458,7 @@ describe('Mgid bid adapter', function () { expect(data.device.language).to.deep.equal(lang); expect(data.imp[0].tagid).to.deep.equal('2/div'); expect(data.imp[0].ext.gpid).to.deep.equal('/1111/gpid'); - expect(data.imp[0].banner).to.deep.equal({w: 300, h: 250}); + expect(data.imp[0].banner).to.deep.equal({ w: 300, h: 250 }); expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ 'method': 'POST', @@ -472,8 +472,8 @@ describe('Mgid bid adapter', function () { native: '', }; bid.nativeParams = { - title: {required: true}, - image: {sizes: [80, 80]}, + title: { required: true }, + image: { sizes: [80, 80] }, }; const bidRequests = [bid]; const request = spec.buildRequests(bidRequests); @@ -485,8 +485,8 @@ describe('Mgid bid adapter', function () { native: '', }; bid.nativeParams = { - title: {required: true}, - image: {sizes: [80, 80]}, + title: { required: true }, + image: { sizes: [80, 80] }, sponsored: { }, }; @@ -508,7 +508,7 @@ describe('Mgid bid adapter', function () { expect(data.device.language).to.deep.equal(lang); expect(data.imp[0].tagid).to.deep.equal('2/div'); expect(data.imp[0].ext.gpid).to.deep.equal('/1111/gpid'); - expect(data.imp[0].native).is.a('object').and.to.deep.equal({'request': {'assets': [{'id': 1, 'required': 1, 'title': {'len': 80}}, {'id': 2, 'img': {'h': 80, 'type': 3, 'w': 80}, 'required': 0}, {'data': {'type': 1}, 'id': 11, 'required': 0}], 'plcmtcnt': 1}}); + expect(data.imp[0].native).is.a('object').and.to.deep.equal({ 'request': { 'assets': [{ 'id': 1, 'required': 1, 'title': { 'len': 80 } }, { 'id': 2, 'img': { 'h': 80, 'type': 3, 'w': 80 }, 'required': 0 }, { 'data': { 'type': 1 }, 'id': 11, 'required': 0 }], 'plcmtcnt': 1 } }); expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ 'method': 'POST', @@ -522,8 +522,8 @@ describe('Mgid bid adapter', function () { native: '', }; bid.nativeParams = { - title: {required: true}, - image: {wmin: 50, hmin: 50, required: true}, + title: { required: true }, + image: { wmin: 50, hmin: 50, required: true }, icon: {}, sponsored: { }, }; @@ -545,7 +545,7 @@ describe('Mgid bid adapter', function () { expect(data.device.w).equal(screenWidth); expect(data.device.language).to.deep.equal(lang); expect(data.imp[0].tagid).to.deep.equal('2/div'); - expect(data.imp[0].native).is.a('object').and.to.deep.equal({'request': {'assets': [{'id': 1, 'required': 1, 'title': {'len': 80}}, {'id': 2, 'img': {'h': 328, hmin: 50, 'type': 3, 'w': 492, wmin: 50}, 'required': 1}, {'id': 3, 'img': {'h': 50, 'type': 1, 'w': 50}, 'required': 0}, {'data': {'type': 1}, 'id': 11, 'required': 0}], 'plcmtcnt': 1}}); + expect(data.imp[0].native).is.a('object').and.to.deep.equal({ 'request': { 'assets': [{ 'id': 1, 'required': 1, 'title': { 'len': 80 } }, { 'id': 2, 'img': { 'h': 328, hmin: 50, 'type': 3, 'w': 492, wmin: 50 }, 'required': 1 }, { 'id': 3, 'img': { 'h': 50, 'type': 1, 'w': 50 }, 'required': 0 }, { 'data': { 'type': 1 }, 'id': 11, 'required': 0 }], 'plcmtcnt': 1 } }); expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ 'method': 'POST', @@ -559,8 +559,8 @@ describe('Mgid bid adapter', function () { native: '', }; bid.nativeParams = { - title: {required: true}, - image: {sizes: [80, 80]}, + title: { required: true }, + image: { sizes: [80, 80] }, sponsoredBy: { }, }; @@ -581,7 +581,7 @@ describe('Mgid bid adapter', function () { expect(data.device.w).equal(screenWidth); expect(data.device.language).to.deep.equal(lang); expect(data.imp[0].tagid).to.deep.equal('2/div'); - expect(data.imp[0].native).is.a('object').and.to.deep.equal({'request': {'assets': [{'id': 1, 'required': 1, 'title': {'len': 80}}, {'id': 2, 'img': {'h': 80, 'type': 3, 'w': 80}, 'required': 0}, {'data': {'type': 1}, 'id': 4, 'required': 0}], 'plcmtcnt': 1}}); + expect(data.imp[0].native).is.a('object').and.to.deep.equal({ 'request': { 'assets': [{ 'id': 1, 'required': 1, 'title': { 'len': 80 } }, { 'id': 2, 'img': { 'h': 80, 'type': 3, 'w': 80 }, 'required': 0 }, { 'data': { 'type': 1 }, 'id': 4, 'required': 0 }], 'plcmtcnt': 1 } }); expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ 'method': 'POST', @@ -614,7 +614,7 @@ describe('Mgid bid adapter', function () { expect(data.device.w).equal(screenWidth); expect(data.device.language).to.deep.equal(lang); expect(data.imp[0].tagid).to.deep.equal('2/div'); - expect(data.imp[0].banner).to.deep.equal({w: 300, h: 600, format: [{w: 300, h: 600}, {w: 300, h: 250}], pos: 1}); + expect(data.imp[0].banner).to.deep.equal({ w: 300, h: 600, format: [{ w: 300, h: 600 }, { w: 300, h: 250 }], pos: 1 }); expect(data.imp[0].secure).to.deep.equal(secure); expect(request).to.deep.equal({ @@ -649,8 +649,8 @@ describe('Mgid bid adapter', function () { segtax: 1, }, segment: [ - {id: '123'}, - {id: '456'}, + { id: '123' }, + { id: '456' }, ], }] } @@ -665,8 +665,8 @@ describe('Mgid bid adapter', function () { segtax: 2, }, segment: [ - {'id': '789'}, - {'id': '987'}, + { 'id': '789' }, + { 'id': '987' }, ], }] }, @@ -695,21 +695,21 @@ describe('Mgid bid adapter', function () { describe('interpretResponse', function () { it('should not push proper native bid response if adm is missing', function () { const resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': {'place': 0, 'crtype': 'native'}, 'adomain': ['test.com']}], 'seat': '44082'}]} + body: { 'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{ 'bid': [{ 'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': { 'place': 0, 'crtype': 'native' }, 'adomain': ['test.com'] }], 'seat': '44082' }] } }; const bids = spec.interpretResponse(resp); expect(bids).to.deep.equal([]) }); it('should not push proper native bid response if assets is empty', function () { const resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[],"imptrackers":["imptrackers1"]}}', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': {'place': 0, 'crtype': 'native'}, 'adomain': ['test.com']}], 'seat': '44082'}]} + body: { 'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{ 'bid': [{ 'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[],"imptrackers":["imptrackers1"]}}', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': { 'place': 0, 'crtype': 'native' }, 'adomain': ['test.com'] }], 'seat': '44082' }] } }; const bids = spec.interpretResponse(resp); expect(bids).to.deep.equal([]) }); it('should push proper native bid response, assets1', function () { const resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[{"id":1,"required":0,"title":{"text":"title1"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"image_src"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"icon_src"}},{"id":4,"required":0,"data":{"type":4,"value":"sponsored"}},{"id":5,"required":0,"data":{"type":6,"value":"price1"}},{"id":6,"required":0,"data":{"type":7,"value":"price2"}}],"imptrackers":["imptrackers1"]}}', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': {'place': 0, 'crtype': 'native'}, 'adomain': ['test.com']}], 'seat': '44082'}], ext: {'muidn': 'userid'}} + body: { 'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{ 'bid': [{ 'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[{"id":1,"required":0,"title":{"text":"title1"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"image_src"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"icon_src"}},{"id":4,"required":0,"data":{"type":4,"value":"sponsored"}},{"id":5,"required":0,"data":{"type":6,"value":"price1"}},{"id":6,"required":0,"data":{"type":7,"value":"price2"}}],"imptrackers":["imptrackers1"]}}', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': { 'place': 0, 'crtype': 'native' }, 'adomain': ['test.com'] }], 'seat': '44082' }], ext: { 'muidn': 'userid' } } }; const bids = spec.interpretResponse(resp); expect(bids).to.deep.equal([{ @@ -722,7 +722,7 @@ describe('Mgid bid adapter', function () { 'height': 0, 'isBurl': true, 'mediaType': 'native', - 'meta': {'advertiserDomains': ['test.com']}, + 'meta': { 'advertiserDomains': ['test.com'] }, 'native': { 'clickTrackers': [], 'clickUrl': 'link_url', @@ -753,7 +753,7 @@ describe('Mgid bid adapter', function () { }); it('should push proper native bid response, assets2', function () { const resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[{"id":1,"required":0,"title":{"text":"title1"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"image_src"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"icon_src"}}],"imptrackers":["imptrackers1"]}}', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': {'place': 0, 'crtype': 'native'}, 'adomain': ['test.com']}], 'seat': '44082'}]} + body: { 'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': 'GBP', 'seatbid': [{ 'bid': [{ 'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': '{"native":{"ver":"1.1","link":{"url":"link_url"},"assets":[{"id":1,"required":0,"title":{"text":"title1"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"image_src"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"icon_src"}}],"imptrackers":["imptrackers1"]}}', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'ext': { 'place': 0, 'crtype': 'native' }, 'adomain': ['test.com'] }], 'seat': '44082' }] } }; const bids = spec.interpretResponse(resp); expect(bids).to.deep.equal([ @@ -766,7 +766,7 @@ describe('Mgid bid adapter', function () { 'height': 0, 'isBurl': true, 'mediaType': 'native', - 'meta': {'advertiserDomains': ['test.com']}, + 'meta': { 'advertiserDomains': ['test.com'] }, 'netRevenue': true, 'nurl': 'https nurl', 'burl': 'https burl', @@ -800,7 +800,7 @@ describe('Mgid bid adapter', function () { }); it('should push proper banner bid response', function () { const resp = { - body: {'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': '', 'seatbid': [{'bid': [{'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': 'html: adm', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'adomain': ['test.com']}], 'seat': '44082'}]} + body: { 'id': '57c0c2b1b732ca', 'bidid': '57c0c2b1b732ca', 'cur': '', 'seatbid': [{ 'bid': [{ 'price': 1.5, 'h': 600, 'w': 300, 'id': '1', 'impid': '61e40632c53fc2', 'adid': '2898532/2419121/2592854/2499195', 'nurl': 'https nurl', 'burl': 'https burl', 'adm': 'html: adm', 'cid': '44082', 'crid': '2898532/2419121/2592854/2499195', 'cat': ['IAB7', 'IAB14', 'IAB18-3', 'IAB1-2'], 'adomain': ['test.com'] }], 'seat': '44082' }] } }; const bids = spec.interpretResponse(resp); expect(bids).to.deep.equal([ @@ -813,7 +813,7 @@ describe('Mgid bid adapter', function () { 'height': 600, 'isBurl': true, 'mediaType': 'banner', - 'meta': {'advertiserDomains': ['test.com']}, + 'meta': { 'advertiserDomains': ['test.com'] }, 'netRevenue': true, 'nurl': 'https nurl', 'burl': 'https burl', @@ -827,32 +827,32 @@ describe('Mgid bid adapter', function () { describe('getUserSyncs', function () { afterEach(function() { - config.setConfig({userSync: {syncsPerBidder: USERSYNC_DEFAULT_CONFIG.syncsPerBidder}}); + config.setConfig({ userSync: { syncsPerBidder: USERSYNC_DEFAULT_CONFIG.syncsPerBidder } }); }); it('should do nothing on getUserSyncs without inputs', function () { expect(spec.getUserSyncs()).to.equal(undefined) }); it('should return frame object with empty consents', function () { - const sync = spec.getUserSyncs({iframeEnabled: true}) + const sync = spec.getUserSyncs({ iframeEnabled: true }) expect(sync).to.have.length(1) expect(sync[0]).to.have.property('type', 'iframe') expect(sync[0]).to.have.property('url').match(/https:\/\/cm\.mgid\.com\/i\.html\?cbuster=\d+&gdpr_consent=&gdpr=0/) }); it('should return frame object with gdpr consent', function () { - const sync = spec.getUserSyncs({iframeEnabled: true}, undefined, {consentString: 'consent', gdprApplies: true}) + const sync = spec.getUserSyncs({ iframeEnabled: true }, undefined, { consentString: 'consent', gdprApplies: true }) expect(sync).to.have.length(1) expect(sync[0]).to.have.property('type', 'iframe') expect(sync[0]).to.have.property('url').match(/https:\/\/cm\.mgid\.com\/i\.html\?cbuster=\d+&gdpr_consent=consent&gdpr=1/) }); it('should return frame object with gdpr + usp', function () { - const sync = spec.getUserSyncs({iframeEnabled: true}, undefined, {consentString: 'consent1', gdprApplies: true}, {'consentString': 'consent2'}) + const sync = spec.getUserSyncs({ iframeEnabled: true }, undefined, { consentString: 'consent1', gdprApplies: true }, { 'consentString': 'consent2' }) expect(sync).to.have.length(1) expect(sync[0]).to.have.property('type', 'iframe') expect(sync[0]).to.have.property('url').match(/https:\/\/cm\.mgid\.com\/i\.html\?cbuster=\d+&gdpr_consent=consent1&gdpr=1&us_privacy=consent2/) }); it('should return img object with gdpr + usp', function () { - config.setConfig({userSync: {syncsPerBidder: undefined}}); - const sync = spec.getUserSyncs({pixelEnabled: true}, undefined, {consentString: 'consent1', gdprApplies: true}, {'consentString': 'consent2'}) + config.setConfig({ userSync: { syncsPerBidder: undefined } }); + const sync = spec.getUserSyncs({ pixelEnabled: true }, undefined, { consentString: 'consent1', gdprApplies: true }, { 'consentString': 'consent2' }) expect(sync).to.have.length(USERSYNC_DEFAULT_CONFIG.syncsPerBidder) for (let i = 0; i < USERSYNC_DEFAULT_CONFIG.syncsPerBidder; i++) { expect(sync[i]).to.have.property('type', 'image') @@ -860,14 +860,14 @@ describe('Mgid bid adapter', function () { } }); it('should return frame object with gdpr + usp', function () { - const sync = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}, undefined, {consentString: 'consent1', gdprApplies: true}, {'consentString': 'consent2'}) + const sync = spec.getUserSyncs({ iframeEnabled: true, pixelEnabled: true }, undefined, { consentString: 'consent1', gdprApplies: true }, { 'consentString': 'consent2' }) expect(sync).to.have.length(1) expect(sync[0]).to.have.property('type', 'iframe') expect(sync[0]).to.have.property('url').match(/https:\/\/cm\.mgid\.com\/i\.html\?cbuster=\d+&gdpr_consent=consent1&gdpr=1&us_privacy=consent2/) }); it('should return img (pixels) objects with gdpr + usp', function () { - const response = [{body: {ext: {cm: ['http://cm.mgid.com/i.gif?cdsp=1111', 'http://cm.mgid.com/i.gif']}}}] - const sync = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, response, {consentString: 'consent1', gdprApplies: true}, {'consentString': 'consent2'}) + const response = [{ body: { ext: { cm: ['http://cm.mgid.com/i.gif?cdsp=1111', 'http://cm.mgid.com/i.gif'] } } }] + const sync = spec.getUserSyncs({ iframeEnabled: false, pixelEnabled: true }, response, { consentString: 'consent1', gdprApplies: true }, { 'consentString': 'consent2' }) expect(sync).to.have.length(2) expect(sync[0]).to.have.property('type', 'image') expect(sync[0]).to.have.property('url').match(/http:\/\/cm\.mgid\.com\/i\.gif\?cdsp=1111&cbuster=\d+&gdpr_consent=consent1&gdpr=1&us_privacy=consent2/) @@ -878,12 +878,12 @@ describe('Mgid bid adapter', function () { describe('getUserSyncs with img from ext.cm and gdpr + usp + coppa + gpp', function () { afterEach(function() { - config.setConfig({coppa: undefined}) + config.setConfig({ coppa: undefined }) }); it('should return img (pixels) objects with gdpr + usp + coppa + gpp', function () { - config.setConfig({coppa: 1}); - const response = [{body: {ext: {cm: ['http://cm.mgid.com/i.gif?cdsp=1111', 'http://cm.mgid.com/i.gif']}}}] - const sync = spec.getUserSyncs({iframeEnabled: false, pixelEnabled: true}, response, {consentString: 'consent1', gdprApplies: true}, {'consentString': 'consent2'}, {gppString: 'gpp'}) + config.setConfig({ coppa: 1 }); + const response = [{ body: { ext: { cm: ['http://cm.mgid.com/i.gif?cdsp=1111', 'http://cm.mgid.com/i.gif'] } } }] + const sync = spec.getUserSyncs({ iframeEnabled: false, pixelEnabled: true }, response, { consentString: 'consent1', gdprApplies: true }, { 'consentString': 'consent2' }, { gppString: 'gpp' }) expect(sync).to.have.length(2) expect(sync[0]).to.have.property('type', 'image') expect(sync[0]).to.have.property('url').match(/http:\/\/cm\.mgid\.com\/i\.gif\?cdsp=1111&cbuster=\d+&gdpr_consent=consent1&gdpr=1&us_privacy=consent2&gppString=gpp&coppa=1/) @@ -902,7 +902,7 @@ describe('Mgid bid adapter', function () { it('should replace nurl and burl for native', function () { const burl = 'burl&s=${' + 'AUCTION_PRICE}'; const nurl = 'nurl&s=${' + 'AUCTION_PRICE}'; - const bid = {'bidderCode': 'mgid', 'width': 0, 'height': 0, 'statusMessage': 'Bid available', 'adId': '3d0b6ff1dda89', 'requestId': '2a423489e058a1', 'mediaType': 'native', 'source': 'client', 'ad': '{"native":{"ver":"1.1","link":{"url":"LinkURL"},"assets":[{"id":1,"required":0,"title":{"text":"TITLE"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"ImageURL"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"IconURL"}},{"id":11,"required":0,"data":{"type":1,"value":"sponsored"}}],"imptrackers":["ImpTrackerURL"]}}', 'cpm': 0.66, 'creativeId': '353538_591471', 'currency': 'USD', 'dealId': '', 'netRevenue': true, 'ttl': 300, 'nurl': nurl, 'burl': burl, 'isBurl': true, 'native': {'title': 'TITLE', 'image': {'url': 'ImageURL', 'height': 80, 'width': 80}, 'icon': {'url': 'IconURL', 'height': 50, 'width': 50}, 'sponsored': 'sponsored', 'clickUrl': 'LinkURL', 'clickTrackers': [], 'impressionTrackers': ['ImpTrackerURL'], 'jstracker': []}, 'auctionId': 'a92bffce-14d2-4f8f-a78a-7b9b5e4d28fa', 'responseTimestamp': 1556867386065, 'requestTimestamp': 1556867385916, 'bidder': 'mgid', 'adUnitCode': 'div-gpt-ad-1555415275793-0', 'timeToRespond': 149, 'pbLg': '0.50', 'pbMg': '0.60', 'pbHg': '0.66', 'pbAg': '0.65', 'pbDg': '0.66', 'pbCg': '', 'size': '0x0', 'adserverTargeting': {'hb_bidder': 'mgid', 'hb_adid': '3d0b6ff1dda89', 'hb_pb': '0.66', 'hb_size': '0x0', 'hb_source': 'client', 'hb_format': 'native', 'hb_native_title': 'TITLE', 'hb_native_image': 'hb_native_image:3d0b6ff1dda89', 'hb_native_icon': 'IconURL', 'hb_native_linkurl': 'hb_native_linkurl:3d0b6ff1dda89'}, 'status': 'targetingSet', 'params': [{'accountId': '184', 'placementId': '353538'}]}; + const bid = { 'bidderCode': 'mgid', 'width': 0, 'height': 0, 'statusMessage': 'Bid available', 'adId': '3d0b6ff1dda89', 'requestId': '2a423489e058a1', 'mediaType': 'native', 'source': 'client', 'ad': '{"native":{"ver":"1.1","link":{"url":"LinkURL"},"assets":[{"id":1,"required":0,"title":{"text":"TITLE"}},{"id":2,"required":0,"img":{"w":80,"h":80,"type":3,"url":"ImageURL"}},{"id":3,"required":0,"img":{"w":50,"h":50,"type":1,"url":"IconURL"}},{"id":11,"required":0,"data":{"type":1,"value":"sponsored"}}],"imptrackers":["ImpTrackerURL"]}}', 'cpm': 0.66, 'creativeId': '353538_591471', 'currency': 'USD', 'dealId': '', 'netRevenue': true, 'ttl': 300, 'nurl': nurl, 'burl': burl, 'isBurl': true, 'native': { 'title': 'TITLE', 'image': { 'url': 'ImageURL', 'height': 80, 'width': 80 }, 'icon': { 'url': 'IconURL', 'height': 50, 'width': 50 }, 'sponsored': 'sponsored', 'clickUrl': 'LinkURL', 'clickTrackers': [], 'impressionTrackers': ['ImpTrackerURL'], 'jstracker': [] }, 'auctionId': 'a92bffce-14d2-4f8f-a78a-7b9b5e4d28fa', 'responseTimestamp': 1556867386065, 'requestTimestamp': 1556867385916, 'bidder': 'mgid', 'adUnitCode': 'div-gpt-ad-1555415275793-0', 'timeToRespond': 149, 'pbLg': '0.50', 'pbMg': '0.60', 'pbHg': '0.66', 'pbAg': '0.65', 'pbDg': '0.66', 'pbCg': '', 'size': '0x0', 'adserverTargeting': { 'hb_bidder': 'mgid', 'hb_adid': '3d0b6ff1dda89', 'hb_pb': '0.66', 'hb_size': '0x0', 'hb_source': 'client', 'hb_format': 'native', 'hb_native_title': 'TITLE', 'hb_native_image': 'hb_native_image:3d0b6ff1dda89', 'hb_native_icon': 'IconURL', 'hb_native_linkurl': 'hb_native_linkurl:3d0b6ff1dda89' }, 'status': 'targetingSet', 'params': [{ 'accountId': '184', 'placementId': '353538' }] }; spec.onBidWon(bid); expect(bid.nurl).to.deep.equal('nurl&s=0.66'); expect(bid.burl).to.deep.equal('burl&s=0.66'); @@ -910,7 +910,7 @@ describe('Mgid bid adapter', function () { it('should replace nurl and burl for banner', function () { const burl = 'burl&s=${' + 'AUCTION_PRICE}'; const nurl = 'nurl&s=${' + 'AUCTION_PRICE}'; - const bid = {'bidderCode': 'mgid', 'width': 0, 'height': 0, 'statusMessage': 'Bid available', 'adId': '3d0b6ff1dda89', 'requestId': '2a423489e058a1', 'mediaType': 'banner', 'source': 'client', 'ad': burl, 'cpm': 0.66, 'creativeId': '353538_591471', 'currency': 'USD', 'dealId': '', 'netRevenue': true, 'ttl': 300, 'nurl': nurl, 'burl': burl, 'isBurl': true, 'auctionId': 'a92bffce-14d2-4f8f-a78a-7b9b5e4d28fa', 'responseTimestamp': 1556867386065, 'requestTimestamp': 1556867385916, 'bidder': 'mgid', 'adUnitCode': 'div-gpt-ad-1555415275793-0', 'timeToRespond': 149, 'pbLg': '0.50', 'pbMg': '0.60', 'pbHg': '0.66', 'pbAg': '0.65', 'pbDg': '0.66', 'pbCg': '', 'size': '0x0', 'adserverTargeting': {'hb_bidder': 'mgid', 'hb_adid': '3d0b6ff1dda89', 'hb_pb': '0.66', 'hb_size': '0x0', 'hb_source': 'client', 'hb_format': 'banner', 'hb_banner_title': 'TITLE', 'hb_banner_image': 'hb_banner_image:3d0b6ff1dda89', 'hb_banner_icon': 'IconURL', 'hb_banner_linkurl': 'hb_banner_linkurl:3d0b6ff1dda89'}, 'status': 'targetingSet', 'params': [{'accountId': '184', 'placementId': '353538'}]}; + const bid = { 'bidderCode': 'mgid', 'width': 0, 'height': 0, 'statusMessage': 'Bid available', 'adId': '3d0b6ff1dda89', 'requestId': '2a423489e058a1', 'mediaType': 'banner', 'source': 'client', 'ad': burl, 'cpm': 0.66, 'creativeId': '353538_591471', 'currency': 'USD', 'dealId': '', 'netRevenue': true, 'ttl': 300, 'nurl': nurl, 'burl': burl, 'isBurl': true, 'auctionId': 'a92bffce-14d2-4f8f-a78a-7b9b5e4d28fa', 'responseTimestamp': 1556867386065, 'requestTimestamp': 1556867385916, 'bidder': 'mgid', 'adUnitCode': 'div-gpt-ad-1555415275793-0', 'timeToRespond': 149, 'pbLg': '0.50', 'pbMg': '0.60', 'pbHg': '0.66', 'pbAg': '0.65', 'pbDg': '0.66', 'pbCg': '', 'size': '0x0', 'adserverTargeting': { 'hb_bidder': 'mgid', 'hb_adid': '3d0b6ff1dda89', 'hb_pb': '0.66', 'hb_size': '0x0', 'hb_source': 'client', 'hb_format': 'banner', 'hb_banner_title': 'TITLE', 'hb_banner_image': 'hb_banner_image:3d0b6ff1dda89', 'hb_banner_icon': 'IconURL', 'hb_banner_linkurl': 'hb_banner_linkurl:3d0b6ff1dda89' }, 'status': 'targetingSet', 'params': [{ 'accountId': '184', 'placementId': '353538' }] }; spec.onBidWon(bid); expect(bid.nurl).to.deep.equal('nurl&s=0.66'); expect(bid.burl).to.deep.equal(burl); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index a0b5e841f85..c801ecd2bfc 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1,8 +1,8 @@ -import {expect} from 'chai'; -import {spec, REQUEST_URL, SYNC_URL, DEFAULT_PH} from 'modules/openxBidAdapter.js'; -import {newBidder} from 'src/adapters/bidderFactory.js'; -import {BANNER, NATIVE, VIDEO} from 'src/mediaTypes.js'; -import {config} from 'src/config.js'; +import { expect } from 'chai'; +import { spec, REQUEST_URL, SYNC_URL, DEFAULT_PH } from 'modules/openxBidAdapter.js'; +import { newBidder } from 'src/adapters/bidderFactory.js'; +import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes.js'; +import { config } from 'src/config.js'; import * as utils from 'src/utils.js'; // load modules that register ORTB processors import 'src/prebid.js' @@ -13,10 +13,10 @@ import 'modules/priceFloors.js'; import 'modules/consentManagementTcf.js'; import 'modules/consentManagementUsp.js'; -import {deepClone} from 'src/utils.js'; -import {version} from 'package.json'; -import {addFPDToBidderRequest} from '../../helpers/fpd.js'; -import {hook} from '../../../src/hook.js'; +import { deepClone } from 'src/utils.js'; +import { version } from 'package.json'; +import { addFPDToBidderRequest } from '../../helpers/fpd.js'; +import { hook } from '../../../src/hook.js'; const DEFAULT_SYNC = SYNC_URL + '?ph=' + DEFAULT_PH; const BidRequestBuilder = function BidRequestBuilder(options) { @@ -91,7 +91,7 @@ describe('OpenxRtbAdapter', function () { bidder: 'openx', params: {}, adUnitCode: 'adunit-code', - mediaTypes: {banner: {}}, + mediaTypes: { banner: {} }, sizes: [[300, 250], [300, 600]], bidId: '30b31c1838de1e', bidderRequestId: '22edbae2733bf6', @@ -100,13 +100,13 @@ describe('OpenxRtbAdapter', function () { }); it('should return false when there is no delivery domain', function () { - bannerBid.params = {'unit': '12345678'}; + bannerBid.params = { 'unit': '12345678' }; expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); describe('when there is a delivery domain', function () { beforeEach(function () { - bannerBid.params = {delDomain: 'test-delivery-domain'} + bannerBid.params = { delDomain: 'test-delivery-domain' } }); it('should return false when there is no ad unit id and size', function () { @@ -362,7 +362,7 @@ describe('OpenxRtbAdapter', function () { }; beforeEach(function () { - mockBidderRequest = {refererInfo: {}}; + mockBidderRequest = { refererInfo: {} }; bidRequestsWithMediaTypes = [{ bidder: 'openx', @@ -502,7 +502,7 @@ describe('OpenxRtbAdapter', function () { params: { unit: '12345678', delDomain: 'test-del-domain', - customParams: {'Test1': 'testval1+', 'test2': ['testval2/', 'testval3']} + customParams: { 'Test1': 'testval1+', 'test2': ['testval2/', 'testval3'] } } } ); @@ -584,7 +584,7 @@ describe('OpenxRtbAdapter', function () { describe('FPD', function() { let bidRequests; - const mockBidderRequest = {refererInfo: {}}; + const mockBidderRequest = { refererInfo: {} }; beforeEach(function () { bidRequests = [{ @@ -801,27 +801,28 @@ describe('OpenxRtbAdapter', function () { describe('with user agent client hints', function () { it('should add device.sua if available', function () { - const bidderRequestWithUserAgentClientHints = { refererInfo: {}, + const bidderRequestWithUserAgentClientHints = { + refererInfo: {}, ortb2: { device: { sua: { source: 2, platform: { brand: 'macOS', - version: [ '12', '4', '0' ] + version: ['12', '4', '0'] }, browsers: [ { brand: 'Chromium', - version: [ '106', '0', '5249', '119' ] + version: ['106', '0', '5249', '119'] }, { brand: 'Google Chrome', - version: [ '106', '0', '5249', '119' ] + version: ['106', '0', '5249', '119'] }, { brand: 'Not;A=Brand', - version: [ '99', '0', '0', '0' ] + version: ['99', '0', '0', '0'] }], mobile: 0, model: 'Pro', @@ -829,12 +830,13 @@ describe('OpenxRtbAdapter', function () { architecture: 'x86' } } - }}; + } + }; let request = spec.buildRequests(bidRequests, bidderRequestWithUserAgentClientHints); expect(request[0].data.device.sua).to.exist; expect(request[0].data.device.sua).to.deep.equal(bidderRequestWithUserAgentClientHints.ortb2.device.sua); - const bidderRequestWithoutUserAgentClientHints = {refererInfo: {}, ortb2: {}}; + const bidderRequestWithoutUserAgentClientHints = { refererInfo: {}, ortb2: {} }; request = spec.buildRequests(bidRequests, bidderRequestWithoutUserAgentClientHints); expect(request[0].data.device?.sua).to.not.exist; }); @@ -1039,7 +1041,7 @@ describe('OpenxRtbAdapter', function () { it('should send a coppa flag there is when there is coppa param settings in the bid params', async function () { const request = spec.buildRequests(bidRequestsWithMediaTypes, await addFPDToBidderRequest(mockBidderRequest)); - request.params = {coppa: true}; + request.params = { coppa: true }; expect(request[0].data.regs.coppa).to.equal(1); }); @@ -1108,17 +1110,19 @@ describe('OpenxRtbAdapter', function () { bidId: 'test-bid-id-1', bidderRequestId: 'test-bid-request-1', auctionId: 'test-auction-1', - ortb2: {source: { - schain: schainConfig, - ext: {schain: schainConfig} - }} + ortb2: { + source: { + schain: schainConfig, + ext: { schain: schainConfig } + } + } }]; // Add schain to mockBidderRequest as well mockBidderRequest.ortb2 = { source: { schain: schainConfig, - ext: {schain: schainConfig} + ext: { schain: schainConfig } } }; }); @@ -1189,7 +1193,7 @@ describe('OpenxRtbAdapter', function () { }]; // enrich bid request with userId key/value - mockBidderRequest.ortb2 = {user: {ext: {eids}}} + mockBidderRequest.ortb2 = { user: { ext: { eids } } } const request = spec.buildRequests(bidRequests, mockBidderRequest); expect(request[0].data.user.ext.eids).to.eql(eids); }); @@ -1282,10 +1286,10 @@ describe('OpenxRtbAdapter', function () { auctionId: 'test-auction-id' }]; - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; - bidResponse = {nbr: 0}; // Unknown error - response = spec.interpretResponse({body: bidResponse}, bidRequest); + bidResponse = { nbr: 0 }; // Unknown error + response = spec.interpretResponse({ body: bidResponse }, bidRequest); }); it('should not return any bids', function () { @@ -1313,10 +1317,10 @@ describe('OpenxRtbAdapter', function () { auctionId: 'test-auction-id' }]; - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; - bidResponse = {ext: {}, id: 'test-bid-id'}; - response = spec.interpretResponse({body: bidResponse}, bidRequest); + bidResponse = { ext: {}, id: 'test-bid-id' }; + response = spec.interpretResponse({ body: bidResponse }, bidRequest); }); it('should not return any bids', function () { @@ -1344,10 +1348,10 @@ describe('OpenxRtbAdapter', function () { auctionId: 'test-auction-id' }]; - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; bidResponse = ''; // Unknown error - response = spec.interpretResponse({body: bidResponse}, bidRequest); + response = spec.interpretResponse({ body: bidResponse }, bidRequest); }); it('should not return any bids', function () { @@ -1397,10 +1401,10 @@ describe('OpenxRtbAdapter', function () { context('when there is a response, the common response properties', function () { beforeEach(function () { bidRequestConfigs = deepClone(SAMPLE_BID_REQUESTS); - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; bidResponse = deepClone(SAMPLE_BID_RESPONSE); - bid = spec.interpretResponse({body: bidResponse}, bidRequest).bids[0]; + bid = spec.interpretResponse({ body: bidResponse }, bidRequest).bids[0]; }); it('should return a price', function () { @@ -1476,7 +1480,7 @@ describe('OpenxRtbAdapter', function () { auctionId: 'test-auction-id' }]; - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; bidResponse = { seatbid: [{ @@ -1494,7 +1498,7 @@ describe('OpenxRtbAdapter', function () { cur: 'AUS' }; - bid = spec.interpretResponse({body: bidResponse}, bidRequest).bids[0]; + bid = spec.interpretResponse({ body: bidResponse }, bidRequest).bids[0]; }); it('should return the proper mediaType', function () { @@ -1522,7 +1526,7 @@ describe('OpenxRtbAdapter', function () { auctionId: 'test-auction-id' }]; - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; bidResponse = { seatbid: [{ @@ -1541,14 +1545,14 @@ describe('OpenxRtbAdapter', function () { }); it('should return the proper mediaType', function () { - bid = spec.interpretResponse({body: bidResponse}, bidRequest).bids[0]; + bid = spec.interpretResponse({ body: bidResponse }, bidRequest).bids[0]; expect(bid.mediaType).to.equal(Object.keys(bidRequestConfigs[0].mediaTypes)[0]); }); it('should return the proper vastUrl', function () { const winUrl = 'https//my.win.url'; bidResponse.seatbid[0].bid[0].nurl = winUrl - bid = spec.interpretResponse({body: bidResponse}, bidRequest).bids[0]; + bid = spec.interpretResponse({ body: bidResponse }, bidRequest).bids[0]; expect(bid.vastUrl).to.equal(winUrl); }); @@ -1576,7 +1580,7 @@ describe('OpenxRtbAdapter', function () { auctionId: 'test-auction-id' }]; - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; bidResponse = { seatbid: [{ @@ -1592,7 +1596,7 @@ describe('OpenxRtbAdapter', function () { }); it('should return video mediaType', function () { - bid = spec.interpretResponse({body: bidResponse}, bidRequest).bids[0]; + bid = spec.interpretResponse({ body: bidResponse }, bidRequest).bids[0]; expect(bid.mediaType).to.equal(VIDEO); }); }); @@ -1632,7 +1636,7 @@ describe('OpenxRtbAdapter', function () { auctionId: 'test-auction-id-2' }]; - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; bidResponse = { seatbid: [{ @@ -1648,7 +1652,7 @@ describe('OpenxRtbAdapter', function () { }); it('should return banner mediaType', function () { - bid = spec.interpretResponse({body: bidResponse}, bidRequest).bids[0]; + bid = spec.interpretResponse({ body: bidResponse }, bidRequest).bids[0]; expect(bid.mediaType).to.equal(BANNER); }); }); @@ -1685,7 +1689,7 @@ describe('OpenxRtbAdapter', function () { auctionId: 'test-auction-id' }]; - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; bidResponse = { seatbid: [{ @@ -1701,21 +1705,21 @@ describe('OpenxRtbAdapter', function () { }); it('should return the proper mediaType', function () { - bid = spec.interpretResponse({body: bidResponse}, bidRequest).bids[0]; + bid = spec.interpretResponse({ body: bidResponse }, bidRequest).bids[0]; expect(bid.mediaType).to.equal(Object.keys(bidRequestConfigs[0].mediaTypes)[0]); }); it('should return parsed adm JSON in native.ortb response field', function () { - bid = spec.interpretResponse({body: bidResponse}, bidRequest).bids[0]; + bid = spec.interpretResponse({ body: bidResponse }, bidRequest).bids[0]; expect(bid.native.ortb).to.deep.equal({ ver: '1.2', assets: [{ id: 1, required: 1, - title: {text: 'OpenX (Title)'} + title: { text: 'OpenX (Title)' } }], - link: {url: 'https://www.openx.com/'}, + link: { url: 'https://www.openx.com/' }, eventtrackers: [{ event: 1, method: 1, @@ -1758,7 +1762,7 @@ describe('OpenxRtbAdapter', function () { auctionId: 'test-auction-id' }]; - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; bidResponse = { seatbid: [{ @@ -1774,7 +1778,7 @@ describe('OpenxRtbAdapter', function () { }); it('should return banner mediaType', function () { - bid = spec.interpretResponse({body: bidResponse}, bidRequest).bids[0]; + bid = spec.interpretResponse({ body: bidResponse }, bidRequest).bids[0]; expect(bid.mediaType).to.equal(BANNER); }); }); @@ -1825,7 +1829,7 @@ describe('OpenxRtbAdapter', function () { auctionId: 'test-auction-id-2' }]; - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0]; bidResponse = { seatbid: [{ @@ -1841,7 +1845,7 @@ describe('OpenxRtbAdapter', function () { }); it('should return native mediaType', function () { - bid = spec.interpretResponse({body: bidResponse}, bidRequest).bids[0]; + bid = spec.interpretResponse({ body: bidResponse }, bidRequest).bids[0]; expect(bid.mediaType).to.equal(NATIVE); }); }); @@ -1851,42 +1855,42 @@ describe('OpenxRtbAdapter', function () { describe('user sync', function () { it('should register the default image pixel if no pixels available', function () { const syncs = spec.getUserSyncs( - {pixelEnabled: true}, + { pixelEnabled: true }, [] ); - expect(syncs).to.deep.equal([{type: 'image', url: DEFAULT_SYNC}]); + expect(syncs).to.deep.equal([{ type: 'image', url: DEFAULT_SYNC }]); }); it('should register custom syncUrl when exists', function () { const syncs = spec.getUserSyncs( - {pixelEnabled: true}, - [{body: {ext: {delDomain: 'www.url.com'}}}] + { pixelEnabled: true }, + [{ body: { ext: { delDomain: 'www.url.com' } } }] ); - expect(syncs).to.deep.equal([{type: 'image', url: 'https://www.url.com/w/1.0/pd'}]); + expect(syncs).to.deep.equal([{ type: 'image', url: 'https://www.url.com/w/1.0/pd' }]); }); it('should register custom syncUrl when exists', function () { const syncs = spec.getUserSyncs( - {pixelEnabled: true}, - [{body: {ext: {platform: 'abc'}}}] + { pixelEnabled: true }, + [{ body: { ext: { platform: 'abc' } } }] ); - expect(syncs).to.deep.equal([{type: 'image', url: SYNC_URL + '?ph=abc'}]); + expect(syncs).to.deep.equal([{ type: 'image', url: SYNC_URL + '?ph=abc' }]); }); it('when iframe sync is allowed, it should register an iframe sync', function () { const syncs = spec.getUserSyncs( - {iframeEnabled: true}, + { iframeEnabled: true }, [] ); - expect(syncs).to.deep.equal([{type: 'iframe', url: DEFAULT_SYNC}]); + expect(syncs).to.deep.equal([{ type: 'iframe', url: DEFAULT_SYNC }]); }); it('should prioritize iframe over image for user sync', function () { const syncs = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + { iframeEnabled: true, pixelEnabled: true }, [] ); - expect(syncs).to.deep.equal([{type: 'iframe', url: DEFAULT_SYNC}]); + expect(syncs).to.deep.equal([{ type: 'iframe', url: DEFAULT_SYNC }]); }); describe('when gdpr applies', function () { @@ -1904,8 +1908,8 @@ describe('OpenxRtbAdapter', function () { }); it('when there is a response, it should have the gdpr query params', () => { - const [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + const [{ url }] = spec.getUserSyncs( + { iframeEnabled: true, pixelEnabled: true }, [], gdprConsent ); @@ -1915,8 +1919,8 @@ describe('OpenxRtbAdapter', function () { }); it('should not send signals if no consent object is available', function () { - const [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + const [{ url }] = spec.getUserSyncs( + { iframeEnabled: true, pixelEnabled: true }, [], ); expect(url).to.not.have.string('gdpr_consent='); @@ -1930,8 +1934,8 @@ describe('OpenxRtbAdapter', function () { gppString: 'gpp-pixel-consent', applicableSections: [6, 7] } - const [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + const [{ url }] = spec.getUserSyncs( + { iframeEnabled: true, pixelEnabled: true }, [], undefined, undefined, @@ -1951,8 +1955,8 @@ describe('OpenxRtbAdapter', function () { gppString: 'gpp-pixel-consent', applicableSections: [6, 7] } - const [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + const [{ url }] = spec.getUserSyncs( + { iframeEnabled: true, pixelEnabled: true }, [], gdprConsent, undefined, @@ -1969,8 +1973,8 @@ describe('OpenxRtbAdapter', function () { const gppConsent = { applicableSections: [6, 7] } - const [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + const [{ url }] = spec.getUserSyncs( + { iframeEnabled: true, pixelEnabled: true }, [], undefined, undefined, @@ -1985,8 +1989,8 @@ describe('OpenxRtbAdapter', function () { const gppConsent = { gppString: 'gpp-pixel-consent', } - const [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + const [{ url }] = spec.getUserSyncs( + { iframeEnabled: true, pixelEnabled: true }, [], undefined, undefined, @@ -2002,8 +2006,8 @@ describe('OpenxRtbAdapter', function () { gppString: 'gpp-pixel-consent', applicableSections: [] } - const [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + const [{ url }] = spec.getUserSyncs( + { iframeEnabled: true, pixelEnabled: true }, [], undefined, undefined, @@ -2015,8 +2019,8 @@ describe('OpenxRtbAdapter', function () { }); it('should not send GPP query params when GPP consent object not available', function () { - const [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + const [{ url }] = spec.getUserSyncs( + { iframeEnabled: true, pixelEnabled: true }, [], undefined, undefined, undefined ); expect(url).to.not.have.string('gpp='); @@ -2033,8 +2037,8 @@ describe('OpenxRtbAdapter', function () { uspPixelUrl = `${DEFAULT_SYNC}&us_privacy=${privacyString}` }); it('should send the us privacy string, ', () => { - const [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + const [{ url }] = spec.getUserSyncs( + { iframeEnabled: true, pixelEnabled: true }, [], undefined, usPrivacyConsent @@ -2043,8 +2047,8 @@ describe('OpenxRtbAdapter', function () { }); it('should not send signals if no consent string is available', function () { - const [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, + const [{ url }] = spec.getUserSyncs( + { iframeEnabled: true, pixelEnabled: true }, [], ); expect(url).to.not.have.string('us_privacy='); diff --git a/test/spec/modules/ozoneBidAdapter_spec.js b/test/spec/modules/ozoneBidAdapter_spec.js index 16440f7e11d..9e6092f2cad 100644 --- a/test/spec/modules/ozoneBidAdapter_spec.js +++ b/test/spec/modules/ozoneBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import { spec, getWidthAndHeightFromVideoObject, defaultSize } from 'modules/ozoneBidAdapter.js'; import { config } from 'src/config.js'; -import {Renderer} from '../../../src/Renderer.js'; +import { Renderer } from '../../../src/Renderer.js'; import * as utils from '../../../src/utils.js'; -import {deepSetValue, mergeDeep} from '../../../src/utils.js'; +import { deepSetValue, mergeDeep } from '../../../src/utils.js'; const OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; const BIDDER_CODE = 'ozone'; spec.getGetParametersAsObject = function() { @@ -20,8 +20,8 @@ var validBidRequests = [ bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } }] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } @@ -34,8 +34,8 @@ var validBidRequestsNoCustomData = [ bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } }] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } @@ -49,8 +49,8 @@ var validBidRequestsMulti = [ bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } }] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' }, @@ -62,8 +62,8 @@ var validBidRequestsMulti = [ bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c0', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } }] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } @@ -769,8 +769,8 @@ var validBidRequestsWithUserIdData = [ bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } }] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87', userId: { @@ -779,9 +779,9 @@ var validBidRequestsWithUserIdData = [ 'id5id': { uid: '1111', ext: { linkType: 2, abTestingControlGroup: false } }, 'criteoId': '1111criteoId', 'idl_env': 'liverampId', - 'lipb': {'lipbid': 'lipbidId123'}, - 'parrableId': {'eid': '01.5678.parrableid'}, - 'sharedid': {'id': '01EAJWWNEPN3CYMM5N8M5VXY22', 'third': '01EAJWWNEPN3CYMM5N8M5VXY22'} + 'lipb': { 'lipbid': 'lipbidId123' }, + 'parrableId': { 'eid': '01.5678.parrableid' }, + 'sharedid': { 'id': '01EAJWWNEPN3CYMM5N8M5VXY22', 'third': '01EAJWWNEPN3CYMM5N8M5VXY22' } }, userIdAsEids: [ { @@ -827,14 +827,14 @@ var validBidRequestsWithUserIdData = [ { 'source': 'lipb', 'uids': [{ - 'id': {'lipbid': 'lipbidId123'}, + 'id': { 'lipbid': 'lipbidId123' }, 'atype': 1, }] }, { 'source': 'parrableId', 'uids': [{ - 'id': {'eid': '01.5678.parrableid'}, + 'id': { 'eid': '01.5678.parrableid' }, 'atype': 1, }] } @@ -849,7 +849,7 @@ var validBidRequestsMinimal = [ bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - params: { publisherId: '9876abcd12-3', placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + params: { publisherId: '9876abcd12-3', placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } }] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } @@ -862,8 +862,8 @@ var validBidRequestsNoSizes = [ bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } }] }, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; @@ -875,9 +875,9 @@ var validBidRequestsWithBannerMediaType = [ bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } } ] }, - mediaTypes: {banner: {sizes: [[300, 250], [300, 600]]}}, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, banner: { format: [{ w: 300, h: 250 }, { w: 300, h: 600 }], h: 250, topframe: 1, w: 300 } }] }, + mediaTypes: { banner: { sizes: [[300, 250], [300, 600]] } }, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; @@ -889,9 +889,9 @@ var validBidRequestsWithNonBannerMediaTypesAndValidOutstreamVideo = [ bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, video: {skippable: true, playback_method: ['auto_play_sound_off'], targetDiv: 'some-different-div-id-to-my-adunitcode'} } ] }, - mediaTypes: {video: {mimes: ['video/mp4'], 'context': 'outstream', 'sizes': [640, 480], playerSize: [640, 480]}, native: {info: 'dummy data'}}, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ id: '2899ec066a91ff8', tagid: 'undefined', secure: 1, video: { skippable: true, playback_method: ['auto_play_sound_off'], targetDiv: 'some-different-div-id-to-my-adunitcode' } }] }, + mediaTypes: { video: { mimes: ['video/mp4'], 'context': 'outstream', 'sizes': [640, 480], playerSize: [640, 480] }, native: { info: 'dummy data' } }, transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' } ]; @@ -1091,8 +1091,8 @@ var validBidderRequest = { bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' }] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' }], @@ -1112,8 +1112,8 @@ var validBidderRequestWithCookieDeprecation = { bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' }] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' }], @@ -1172,8 +1172,8 @@ var bidderRequestWithFullGdpr = { bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, - params: { publisherId: '9876abcd12-3', customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [ { banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' } ] }, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, + params: { publisherId: '9876abcd12-3', customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' }] }, sizes: [[300, 250], [300, 600]], transactionId: '2e63c0ed-b10c-4008-aed5-84582cecfe87' }], @@ -1258,16 +1258,16 @@ var bidderRequestWithPartialGdpr = { bidRequestsCount: 1, bidder: 'ozone', bidderRequestId: '1c1586b27a1b5c8', - crumbs: {pubcid: '203a0692-f728-4856-87f6-9a25a6b63715'}, + crumbs: { pubcid: '203a0692-f728-4856-87f6-9a25a6b63715' }, params: { publisherId: '9876abcd12-3', - customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}], + customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }], placementId: '1310000099', siteId: '1234567890', id: 'fea37168-78f1-4a23-a40e-88437a99377e', auctionId: '27dcb421-95c6-4024-a624-3c03816c5f99', imp: [{ - banner: {topframe: 1, w: 300, h: 250, format: [{w: 300, h: 250}, {w: 300, h: 600}]}, + banner: { topframe: 1, w: 300, h: 250, format: [{ w: 300, h: 250 }, { w: 300, h: 600 }] }, id: '2899ec066a91ff8', secure: 1, tagid: 'undefined' @@ -1412,7 +1412,7 @@ var validResponse2Bids = { } } } - } ], + }], 'seat': 'appnexus' } ], @@ -1498,7 +1498,7 @@ var validResponse2BidsSameAdunit = { } } } - } ], + }], 'seat': 'ozappnexus' } ], @@ -2212,37 +2212,37 @@ describe('ozone Adapter', function () { it('should check deepSet means "unconditionally set element to this value, optionally building the path" and Object.assign will blend the keys together, neither will deeply merge nested objects successfully.', function () { let xx = {}; let yy = { - 'publisher': {'id': 123}, + 'publisher': { 'id': 123 }, 'page': 567, 'id': 900 }; deepSetValue(xx, 'site', yy); expect(xx.site).to.have.all.keys(['publisher', 'page', 'id']); - xx = {site: {'name': 'test1'}}; + xx = { site: { 'name': 'test1' } }; deepSetValue(xx, 'site', yy); - expect(xx.site).to.have.all.keys([ 'publisher', 'page', 'id']); - xx = {site: {'name': 'test1'}}; + expect(xx.site).to.have.all.keys(['publisher', 'page', 'id']); + xx = { site: { 'name': 'test1' } }; Object.assign(xx.site, yy); - expect(xx.site).to.have.all.keys([ 'publisher', 'page', 'id', 'name']); - xx = {site: {'name': 'test1'}}; + expect(xx.site).to.have.all.keys(['publisher', 'page', 'id', 'name']); + xx = { site: { 'name': 'test1' } }; deepSetValue(xx, 'site', yy); - expect(xx.site).to.have.all.keys([ 'publisher', 'page', 'id']); - xx = {regs: {dsa: {'val1:': 1}}}; - deepSetValue(xx, 'regs.ext.usprivacy', {'usp_key': 'usp_value'}); + expect(xx.site).to.have.all.keys(['publisher', 'page', 'id']); + xx = { regs: { dsa: { 'val1:': 1 } } }; + deepSetValue(xx, 'regs.ext.usprivacy', { 'usp_key': 'usp_value' }); expect(xx.regs).to.have.all.keys(['dsa', 'ext']); - xx = {regs: {dsa: {'val1:': 1}}}; - deepSetValue(xx.regs, 'ext.usprivacy', {'usp_key': 'usp_value'}); + xx = { regs: { dsa: { 'val1:': 1 } } }; + deepSetValue(xx.regs, 'ext.usprivacy', { 'usp_key': 'usp_value' }); expect(xx.regs).to.have.all.keys(['dsa', 'ext']); - let ozoneRequest = {user: { ext: {'data': 'some data ... '}, keywords: "a,b,c"}}; - Object.assign(ozoneRequest, {user: {ext: {eids: ['some eid', 'another one']}}}); + let ozoneRequest = { user: { ext: { 'data': 'some data ... ' }, keywords: "a,b,c" } }; + Object.assign(ozoneRequest, { user: { ext: { eids: ['some eid', 'another one'] } } }); expect(ozoneRequest.user.ext).to.have.all.keys(['eids']); }); it('should verify that mergeDeep does what I want it to do', function() { - let ozoneRequest = {user: { ext: {'data': 'some data ... '}, keywords: "a,b,c"}}; - ozoneRequest = mergeDeep(ozoneRequest, {user: {ext: {eids: ['some eid', 'another one']}}}); + let ozoneRequest = { user: { ext: { 'data': 'some data ... ' }, keywords: "a,b,c" } }; + ozoneRequest = mergeDeep(ozoneRequest, { user: { ext: { eids: ['some eid', 'another one'] } } }); expect(ozoneRequest.user.ext).to.have.all.keys(['eids', 'data']); - ozoneRequest = {user: { ext: {'data': 'some data ... '}, keywords: "a,b,c"}}; - mergeDeep(ozoneRequest, {user: {ext: {eids: ['some eid', 'another one']}}}); + ozoneRequest = { user: { ext: { 'data': 'some data ... ' }, keywords: "a,b,c" } }; + mergeDeep(ozoneRequest, { user: { ext: { eids: ['some eid', 'another one'] } } }); expect(ozoneRequest.user.ext).to.have.all.keys(['eids', 'data']); }); }); @@ -2264,7 +2264,7 @@ describe('ozone Adapter', function () { placementId: '1310000099', publisherId: '9876abcd12-3', siteId: '1234567890', - customData: [{'settings': {}, 'targeting': {'gender': 'bart', 'age': 'low'}}] + customData: [{ 'settings': {}, 'targeting': { 'gender': 'bart', 'age': 'low' } }] }, siteId: 1234567890 } @@ -2446,7 +2446,7 @@ describe('ozone Adapter', function () { 'placementId': '1234567890', 'publisherId': '9876abcd12-3', 'siteId': '1234567890', - 'customData': {'gender': 'bart', 'age': 'low'} + 'customData': { 'gender': 'bart', 'age': 'low' } } }; it('should not validate customData being an object, not an array', function () { @@ -2469,7 +2469,7 @@ describe('ozone Adapter', function () { params: { 'placementId': '1234567890', 'publisherId': '9876abcd12-3', - 'customData': [{'settings': {}, 'xx': {'gender': 'bart', 'age': 'low'}}], + 'customData': [{ 'settings': {}, 'xx': { 'gender': 'bart', 'age': 'low' } }], siteId: '1234567890' } }; @@ -2481,7 +2481,7 @@ describe('ozone Adapter', function () { params: { 'placementId': '1234567890', 'publisherId': '9876abcd12-3', - 'customData': [{'settings': {}, 'targeting': 'this should be an object'}], + 'customData': [{ 'settings': {}, 'targeting': 'this should be an object' }], siteId: '1234567890' } }; @@ -2508,8 +2508,7 @@ describe('ozone Adapter', function () { siteId: '1234567890' }, mediaTypes: { - video: { - mimes: ['video/mp4']} + video: { mimes: ['video/mp4'] } } }; it('should not validate video without context attribute', function () { @@ -2525,7 +2524,8 @@ describe('ozone Adapter', function () { mediaTypes: { video: { mimes: ['video/mp4'], - 'context': 'outstream'}, + 'context': 'outstream' + }, } }; it('should validate video outstream being sent', function () { @@ -2573,7 +2573,7 @@ describe('ozone Adapter', function () { }); it('ignores ozoneData in & after version 2.1.1', function () { const validBidRequestsWithOzoneData = JSON.parse(JSON.stringify(validBidRequests)); - validBidRequestsWithOzoneData[0].params.ozoneData = {'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null'}; + validBidRequestsWithOzoneData[0].params.ozoneData = { 'networkID': '3048', 'dfpSiteID': 'd.thesun', 'sectionID': 'homepage', 'path': '/', 'sec_id': 'null', 'sec': 'sec', 'topics': 'null', 'kw': 'null', 'aid': 'null', 'search': 'null', 'article_type': 'null', 'hide_ads': '', 'article_slug': 'null' }; const request = spec.buildRequests(validBidRequestsWithOzoneData, validBidderRequest); expect(request.data).to.be.a('string'); var data = JSON.parse(request.data); @@ -2603,11 +2603,11 @@ describe('ozone Adapter', function () { expect(request).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); }); it('should be able to handle non-single requests', function () { - config.setConfig({'ozone': {'singleRequest': false}}); + config.setConfig({ 'ozone': { 'singleRequest': false } }); const request = spec.buildRequests(validBidRequestsNoSizes, validBidderRequest); expect(request).to.be.a('array'); expect(request[0]).to.have.all.keys(['bidderRequest', 'data', 'method', 'url']); - config.setConfig({'ozone': {'singleRequest': true}}); + config.setConfig({ 'ozone': { 'singleRequest': true } }); }); it('should add gdpr consent information to the request when ozone is true', function () { const consentString = 'BOcocyaOcocyaAfEYDENCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NphLgA=='; @@ -2618,8 +2618,8 @@ describe('ozone Adapter', function () { vendorData: { metadata: consentString, gdprApplies: true, - vendorConsents: {524: true}, - purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true} + vendorConsents: { 524: true }, + purposeConsents: { 1: true, 2: true, 3: true, 4: true, 5: true } } } const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); @@ -2653,7 +2653,7 @@ describe('ozone Adapter', function () { metadata: consentString, gdprApplies: true, vendorConsents: {}, - purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true} + purposeConsents: { 1: true, 2: true, 3: true, 4: true, 5: true } } }; const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); @@ -2664,7 +2664,7 @@ describe('ozone Adapter', function () { const gppString = 'gppConsentString'; const gppSections = [7, 8, 9]; const bidderRequest = JSON.parse(JSON.stringify(validBidderRequest)); - bidderRequest.ortb2 = {regs: {gpp: gppString, gpp_sid: gppSections}}; + bidderRequest.ortb2 = { regs: { gpp: gppString, gpp_sid: gppSections } }; const request = spec.buildRequests(validBidRequestsNoSizes, bidderRequest); const payload = JSON.parse(request.data); expect(payload.regs.ext.gpp).to.equal(gppString); @@ -2684,19 +2684,19 @@ describe('ozone Adapter', function () { vendorData: { metadata: consentString, gdprApplies: true, - vendorConsents: {524: true}, - purposeConsents: {1: true, 2: true, 3: true, 4: true, 5: true} + vendorConsents: { 524: true }, + purposeConsents: { 1: true, 2: true, 3: true, 4: true, 5: true } } }; const bidRequests = JSON.parse(JSON.stringify(validBidRequests)); bidRequests[0]['userId'] = { - 'digitrustid': {data: {id: 'DTID', keyv: 4, privacy: {optout: false}, producer: 'ABC', version: 2}}, + 'digitrustid': { data: { id: 'DTID', keyv: 4, privacy: { optout: false }, producer: 'ABC', version: 2 } }, 'id5id': { uid: '1111', ext: { linkType: 2, abTestingControlGroup: false } }, 'idl_env': '3333', 'parrableid': 'eidVersion.encryptionKeyReference.encryptedValue', 'pubcid': '5555', 'tdid': '6666', - 'sharedid': {'id': '01EAJWWNEPN3CYMM5N8M5VXY22', 'third': '01EAJWWNEPN3CYMM5N8M5VXY22'} + 'sharedid': { 'id': '01EAJWWNEPN3CYMM5N8M5VXY22', 'third': '01EAJWWNEPN3CYMM5N8M5VXY22' } }; bidRequests[0]['userIdAsEids'] = validBidRequestsWithUserIdData[0]['userIdAsEids']; const request = spec.buildRequests(bidRequests, bidderRequest); @@ -2733,32 +2733,32 @@ describe('ozone Adapter', function () { }); it('replaces the auction url for a config override', function () { const fakeOrigin = 'http://sometestendpoint'; - config.setConfig({'ozone': {'endpointOverride': {'origin': fakeOrigin}}}); + config.setConfig({ 'ozone': { 'endpointOverride': { 'origin': fakeOrigin } } }); const request = spec.buildRequests(validBidRequests, validBidderRequest); expect(request.url).to.equal(fakeOrigin + '/openrtb2/auction'); expect(request.method).to.equal('POST'); const data = JSON.parse(request.data); expect(data.ext.ozone.origin).to.equal(fakeOrigin); - config.setConfig({'ozone': {'kvpPrefix': null, 'endpointOverride': null}}); + config.setConfig({ 'ozone': { 'kvpPrefix': null, 'endpointOverride': null } }); }); it('replaces the FULL auction url for a config override', function () { const fakeurl = 'http://sometestendpoint/myfullurl'; - config.setConfig({'ozone': {'endpointOverride': {'auctionUrl': fakeurl}}}); + config.setConfig({ 'ozone': { 'endpointOverride': { 'auctionUrl': fakeurl } } }); const request = spec.buildRequests(validBidRequests, validBidderRequest); expect(request.url).to.equal(fakeurl); expect(request.method).to.equal('POST'); const data = JSON.parse(request.data); expect(data.ext.ozone.origin).to.equal(fakeurl); - config.setConfig({'ozone': {'kvpPrefix': null, 'endpointOverride': null}}); + config.setConfig({ 'ozone': { 'kvpPrefix': null, 'endpointOverride': null } }); }); it('replaces the renderer url for a config override', function () { const fakeUrl = 'http://renderer.com'; - config.setConfig({'ozone': {'endpointOverride': {'rendererUrl': fakeUrl}}}); + config.setConfig({ 'ozone': { 'endpointOverride': { 'rendererUrl': fakeUrl } } }); const result = spec.interpretResponse(getCleanValidVideoResponse(), validBidderRequest1OutstreamVideo2020); const bid = result[0]; expect(bid.renderer).to.be.an.instanceOf(Renderer); expect(bid.renderer.url).to.equal(fakeUrl); - config.setConfig({'ozone': {'kvpPrefix': null, 'endpointOverride': null}}); + config.setConfig({ 'ozone': { 'kvpPrefix': null, 'endpointOverride': null } }); }); it('should create a meta object on each bid returned', function () { const request = spec.buildRequests(validBidRequests, validBidderRequest); @@ -2769,7 +2769,7 @@ describe('ozone Adapter', function () { it('should use oztestmode GET value if set', function() { var specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { - return {'oztestmode': 'mytestvalue_123'}; + return { 'oztestmode': 'mytestvalue_123' }; }; const request = specMock.buildRequests(validBidRequests, validBidderRequest); const data = JSON.parse(request.data); @@ -2779,7 +2779,7 @@ describe('ozone Adapter', function () { it('should ignore these GET params if present (removed 202410): ozf, ozpf, ozrp, ozip', function() { var specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { - return {ozf: '1', ozpf: '10', ozrp: '2', ozip: '123'}; + return { ozf: '1', ozpf: '10', ozrp: '2', ozip: '123' }; }; const request = specMock.buildRequests(validBidRequests, validBidderRequest); const data = JSON.parse(request.data); @@ -2788,7 +2788,7 @@ describe('ozone Adapter', function () { it('should use oztestmode GET value if set, even if there is no customdata in config', function() { var specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { - return {'oztestmode': 'mytestvalue_123'}; + return { 'oztestmode': 'mytestvalue_123' }; }; const request = specMock.buildRequests(validBidRequestsMinimal, validBidderRequest); const data = JSON.parse(request.data); @@ -2804,7 +2804,7 @@ describe('ozone Adapter', function () { expect(data.imp[0].ext.gpid).to.equal('/22037345/projectozone'); }); it('should batch into 10s if config is set to true', function () { - config.setConfig({ozone: {'batchRequests': true}}); + config.setConfig({ ozone: { 'batchRequests': true } }); var specMock = utils.deepClone(spec); const arrReq = []; for (let i = 0; i < 25; i++) { @@ -2817,7 +2817,7 @@ describe('ozone Adapter', function () { config.resetConfig(); }); it('should batch into 7 if config is set to 7', function () { - config.setConfig({ozone: {'batchRequests': 7}}); + config.setConfig({ ozone: { 'batchRequests': 7 } }); var specMock = utils.deepClone(spec); const arrReq = []; for (let i = 0; i < 25; i++) { @@ -2830,7 +2830,7 @@ describe('ozone Adapter', function () { config.resetConfig(); }); it('should not batch if config is set to false and singleRequest is true', function () { - config.setConfig({ozone: {'batchRequests': false, 'singleRequest': true}}); + config.setConfig({ ozone: { 'batchRequests': false, 'singleRequest': true } }); var specMock = utils.deepClone(spec); const arrReq = []; for (let i = 0; i < 15; i++) { @@ -2843,7 +2843,7 @@ describe('ozone Adapter', function () { config.resetConfig(); }); it('should not batch if config is set to invalid value -10 and singleRequest is true', function () { - config.setConfig({ozone: {'batchRequests': -10, 'singleRequest': true}}); + config.setConfig({ ozone: { 'batchRequests': -10, 'singleRequest': true } }); var specMock = utils.deepClone(spec); const arrReq = []; for (let i = 0; i < 15; i++) { @@ -2858,7 +2858,7 @@ describe('ozone Adapter', function () { it('should use GET values for batchRequests if found', function() { var specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { - return {'batchRequests': '5'}; + return { 'batchRequests': '5' }; }; const arrReq = []; for (let i = 0; i < 25; i++) { @@ -2870,25 +2870,25 @@ describe('ozone Adapter', function () { expect(request.length).to.equal(5); specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { - return {'batchRequests': '10'}; + return { 'batchRequests': '10' }; }; request = specMock.buildRequests(arrReq, validBidderRequest); expect(request.length).to.equal(3); specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { - return {'batchRequests': true}; + return { 'batchRequests': true }; }; request = specMock.buildRequests(arrReq, validBidderRequest); expect(request.method).to.equal('POST'); specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { - return {'batchRequests': 'true'}; + return { 'batchRequests': 'true' }; }; request = specMock.buildRequests(arrReq, validBidderRequest); expect(request.method).to.equal('POST'); specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { - return {'batchRequests': -5}; + return { 'batchRequests': -5 }; }; request = specMock.buildRequests(arrReq, validBidderRequest); expect(request.method).to.equal('POST'); @@ -2896,7 +2896,7 @@ describe('ozone Adapter', function () { it('should use a valid ozstoredrequest GET value if set to override the placementId values, and set oz_rw if we find it', function() { var specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { - return {'ozstoredrequest': '1122334455'}; + return { 'ozstoredrequest': '1122334455' }; }; const request = specMock.buildRequests(validBidRequestsMinimal, validBidderRequest); const data = JSON.parse(request.data); @@ -2906,7 +2906,7 @@ describe('ozone Adapter', function () { it('should NOT use an invalid ozstoredrequest GET value if set to override the placementId values, and set oz_rw to 0', function() { var specMock = utils.deepClone(spec); specMock.getGetParametersAsObject = function() { - return {'ozstoredrequest': 'BADVAL'}; + return { 'ozstoredrequest': 'BADVAL' }; }; const request = specMock.buildRequests(validBidRequestsMinimal, validBidderRequest); const data = JSON.parse(request.data); @@ -2914,7 +2914,7 @@ describe('ozone Adapter', function () { expect(data.imp[0].ext.prebid.storedrequest.id).to.equal('1310000099'); }); it('should pick up the config value of coppa & set it in the request', function () { - config.setConfig({'coppa': true}); + config.setConfig({ 'coppa': true }); const request = spec.buildRequests(validBidRequestsNoSizes, validBidderRequest); const payload = JSON.parse(request.data); expect(payload.regs).to.include.keys('coppa'); @@ -2922,21 +2922,21 @@ describe('ozone Adapter', function () { config.resetConfig(); }); it('should pick up the config value of coppa & only set it in the request if its true', function () { - config.setConfig({'coppa': false}); + config.setConfig({ 'coppa': false }); const request = spec.buildRequests(validBidRequestsNoSizes, validBidderRequest); const payload = JSON.parse(request.data); expect(utils.deepAccess(payload, 'regs.coppa')).to.be.undefined; config.resetConfig(); }); it('should handle oz_omp_floor correctly', function () { - config.setConfig({'ozone': {'oz_omp_floor': 1.56}}); + config.setConfig({ 'ozone': { 'oz_omp_floor': 1.56 } }); const request = spec.buildRequests(validBidRequestsNoSizes, validBidderRequest); const payload = JSON.parse(request.data); expect(utils.deepAccess(payload, 'ext.ozone.oz_omp_floor')).to.equal(1.56); config.resetConfig(); }); it('should ignore invalid oz_omp_floor values', function () { - config.setConfig({'ozone': {'oz_omp_floor': '1.56'}}); + config.setConfig({ 'ozone': { 'oz_omp_floor': '1.56' } }); const request = spec.buildRequests(validBidRequestsNoSizes, validBidderRequest); const payload = JSON.parse(request.data); expect(utils.deepAccess(payload, 'ext.ozone.oz_omp_floor')).to.be.undefined; @@ -2973,13 +2973,13 @@ describe('ozone Adapter', function () { expect(utils.deepAccess(payload2, 'ext.ozone.pv')).to.equal(utils.deepAccess(payload, 'ext.ozone.pv')); }); it('should indicate that the whitelist was used when it contains valid data', function () { - config.setConfig({'ozone': {'oz_whitelist_adserver_keys': ['oz_ozappnexus_pb', 'oz_ozappnexus_imp_id']}}); + config.setConfig({ 'ozone': { 'oz_whitelist_adserver_keys': ['oz_ozappnexus_pb', 'oz_ozappnexus_imp_id'] } }); const request = spec.buildRequests(validBidRequests, validBidderRequest); const payload = JSON.parse(request.data); expect(payload.ext.ozone.oz_kvp_rw).to.equal(1); }); it('should indicate that the whitelist was not used when it contains no data', function () { - config.setConfig({'ozone': {'oz_whitelist_adserver_keys': []}}); + config.setConfig({ 'ozone': { 'oz_whitelist_adserver_keys': [] } }); const request = spec.buildRequests(validBidRequests, validBidderRequest); const payload = JSON.parse(request.data); expect(payload.ext.ozone.oz_kvp_rw).to.equal(0); @@ -3068,7 +3068,7 @@ describe('ozone Adapter', function () { for (let i = 0; i < keys.length; i++) { expect(allowed).to.include(keys[i]); } - expect(payload.imp[0].video.ext).to.include({'context': 'outstream'}); + expect(payload.imp[0].video.ext).to.include({ 'context': 'outstream' }); }); it('should handle standard floor config correctly', function () { config.setConfig({ @@ -3090,7 +3090,7 @@ describe('ozone Adapter', function () { } }); const localBidRequest = JSON.parse(JSON.stringify(validBidRequestsWithBannerMediaType)); - localBidRequest[0].getFloor = function(x) { return {'currency': 'USD', 'floor': 0.8} }; + localBidRequest[0].getFloor = function(x) { return { 'currency': 'USD', 'floor': 0.8 } }; const request = spec.buildRequests(localBidRequest, validBidderRequest); const payload = JSON.parse(request.data); expect(utils.deepAccess(payload, 'imp.0.floor.banner.currency')).to.equal('USD'); @@ -3156,7 +3156,7 @@ describe('ozone Adapter', function () { }); it('Single request: should use ortb auction ID & transaction ID values if set (this will be the case when publisher opts in with config)', function() { var specMock = utils.deepClone(spec); - config.setConfig({'ozone': {'singleRequest': true}}); + config.setConfig({ 'ozone': { 'singleRequest': true } }); const request = specMock.buildRequests(validBidRequestsWithAuctionIdTransactionId, validBidderRequest); expect(request).to.be.an('Object'); const payload = JSON.parse(request.data); @@ -3167,7 +3167,7 @@ describe('ozone Adapter', function () { }); it('non-Single request: should use ortb auction ID & transaction ID values if set (this will be the case when publisher opts in with config)', function() { var specMock = utils.deepClone(spec); - config.setConfig({'ozone': {'singleRequest': false}}); + config.setConfig({ 'ozone': { 'singleRequest': false } }); const request = specMock.buildRequests(validBidRequestsWithAuctionIdTransactionId, validBidderRequest); expect(request).to.be.an('Array'); const payload = JSON.parse(request[0].data); @@ -3178,7 +3178,7 @@ describe('ozone Adapter', function () { }); it('Batch request (flat array of single requests): should use ortb auction ID & transaction ID values if set (this will be the case when publisher opts in with config)', function() { var specMock = utils.deepClone(spec); - config.setConfig({'ozone': {'batchRequests': 3}}); + config.setConfig({ 'ozone': { 'batchRequests': 3 } }); const request = specMock.buildRequests(valid6BidRequestsWithAuctionIdTransactionId, validBidderRequest); expect(request).to.be.an('Array'); expect(request).to.have.lengthOf(2); @@ -3202,7 +3202,7 @@ describe('ozone Adapter', function () { model: 'iPhone 12 Pro Max', os: 'iOS', osv: '17.4', - ext: {fiftyonedegrees_deviceId: '17595-133085-133468-18092'}, + ext: { fiftyonedegrees_deviceId: '17595-133085-133468-18092' }, }, }; const request = spec.buildRequests(validBidRequests, bidderRequest); @@ -3229,7 +3229,7 @@ describe('ozone Adapter', function () { }); it('should build bid array with gdpr', function () { const validBR = JSON.parse(JSON.stringify(bidderRequestWithFullGdpr)); - validBR.gdprConsent = {'gdprApplies': 1, 'consentString': 'This is the gdpr consent string'}; + validBR.gdprConsent = { 'gdprApplies': 1, 'consentString': 'This is the gdpr consent string' }; const request = spec.buildRequests(validBidRequests, validBR); const result = spec.interpretResponse(validResponse, request); expect(result.length).to.equal(1); @@ -3244,7 +3244,7 @@ describe('ozone Adapter', function () { }); it('should build bid array with only partial gdpr', function () { var validBidderRequestWithGdpr = bidderRequestWithPartialGdpr.bidderRequest; - validBidderRequestWithGdpr.gdprConsent = {'gdprApplies': 1, 'consentString': 'This is the gdpr consent string'}; + validBidderRequestWithGdpr.gdprConsent = { 'gdprApplies': 1, 'consentString': 'This is the gdpr consent string' }; const request = spec.buildRequests(validBidRequests, validBidderRequestWithGdpr); const payload = JSON.parse(request.data); expect(payload.user.ext.consent).to.be.a('string'); @@ -3255,7 +3255,7 @@ describe('ozone Adapter', function () { expect(result).to.be.empty; }); it('should fail ok if seatbid is not an array', function () { - const result = spec.interpretResponse({'body': {'seatbid': 'nothing_here'}}, {}); + const result = spec.interpretResponse({ 'body': { 'seatbid': 'nothing_here' } }, {}); expect(result).to.be.an('array'); expect(result).to.be.empty; }); @@ -3284,13 +3284,13 @@ describe('ozone Adapter', function () { expect(result[0].ttl).to.equal(300); }); it('should handle oz_omp_floor_dollars correctly, inserting 1 as necessary', function () { - config.setConfig({'ozone': {'oz_omp_floor': 0.01}}); + config.setConfig({ 'ozone': { 'oz_omp_floor': 0.01 } }); const request = spec.buildRequests(validBidRequests, validBidderRequest); const result = spec.interpretResponse(validResponse, request); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_omp')).to.equal('1'); }); it('should handle oz_omp_floor_dollars correctly, inserting 0 as necessary', function () { - config.setConfig({'ozone': {'oz_omp_floor': 2.50}}); + config.setConfig({ 'ozone': { 'oz_omp_floor': 2.50 } }); const request = spec.buildRequests(validBidRequests, validBidderRequest); const result = spec.interpretResponse(validResponse, request); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_omp')).to.equal('0'); @@ -3303,7 +3303,7 @@ describe('ozone Adapter', function () { it('should handle ext.bidder.ozone.floor correctly, setting flr & rid as necessary', function () { const request = spec.buildRequests(validBidRequests, validBidderRequest); const vres = JSON.parse(JSON.stringify(validResponse)); - vres.body.seatbid[0].bid[0].ext.bidder.ozone = {floor: 1, ruleId: 'ZjbsYE1q'}; + vres.body.seatbid[0].bid[0].ext.bidder.ozone = { floor: 1, ruleId: 'ZjbsYE1q' }; const result = spec.interpretResponse(vres, request); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_flr')).to.equal(1); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_rid')).to.equal('ZjbsYE1q'); @@ -3311,7 +3311,7 @@ describe('ozone Adapter', function () { it('should handle ext.bidder.ozone.floor correctly, inserting 0 as necessary', function () { const request = spec.buildRequests(validBidRequests, validBidderRequest); const vres = JSON.parse(JSON.stringify(validResponse)); - vres.body.seatbid[0].bid[0].ext.bidder.ozone = {floor: 0, ruleId: 'ZjbXXE1q'}; + vres.body.seatbid[0].bid[0].ext.bidder.ozone = { floor: 0, ruleId: 'ZjbXXE1q' }; const result = spec.interpretResponse(vres, request); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_flr')).to.equal(0); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_rid')).to.equal('ZjbXXE1q'); @@ -3332,21 +3332,21 @@ describe('ozone Adapter', function () { expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_rid', null)).to.equal(null); }); it('should handle a valid whitelist, removing items not on the list & leaving others', function () { - config.setConfig({'ozone': {'oz_whitelist_adserver_keys': ['oz_appnexus_crid', 'oz_appnexus_adId']}}); + config.setConfig({ 'ozone': { 'oz_whitelist_adserver_keys': ['oz_appnexus_crid', 'oz_appnexus_adId'] } }); const request = spec.buildRequests(validBidRequests, validBidderRequest); const result = spec.interpretResponse(validResponse, request); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_adv')).to.be.undefined; expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_adId')).to.equal('2899ec066a91ff8-0-oz-0'); }); it('should ignore a whitelist if enhancedAdserverTargeting is false', function () { - config.setConfig({'ozone': {'oz_whitelist_adserver_keys': ['oz_appnexus_crid', 'oz_appnexus_imp_id'], 'enhancedAdserverTargeting': false}}); + config.setConfig({ 'ozone': { 'oz_whitelist_adserver_keys': ['oz_appnexus_crid', 'oz_appnexus_imp_id'], 'enhancedAdserverTargeting': false } }); const request = spec.buildRequests(validBidRequests, validBidderRequest); const result = spec.interpretResponse(validResponse, request); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_adv')).to.be.undefined; expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_imp_id')).to.be.undefined; }); it('should correctly handle enhancedAdserverTargeting being false', function () { - config.setConfig({'ozone': {'enhancedAdserverTargeting': false}}); + config.setConfig({ 'ozone': { 'enhancedAdserverTargeting': false } }); const request = spec.buildRequests(validBidRequests, validBidderRequest); const result = spec.interpretResponse(validResponse, request); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_adv')).to.be.undefined; @@ -3355,7 +3355,7 @@ describe('ozone Adapter', function () { it('should add flr into ads request if floor exists in the auction response', function () { const request = spec.buildRequests(validBidRequestsMulti, validBidderRequest); const validres = JSON.parse(JSON.stringify(validResponse2Bids)); - validres.body.seatbid[0].bid[0].ext.bidder.ozone = {'floor': 1}; + validres.body.seatbid[0].bid[0].ext.bidder.ozone = { 'floor': 1 }; const result = spec.interpretResponse(validres, request); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_flr')).to.equal(1); expect(utils.deepAccess(result[1].adserverTargeting, 'oz_appnexus_flr', '')).to.equal(''); @@ -3363,7 +3363,7 @@ describe('ozone Adapter', function () { it('should add rid into ads request if ruleId exists in the auction response', function () { const request = spec.buildRequests(validBidRequestsMulti, validBidderRequest); const validres = JSON.parse(JSON.stringify(validResponse2Bids)); - validres.body.seatbid[0].bid[0].ext.bidder.ozone = {'ruleId': 123}; + validres.body.seatbid[0].bid[0].ext.bidder.ozone = { 'ruleId': 123 }; const result = spec.interpretResponse(validres, request); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_appnexus_rid')).to.equal(123); expect(utils.deepAccess(result[1].adserverTargeting, 'oz_appnexus_rid', '')).to.equal(''); @@ -3441,11 +3441,11 @@ describe('ozone Adapter', function () { const validres = JSON.parse(JSON.stringify(validResponse2Bids)); validres.body.seatbid.push(JSON.parse(JSON.stringify(validres.body.seatbid[0]))); validres.body.seatbid[1].seat = 'marktest'; - validres.body.seatbid[1].bid[0].ext.bidder.prebid = {label: ['b1', 'b2', 'b3']}; + validres.body.seatbid[1].bid[0].ext.bidder.prebid = { label: ['b1', 'b2', 'b3'] }; validres.body.seatbid[1].bid[0].price = 10; validres.body.seatbid[1].bid[1].price = 0; - validres.body.seatbid[0].bid[0].ext.bidder.prebid = {label: ['bid1label1', 'bid1label2', 'bid1label3']}; - validres.body.seatbid[0].bid[1].ext.bidder.prebid = {label: ['bid2label']}; + validres.body.seatbid[0].bid[0].ext.bidder.prebid = { label: ['bid1label1', 'bid1label2', 'bid1label3'] }; + validres.body.seatbid[0].bid[1].ext.bidder.prebid = { label: ['bid2label'] }; const result = spec.interpretResponse(validres, request); expect(result.length).to.equal(4); expect(utils.deepAccess(result[0].adserverTargeting, 'oz_winner')).to.equal('marktest'); @@ -3458,7 +3458,7 @@ describe('ozone Adapter', function () { expect(utils.deepAccess(result[3].adserverTargeting, 'oz_labels')).to.equal('bid2label'); }); it('should not add labels in the adserver request if they are present in the auction response when config contains ozone.enhancedAdserverTargeting', function () { - config.setConfig({'ozone': {'enhancedAdserverTargeting': false}}); + config.setConfig({ 'ozone': { 'enhancedAdserverTargeting': false } }); const request = spec.buildRequests(validBidRequestsMulti, validBidderRequest); const validres = JSON.parse(JSON.stringify(validResponse2Bids)); validres.body.seatbid.push(JSON.parse(JSON.stringify(validres.body.seatbid[0]))); @@ -3492,7 +3492,7 @@ describe('ozone Adapter', function () { }); it('should append the various values if they exist', function() { spec.buildRequests(validBidRequests, validBidderRequest); - const result = spec.getUserSyncs({iframeEnabled: true}, 'good server response', gdpr1); + const result = spec.getUserSyncs({ iframeEnabled: true }, 'good server response', gdpr1); expect(result).to.be.an('array'); expect(result[0].url).to.include('publisherId=9876abcd12-3'); expect(result[0].url).to.include('siteId=1234567890'); @@ -3501,51 +3501,51 @@ describe('ozone Adapter', function () { }); it('should append ccpa (usp data)', function() { spec.buildRequests(validBidRequests, validBidderRequest); - const result = spec.getUserSyncs({iframeEnabled: true}, 'good server response', gdpr1, '1YYN'); + const result = spec.getUserSyncs({ iframeEnabled: true }, 'good server response', gdpr1, '1YYN'); expect(result).to.be.an('array'); expect(result[0].url).to.include('usp_consent=1YYN'); }); it('should use "" if no usp is sent to cookieSync', function() { spec.buildRequests(validBidRequests, validBidderRequest); - const result = spec.getUserSyncs({iframeEnabled: true}, 'good server response', gdpr1); + const result = spec.getUserSyncs({ iframeEnabled: true }, 'good server response', gdpr1); expect(result).to.be.an('array'); expect(result[0].url).to.include('usp_consent=&'); }); it('should add gpp if its present', function () { - const result = spec.getUserSyncs({iframeEnabled: true}, 'good server response', gdpr1, '1---', { gppString: 'gppStringHere', applicableSections: [7, 8, 9] }); + const result = spec.getUserSyncs({ iframeEnabled: true }, 'good server response', gdpr1, '1---', { gppString: 'gppStringHere', applicableSections: [7, 8, 9] }); expect(result[0].url).to.include('gpp=gppStringHere&gpp_sid=7,8,9'); }); }); describe('video object utils', function () { it('should find width & height from video object', function () { - const obj = {'playerSize': [640, 480], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const obj = { 'playerSize': [640, 480], 'mimes': ['video/mp4'], 'context': 'outstream' }; const result = getWidthAndHeightFromVideoObject(obj); expect(result.w).to.equal(640); expect(result.h).to.equal(480); }); it('should find null from bad video object', function () { - const obj = {'playerSize': [], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const obj = { 'playerSize': [], 'mimes': ['video/mp4'], 'context': 'outstream' }; const result = getWidthAndHeightFromVideoObject(obj); expect(result).to.be.null; }); it('should find null from bad video object2', function () { - const obj = {'mimes': ['video/mp4'], 'context': 'outstream'}; + const obj = { 'mimes': ['video/mp4'], 'context': 'outstream' }; const result = getWidthAndHeightFromVideoObject(obj); expect(result).to.be.null; }); it('should find null from bad video object3', function () { - const obj = {'playerSize': 'should be an array', 'mimes': ['video/mp4'], 'context': 'outstream'}; + const obj = { 'playerSize': 'should be an array', 'mimes': ['video/mp4'], 'context': 'outstream' }; const result = getWidthAndHeightFromVideoObject(obj); expect(result).to.be.null; }); it('should find that player size is nested', function () { - const obj = {'playerSize': [[640, 480]], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const obj = { 'playerSize': [[640, 480]], 'mimes': ['video/mp4'], 'context': 'outstream' }; const result = getWidthAndHeightFromVideoObject(obj); expect(result.w).to.equal(640); expect(result.h).to.equal(480); }); it('should fail if player size is 2 x nested', function () { - const obj = {'playerSize': [[[640, 480]]], 'mimes': ['video/mp4'], 'context': 'outstream'}; + const obj = { 'playerSize': [[[640, 480]]], 'mimes': ['video/mp4'], 'context': 'outstream' }; const result = getWidthAndHeightFromVideoObject(obj); expect(result).to.be.null; }); @@ -3571,12 +3571,12 @@ describe('ozone Adapter', function () { config.resetConfig() }) it('should return true if oz_request is false', function() { - config.setConfig({'ozone': {'oz_request': false}}); + config.setConfig({ 'ozone': { 'oz_request': false } }); const result = spec.blockTheRequest(); expect(result).to.be.true; }); it('should return false if oz_request is true', function() { - config.setConfig({'ozone': {'oz_request': true}}); + config.setConfig({ 'ozone': { 'oz_request': true } }); const result = spec.blockTheRequest(); expect(result).to.be.false; }); @@ -3653,7 +3653,7 @@ describe('ozone Adapter', function () { }); it('should correctly add video defaults if page config videoParams is defined, also check skip in the parent', function () { var specMock = utils.deepClone(spec); - config.setConfig({'ozone': {videoParams: {outstream: 3, instream: 1}}}); + config.setConfig({ 'ozone': { videoParams: { outstream: 3, instream: 1 } } }); const mediaTypes = { playerSize: [640, 480], mimes: ['video/mp4'], @@ -3689,19 +3689,19 @@ describe('ozone Adapter', function () { }); describe('setBidMediaTypeIfNotExist', function() { it('should leave the bid object alone if it already contains mediaType', function() { - const thisBid = {mediaType: 'marktest'}; + const thisBid = { mediaType: 'marktest' }; spec.setBidMediaTypeIfNotExist(thisBid, 'replacement'); expect(thisBid.mediaType).to.equal('marktest'); }); it('should change the bid object if it doesnt already contain mediaType', function() { - const thisBid = {someKey: 'someValue'}; + const thisBid = { someKey: 'someValue' }; spec.setBidMediaTypeIfNotExist(thisBid, 'replacement'); expect(thisBid.mediaType).to.equal('replacement'); }); }); describe('getLoggableBidObject', function() { it('should return an object without a "renderer" element', function () { - const obj = {'renderer': {}, 'somevalue': '', 'h': 100}; + const obj = { 'renderer': {}, 'somevalue': '', 'h': 100 }; const ret = spec.getLoggableBidObject(obj); expect(ret).to.not.have.own.property('renderer'); expect(ret.h).to.equal(100); @@ -3709,7 +3709,8 @@ describe('ozone Adapter', function () { }); describe('getUserIdFromEids', function() { it('should iterate over userIdAsEids when it is an object', function () { - let bid = { userIdAsEids: + let bid = { + userIdAsEids: [ { source: 'pubcid.org', @@ -3766,7 +3767,7 @@ describe('ozone Adapter', function () { expect(Object.keys(response).length).to.equal(0); }); it('find pubcid in the old location when there are eids and when there arent', function () { - let bid = {crumbs: {pubcid: 'some-random-id-value' }}; + let bid = { crumbs: { pubcid: 'some-random-id-value' } }; Object.defineProperty(bid, 'userIdAsEids', { value: undefined, writable: false, @@ -3886,14 +3887,14 @@ describe('ozone Adapter', function () { } } `); - const parsed = spec.pruneToExtPaths(jsonObj, {maxTestDepth: 2}); + const parsed = spec.pruneToExtPaths(jsonObj, { maxTestDepth: 2 }); expect(parsed).to.have.all.keys('site', 'user', 'regs', 'ext'); expect(Object.keys(parsed.site).length).to.equal(1); expect(parsed.site).to.have.all.keys('ext'); }); it('should prune a json object according to my params even when its empty', function () { const jsonObj = {}; - const parsed = spec.pruneToExtPaths(jsonObj, {maxTestDepth: 2}); + const parsed = spec.pruneToExtPaths(jsonObj, { maxTestDepth: 2 }); expect(Object.keys(parsed).length).to.equal(0); }); it('should prune a json object using Infinity as max depth', function () { @@ -4004,7 +4005,7 @@ describe('ozone Adapter', function () { } } `); - const parsed = spec.pruneToExtPaths(jsonObj, {maxTestDepth: Infinity}); + const parsed = spec.pruneToExtPaths(jsonObj, { maxTestDepth: Infinity }); expect(parsed.site.content.data[0].ext.segtax).to.equal('7'); }); it('should prune another json object', function () { @@ -4030,7 +4031,7 @@ describe('ozone Adapter', function () { } } }`); - const parsed = spec.pruneToExtPaths(jsonObj, {maxTestDepth: 2}); + const parsed = spec.pruneToExtPaths(jsonObj, { maxTestDepth: 2 }); expect(Object.keys(parsed.user).length).to.equal(1); expect(Object.keys(parsed)).to.have.members(['site', 'user']); expect(Object.keys(parsed.user)).to.have.members(['ext']); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 025ac9592b2..620a3d4fddf 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1,21 +1,21 @@ -import {expect} from 'chai'; +import { expect } from 'chai'; import { PrebidServer as Adapter, resetSyncedStatus, validateConfig, s2sDefaultConfig } from 'modules/prebidServerBidAdapter/index.js'; -import adapterManager, {PBS_ADAPTER_NAME} from 'src/adapterManager.js'; +import adapterManager, { PBS_ADAPTER_NAME } from 'src/adapterManager.js'; import * as utils from 'src/utils.js'; -import {deepAccess, deepClone, getWinDimensions, mergeDeep} from 'src/utils.js'; -import {ajax} from 'src/ajax.js'; -import {config} from 'src/config.js'; +import { deepAccess, deepClone, getWinDimensions, mergeDeep } from 'src/utils.js'; +import { ajax } from 'src/ajax.js'; +import { config } from 'src/config.js'; import * as events from 'src/events.js'; import { EVENTS, DEBUG_MODE } from 'src/constants.js'; -import {server} from 'test/mocks/xhr.js'; +import { server } from 'test/mocks/xhr.js'; import 'modules/appnexusBidAdapter.js'; // appnexus alias test import 'modules/rubiconBidAdapter.js'; // rubicon alias test -import {requestBids} from 'src/prebid.js'; +import { requestBids } from 'src/prebid.js'; import 'modules/currency.js'; // adServerCurrency test import 'modules/userId/index.js'; import 'modules/multibid/index.js'; @@ -25,21 +25,21 @@ import 'modules/consentManagementUsp.js'; import 'modules/consentManagementGpp.js'; import * as redactor from 'src/activities/redactor.js'; import * as activityRules from 'src/activities/rules.js'; -import {hook} from '../../../src/hook.js'; -import {decorateAdUnitsWithNativeParams} from '../../../src/native.js'; -import {auctionManager} from '../../../src/auctionManager.js'; -import {stubAuctionIndex} from '../../helpers/indexStub.js'; -import {registerBidder} from 'src/adapters/bidderFactory.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; -import {addFPDToBidderRequest} from '../../helpers/fpd.js'; -import {ACTIVITY_TRANSMIT_UFPD} from '../../../src/activities/activities.js'; -import {MODULE_TYPE_PREBID} from '../../../src/activities/modules.js'; +import { hook } from '../../../src/hook.js'; +import { decorateAdUnitsWithNativeParams } from '../../../src/native.js'; +import { auctionManager } from '../../../src/auctionManager.js'; +import { stubAuctionIndex } from '../../helpers/indexStub.js'; +import { registerBidder } from 'src/adapters/bidderFactory.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; +import { addFPDToBidderRequest } from '../../helpers/fpd.js'; +import { ACTIVITY_TRANSMIT_UFPD } from '../../../src/activities/activities.js'; +import { MODULE_TYPE_PREBID } from '../../../src/activities/modules.js'; import { consolidateEids, extractEids, getPBSBidderConfig } from '../../../modules/prebidServerBidAdapter/bidderConfig.js'; -import {markWinningBid} from '../../../src/adRendering.js'; +import { markWinningBid } from '../../../src/adRendering.js'; let CONFIG = { accountId: '1', @@ -615,7 +615,7 @@ describe('S2S Adapter', function () { beforeEach(function () { config.resetConfig(); - config.setConfig({floors: {enabled: false}}); + config.setConfig({ floors: { enabled: false } }); adapter = new Adapter(); BID_REQUESTS = [ { @@ -703,7 +703,7 @@ describe('S2S Adapter', function () { const s2sConfig = { ...CONFIG, }; - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); s2sReq = { ...REQUEST, s2sConfig @@ -745,10 +745,10 @@ describe('S2S Adapter', function () { beforeEach(() => { s2sReq = { ...REQUEST, - ortb2Fragments: {global: {}}, - ad_units: REQUEST.ad_units.map(au => ({...au, ortb2Imp: {ext: {tid: 'mock-tid'}}})), + ortb2Fragments: { global: {} }, + ad_units: REQUEST.ad_units.map(au => ({ ...au, ortb2Imp: { ext: { tid: 'mock-tid' } } })), }; - BID_REQUESTS[0].bids[0].ortb2Imp = {ext: {tid: 'mock-tid'}}; + BID_REQUESTS[0].bids[0].ortb2Imp = { ext: { tid: 'mock-tid' } }; }); function makeRequest() { @@ -765,7 +765,7 @@ describe('S2S Adapter', function () { }); it('should be set to auction ID otherwise', () => { - config.setConfig({s2sConfig: CONFIG, enableTIDs: true}); + config.setConfig({ s2sConfig: CONFIG, enableTIDs: true }); const req = makeRequest(); expect(req.source.tid).to.eql(BID_REQUESTS[0].auctionId); expect(req.imp[0].ext.tid).to.eql('mock-tid'); @@ -788,7 +788,7 @@ describe('S2S Adapter', function () { } return false; }); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); const ajax = sinon.stub(); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); sinon.assert.calledWith(ajax, sinon.match.any, sinon.match.any, sinon.match.any, sinon.match({ @@ -799,8 +799,8 @@ describe('S2S Adapter', function () { }) it('should set tmaxmax correctly when publisher has specified it', () => { - const cfg = {...CONFIG}; - config.setConfig({s2sConfig: cfg}) + const cfg = { ...CONFIG }; + config.setConfig({ s2sConfig: cfg }) // publisher has specified a tmaxmax in their setup const ortb2Fragments = { @@ -810,7 +810,7 @@ describe('S2S Adapter', function () { } } }; - const s2sCfg = {...REQUEST, cfg} + const s2sCfg = { ...REQUEST, cfg } const payloadWithFragments = { ...s2sCfg, ortb2Fragments }; adapter.callBids(payloadWithFragments, BID_REQUESTS, addBidResponse, done, ajax); @@ -820,13 +820,13 @@ describe('S2S Adapter', function () { }); it('should set tmaxmax correctly when publisher has not specified it', () => { - const cfg = {...CONFIG}; - config.setConfig({s2sConfig: cfg}) + const cfg = { ...CONFIG }; + config.setConfig({ s2sConfig: cfg }) // publisher has not specified a tmaxmax in their setup - so we should be // falling back to requestBidsTimeout const ortb2Fragments = {}; - const s2sCfg = {...REQUEST, cfg}; + const s2sCfg = { ...REQUEST, cfg }; const requestBidsTimeout = 808; const payloadWithFragments = { ...s2sCfg, ortb2Fragments, requestBidsTimeout }; @@ -842,19 +842,19 @@ describe('S2S Adapter', function () { let cfg; beforeEach(() => { - cfg = {accountId: '1', endpoint: 'mock-endpoint', maxTimeout}; - config.setConfig({s2sConfig: cfg}); + cfg = { accountId: '1', endpoint: 'mock-endpoint', maxTimeout }; + config.setConfig({ s2sConfig: cfg }); maxTimeout = maxTimeout ?? s2sDefaultConfig.maxTimeout }); it('should cap tmax to maxTimeout', () => { - adapter.callBids({...REQUEST, requestBidsTimeout: maxTimeout * 2, s2sConfig: cfg}, BID_REQUESTS, addBidResponse, done, ajax); + adapter.callBids({ ...REQUEST, requestBidsTimeout: maxTimeout * 2, s2sConfig: cfg }, BID_REQUESTS, addBidResponse, done, ajax); const req = JSON.parse(server.requests[0].requestBody); expect(req.tmax).to.eql(maxTimeout); }); it('should be set to 0.75 * requestTimeout, if lower than maxTimeout', () => { - adapter.callBids({...REQUEST, requestBidsTimeout: maxTimeout / 2}, BID_REQUESTS, addBidResponse, done, ajax); + adapter.callBids({ ...REQUEST, requestBidsTimeout: maxTimeout / 2 }, BID_REQUESTS, addBidResponse, done, ajax); const req = JSON.parse(server.requests[0].requestBody); expect(req.tmax).to.eql(Math.floor(maxTimeout / 2 * 0.75)); }) @@ -931,16 +931,16 @@ describe('S2S Adapter', function () { }); it('filters ad units without bidders when filterBidderlessCalls is true', function () { - const cfg = {...CONFIG, filterBidderlessCalls: true}; - config.setConfig({s2sConfig: cfg}); + const cfg = { ...CONFIG, filterBidderlessCalls: true }; + config.setConfig({ s2sConfig: cfg }); const badReq = utils.deepClone(REQUEST); badReq.s2sConfig = cfg; - badReq.ad_units = [{...REQUEST.ad_units[0], bids: [{bidder: null}]}]; + badReq.ad_units = [{ ...REQUEST.ad_units[0], bids: [{ bidder: null }] }]; const badBidderRequest = utils.deepClone(BID_REQUESTS); badBidderRequest[0].bidderCode = null; - badBidderRequest[0].bids = [{...badBidderRequest[0].bids[0], bidder: null}]; + badBidderRequest[0].bids = [{ ...badBidderRequest[0].bids[0], bidder: null }]; adapter.callBids(badReq, badBidderRequest, addBidResponse, done, ajax); @@ -994,8 +994,8 @@ describe('S2S Adapter', function () { }); it('should gzip payload when enabled and supported', function(done) { - const s2sCfg = Object.assign({}, CONFIG, {endpointCompression: true}); - config.setConfig({s2sConfig: s2sCfg}); + const s2sCfg = Object.assign({}, CONFIG, { endpointCompression: true }); + config.setConfig({ s2sConfig: s2sCfg }); const req = utils.deepClone(REQUEST); req.s2sConfig = s2sCfg; gzipSupportStub.returns(true); @@ -1013,8 +1013,8 @@ describe('S2S Adapter', function () { }); it('should not gzip when debug mode is enabled', function(done) { - const s2sCfg = Object.assign({}, CONFIG, {endpointCompression: true}); - config.setConfig({s2sConfig: s2sCfg}); + const s2sCfg = Object.assign({}, CONFIG, { endpointCompression: true }); + config.setConfig({ s2sConfig: s2sCfg }); const req = utils.deepClone(REQUEST); req.s2sConfig = s2sCfg; gzipSupportStub.returns(true); @@ -1034,11 +1034,11 @@ describe('S2S Adapter', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); - function mockTCF({applies = true, hasP1Consent = true} = {}) { + function mockTCF({ applies = true, hasP1Consent = true } = {}) { return { consentString: 'mockConsent', gdprApplies: applies, - vendorData: {purpose: {consents: {1: hasP1Consent}}}, + vendorData: { purpose: { consents: { 1: hasP1Consent } } }, } } @@ -1048,7 +1048,7 @@ describe('S2S Adapter', function () { }); it('adds gdpr consent information to ortb2 request depending on presence of module', async function () { - const consentConfig = {consentManagement: {cmpApi: 'iab'}, s2sConfig: CONFIG}; + const consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: CONFIG }; config.setConfig(consentConfig); const gdprBidRequest = utils.deepClone(BID_REQUESTS); @@ -1061,7 +1061,7 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.consent).is.equal('mockConsent'); config.resetConfig(); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(await addFpdEnrichmentsToS2SRequest(REQUEST, BID_REQUESTS), BID_REQUESTS, addBidResponse, done, ajax); requestBid = JSON.parse(server.requests[1].requestBody); @@ -1071,7 +1071,7 @@ describe('S2S Adapter', function () { }); it('adds additional consent information to ortb2 request depending on presence of module', async function () { - const consentConfig = {consentManagement: {cmpApi: 'iab'}, s2sConfig: CONFIG}; + const consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: CONFIG }; config.setConfig(consentConfig); const gdprBidRequest = utils.deepClone(BID_REQUESTS); @@ -1087,7 +1087,7 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.ConsentedProvidersSettings.consented_providers).is.equal('superduperconsent'); config.resetConfig(); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); requestBid = JSON.parse(server.requests[1].requestBody); @@ -1103,7 +1103,7 @@ describe('S2S Adapter', function () { }); it('is added to ortb2 request when in FPD', async function () { - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); const uspBidRequest = utils.deepClone(BID_REQUESTS); uspBidRequest[0].uspConsent = '1NYN'; @@ -1114,7 +1114,7 @@ describe('S2S Adapter', function () { expect(requestBid.regs.ext.us_privacy).is.equal('1NYN'); config.resetConfig(); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(await addFpdEnrichmentsToS2SRequest(REQUEST, BID_REQUESTS), BID_REQUESTS, addBidResponse, done, ajax); requestBid = JSON.parse(server.requests[1].requestBody); @@ -1129,7 +1129,7 @@ describe('S2S Adapter', function () { }); it('is added to ortb2 request when in bidRequest', async function () { - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); const consentBidRequest = utils.deepClone(BID_REQUESTS); consentBidRequest[0].uspConsent = '1NYN'; @@ -1143,7 +1143,7 @@ describe('S2S Adapter', function () { expect(requestBid.user.ext.consent).is.equal('mockConsent'); config.resetConfig(); - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); requestBid = JSON.parse(server.requests[1].requestBody); @@ -1184,8 +1184,8 @@ describe('S2S Adapter', function () { ...REQUEST, ortb2Fragments: { global: { - device: {ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC'}, - app: {bundle: 'com.test.app'}, + device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, + app: { bundle: 'com.test.app' }, } } }, BID_REQUESTS) @@ -1198,7 +1198,7 @@ describe('S2S Adapter', function () { }) sinon.assert.match(requestBid.app, { bundle: 'com.test.app', - publisher: {'id': '1'} + publisher: { 'id': '1' } }); }); @@ -1216,8 +1216,8 @@ describe('S2S Adapter', function () { ...REQUEST, ortb2Fragments: { global: { - device: {ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC'}, - app: {bundle: 'com.test.app'}, + device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, + app: { bundle: 'com.test.app' }, } } }, BID_REQUESTS) @@ -1230,7 +1230,7 @@ describe('S2S Adapter', function () { }) sinon.assert.match(requestBid.app, { bundle: 'com.test.app', - publisher: {'id': '1'} + publisher: { 'id': '1' } }); }); @@ -1368,16 +1368,16 @@ describe('S2S Adapter', function () { code: 'au1', transactionId: 't1', mediaTypes: { - banner: {sizes: [1, 1]} + banner: { sizes: [1, 1] } }, - bids: [{bidder: 'b1', bid_id: 1}] + bids: [{ bidder: 'b1', bid_id: 1 }] }, { code: 'au2', transactionId: 't2', - bids: [{bidder: 'b2', bid_id: 2}], + bids: [{ bidder: 'b2', bid_id: 2 }], mediaTypes: { - banner: {sizes: [1, 1]} + banner: { sizes: [1, 1] } } } ]; @@ -1452,12 +1452,12 @@ describe('S2S Adapter', function () { code: 'au1', transactionId: 't1', mediaTypes: { - banner: {sizes: [1, 1]} + banner: { sizes: [1, 1] } }, bids: [ - {bidder: 'b2', bid_id: 2}, - {bidder: 'b3', bid_id: 3}, - {bidder: 'b1', bid_id: 1}, + { bidder: 'b2', bid_id: 2 }, + { bidder: 'b3', bid_id: 3 }, + { bidder: 'b1', bid_id: 1 }, ] } ] @@ -1485,13 +1485,13 @@ describe('S2S Adapter', function () { }, 'mediaType level floors': { target: 'imp.0.banner.ext', - floorFilter: ({mediaType, size}) => size === '*' && mediaType !== '*' + floorFilter: ({ mediaType, size }) => size === '*' && mediaType !== '*' }, 'format level floors': { target: 'imp.0.banner.format.0.ext', - floorFilter: ({size}) => size !== '*' + floorFilter: ({ size }) => size !== '*' } - }).forEach(([t, {target, floorFilter}]) => { + }).forEach(([t, { target, floorFilter }]) => { describe(t, () => { beforeEach(() => { if (floorFilter != null) { @@ -1532,7 +1532,7 @@ describe('S2S Adapter', function () { throw new Error(); } } - }).forEach(([t, {expectDesc, expectedFloor, expectedCur, conversionFn}]) => { + }).forEach(([t, { expectDesc, expectedFloor, expectedCur, conversionFn }]) => { describe(`and currency conversion ${t}`, () => { let mockConvertCurrency; const origConvertCurrency = getGlobal().convertCurrency; @@ -1629,7 +1629,7 @@ describe('S2S Adapter', function () { }; config.setConfig(_config); - adapter.callBids({...REQUEST, s2sConfig: Object.assign({}, CONFIG, s2sDefaultConfig)}, BID_REQUESTS, addBidResponse, done, ajax); + adapter.callBids({ ...REQUEST, s2sConfig: Object.assign({}, CONFIG, s2sDefaultConfig) }, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(server.requests[0].requestBody); const ortbReq = JSON.parse(requestBid.imp[0].native.request); expect(ortbReq).to.deep.equal({ @@ -1667,27 +1667,27 @@ describe('S2S Adapter', function () { ...CONFIG, ortbNative: { eventtrackers: [ - {event: 1, methods: [1, 2]} + { event: 1, methods: [1, 2] } ] } } config.setConfig({ s2sConfig: cfg }); - adapter.callBids({...REQUEST, s2sConfig: cfg}, BID_REQUESTS, addBidResponse, done, ajax); + adapter.callBids({ ...REQUEST, s2sConfig: cfg }, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(server.requests[0].requestBody); const ortbReq = JSON.parse(requestBid.imp[0].native.request); expect(ortbReq).to.eql({ ...ORTB_NATIVE_REQ, eventtrackers: [ - {event: 1, methods: [1, 2]} + { event: 1, methods: [1, 2] } ] }) }) it('should not include ext.aspectratios if adunit\'s aspect_ratios do not define radio_width and ratio_height', () => { const req = deepClone(REQUEST); - req.ad_units[0].mediaTypes.native.icon.aspect_ratios[0] = {'min_width': 1, 'min_height': 2}; + req.ad_units[0].mediaTypes.native.icon.aspect_ratios[0] = { 'min_width': 1, 'min_height': 2 }; prepRequest(req); adapter.callBids(req, BID_REQUESTS, addBidResponse, done, ajax); const nativeReq = JSON.parse(JSON.parse(server.requests[0].requestBody).imp[0].native.request); @@ -1755,7 +1755,7 @@ describe('S2S Adapter', function () { ...REQUEST, ortb2Fragments: { global: { - app: {bundle: 'com.test.app'}, + app: { bundle: 'com.test.app' }, site: { publisher: { id: '1234', @@ -1786,7 +1786,7 @@ describe('S2S Adapter', function () { const request = utils.deepClone(REQUEST); request.ad_units[0].bids = [aliasBidder]; - adapter.callBids(request, [{...BID_REQUESTS[0], bidderCode: 'beintoo'}], addBidResponse, done, ajax); + adapter.callBids(request, [{ ...BID_REQUESTS[0], bidderCode: 'beintoo' }], addBidResponse, done, ajax); const requestBid = JSON.parse(server.requests[0].requestBody); expect(requestBid.ext).to.haveOwnProperty('prebid'); @@ -1821,7 +1821,7 @@ describe('S2S Adapter', function () { request.ad_units[0].bids = [aliasBidder]; request.s2sConfig = adjustedConfig; - adapter.callBids(request, [{...BID_REQUESTS[0], bidderCode: aliasBidder.bidder}], addBidResponse, done, ajax); + adapter.callBids(request, [{ ...BID_REQUESTS[0], bidderCode: aliasBidder.bidder }], addBidResponse, done, ajax); const requestBid = JSON.parse(server.requests[0].requestBody); expect(requestBid.ext.prebid.aliases).to.deep.equal({ bidderD: 'mockBidder' }); @@ -1842,7 +1842,7 @@ describe('S2S Adapter', function () { // TODO: stub this getGlobal().aliasBidder('appnexus', alias); - adapter.callBids(request, [{...BID_REQUESTS[0], bidderCode: 'foobar'}], addBidResponse, done, ajax); + adapter.callBids(request, [{ ...BID_REQUESTS[0], bidderCode: 'foobar' }], addBidResponse, done, ajax); const requestBid = JSON.parse(server.requests[0].requestBody); expect(requestBid.ext).to.haveOwnProperty('prebid'); @@ -1881,7 +1881,7 @@ describe('S2S Adapter', function () { const request = utils.deepClone(REQUEST); request.ad_units[0].bids = [aliasBidder]; - adapter.callBids(request, [{...BID_REQUESTS[0], bidderCode: aliasBidder.bidder}], addBidResponse, done, ajax); + adapter.callBids(request, [{ ...BID_REQUESTS[0], bidderCode: aliasBidder.bidder }], addBidResponse, done, ajax); const requestBid = JSON.parse(server.requests[0].requestBody); @@ -1918,7 +1918,7 @@ describe('S2S Adapter', function () { // TODO: stub this getGlobal().aliasBidder('appnexus', alias, { skipPbsAliasing: true }); - adapter.callBids(request, [{...BID_REQUESTS[0], bidderCode: aliasBidder.bidder}], addBidResponse, done, ajax); + adapter.callBids(request, [{ ...BID_REQUESTS[0], bidderCode: aliasBidder.bidder }], addBidResponse, done, ajax); const requestBid = JSON.parse(server.requests[0].requestBody); @@ -2085,7 +2085,7 @@ describe('S2S Adapter', function () { }); it('when gdprApplies is false', () => { - bidderReqs[0].gdprConsent = mockTCF({applies: false}); + bidderReqs[0].gdprConsent = mockTCF({ applies: false }); const req = callCookieSync(); expect(req.gdpr).is.equal(0); expect(req.gdpr_consent).is.undefined; @@ -2160,7 +2160,7 @@ describe('S2S Adapter', function () { site: { domain: 'nytimes.com', page: 'http://www.nytimes.com', - publisher: {id: '2'} + publisher: { id: '2' } }, device, } @@ -2209,7 +2209,7 @@ describe('S2S Adapter', function () { ...CONFIG, bidders: ['appnexus', 'rubicon'] } - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); req = { ...REQUEST, s2sConfig, @@ -2217,7 +2217,7 @@ describe('S2S Adapter', function () { global: { user: { ext: { - eids: [{source: 'idA', id: 1}, {source: 'idB', id: 2}] + eids: [{ source: 'idA', id: 1 }, { source: 'idB', id: 2 }] } } }, @@ -2225,7 +2225,7 @@ describe('S2S Adapter', function () { appnexus: { user: { ext: { - eids: [{source: 'idC', id: 3}] + eids: [{ source: 'idC', id: 3 }] } } } @@ -2237,9 +2237,9 @@ describe('S2S Adapter', function () { adapter.callBids(req, BID_REQUESTS, addBidResponse, done, ajax); const payload = JSON.parse(server.requests[0].requestBody); expect(payload.user.ext.eids).to.eql([ - {source: 'idA', id: 1}, - {source: 'idB', id: 2}, - {source: 'idC', id: 3} + { source: 'idA', id: 1 }, + { source: 'idB', id: 2 }, + { source: 'idC', id: 3 } ]); expect(payload.ext.prebid.data.eidpermissions).to.eql([{ bidders: ['appnexus'], @@ -2250,7 +2250,7 @@ describe('S2S Adapter', function () { it('should not set eidpermissions for unrequested bidders', () => { req.ortb2Fragments.bidder.unknown = { user: { - eids: [{source: 'idC', id: 3}, {source: 'idD', id: 4}] + eids: [{ source: 'idC', id: 3 }, { source: 'idD', id: 4 }] } } adapter.callBids(req, BID_REQUESTS, addBidResponse, done, ajax); @@ -2276,15 +2276,15 @@ describe('S2S Adapter', function () { req.ortb2Fragments.bidder.rubicon = { user: { ext: { - eids: [{source: 'idC', id: 4}] + eids: [{ source: 'idC', id: 4 }] } } } adapter.callBids(req, BID_REQUESTS, addBidResponse, done, ajax); const payload = JSON.parse(server.requests[0].requestBody); const globalEids = [ - {source: 'idA', id: 1}, - {source: 'idB', id: 2}, + { source: 'idA', id: 1 }, + { source: 'idB', id: 2 }, ] expect(payload.user.ext.eids).to.eql(globalEids); expect(payload.ext.prebid?.data?.eidpermissions).to.not.exist; @@ -2293,7 +2293,7 @@ describe('S2S Adapter', function () { bidders: ['appnexus'], config: { ortb2: { - user: {ext: {eids: globalEids.concat([{source: 'idC', id: 3}])}} + user: { ext: { eids: globalEids.concat([{ source: 'idC', id: 3 }]) } } } } }, @@ -2301,7 +2301,7 @@ describe('S2S Adapter', function () { bidders: ['rubicon'], config: { ortb2: { - user: {ext: {eids: globalEids.concat([{source: 'idC', id: 4}])}} + user: { ext: { eids: globalEids.concat([{ source: 'idC', id: 4 }]) } } } } } @@ -2656,22 +2656,22 @@ describe('S2S Adapter', function () { Object.entries({ 'set': {}, - 'override': {source: {ext: {schain: 'pub-provided'}}} + 'override': { source: { ext: { schain: 'pub-provided' } } } }).forEach(([t, fpd]) => { it(`should not ${t} source.ext.schain`, () => { const bidderReqs = [ - {...deepClone(BID_REQUESTS[0]), bidderCode: 'A'}, - {...deepClone(BID_REQUESTS[0]), bidderCode: 'B'}, - {...deepClone(BID_REQUESTS[0]), bidderCode: 'C'} + { ...deepClone(BID_REQUESTS[0]), bidderCode: 'A' }, + { ...deepClone(BID_REQUESTS[0]), bidderCode: 'B' }, + { ...deepClone(BID_REQUESTS[0]), bidderCode: 'C' } ]; - const chain1 = {chain: 1}; - const chain2 = {chain: 2}; + const chain1 = { chain: 1 }; + const chain2 = { chain: 2 }; bidderReqs[0].bids[0].schain = chain1; bidderReqs[1].bids[0].schain = chain2; bidderReqs[2].bids[0].schain = chain2; - adapter.callBids({...REQUEST, ortb2Fragments: {global: fpd}}, bidderReqs, addBidResponse, done, ajax); + adapter.callBids({ ...REQUEST, ortb2Fragments: { global: fpd } }, bidderReqs, addBidResponse, done, ajax); const req = JSON.parse(server.requests[0].requestBody); expect(req.source?.ext?.schain).to.eql(fpd?.source?.ext?.schain); }) @@ -2758,7 +2758,7 @@ describe('S2S Adapter', function () { }; const site = { - content: {userrating: 4}, + content: { userrating: 4 }, ext: { data: { pageType: 'article', @@ -2768,7 +2768,7 @@ describe('S2S Adapter', function () { }; const user = { yob: '1984', - geo: {country: 'ca'}, + geo: { country: 'ca' }, ext: { data: { registered: true, @@ -2785,7 +2785,7 @@ describe('S2S Adapter', function () { config: { ortb2: { site: { - content: {userrating: 4}, + content: { userrating: 4 }, ext: { data: { pageType: 'article', @@ -2795,7 +2795,7 @@ describe('S2S Adapter', function () { }, user: { yob: '1984', - geo: {country: 'ca'}, + geo: { country: 'ca' }, ext: { data: { registered: true, @@ -2818,8 +2818,8 @@ describe('S2S Adapter', function () { }, commonSite); const ortb2Fragments = { - global: {site: commonSite, user: commonUser, badv, bcat}, - bidder: Object.fromEntries(allowedBidders.map(bidder => [bidder, {site, user, bcat, badv}])) + global: { site: commonSite, user: commonUser, badv, bcat }, + bidder: Object.fromEntries(allowedBidders.map(bidder => [bidder, { site, user, bcat, badv }])) }; adapter.callBids(await addFpdEnrichmentsToS2SRequest({ @@ -2835,10 +2835,10 @@ describe('S2S Adapter', function () { }); it('passes first party data in request for unknown when allowUnknownBidderCodes is true', async () => { - const cfg = {...CONFIG, allowUnknownBidderCodes: true}; - config.setConfig({s2sConfig: cfg}); + const cfg = { ...CONFIG, allowUnknownBidderCodes: true }; + config.setConfig({ s2sConfig: cfg }); - const clonedReq = {...REQUEST, s2sConfig: cfg} + const clonedReq = { ...REQUEST, s2sConfig: cfg } const s2sBidRequest = utils.deepClone(clonedReq); const bidRequests = utils.deepClone(BID_REQUESTS); @@ -2852,7 +2852,7 @@ describe('S2S Adapter', function () { }; const site = { - content: {userrating: 4}, + content: { userrating: 4 }, ext: { data: { pageType: 'article', @@ -2862,7 +2862,7 @@ describe('S2S Adapter', function () { }; const user = { yob: '1984', - geo: {country: 'ca'}, + geo: { country: 'ca' }, ext: { data: { registered: true, @@ -2879,7 +2879,7 @@ describe('S2S Adapter', function () { config: { ortb2: { site: { - content: {userrating: 4}, + content: { userrating: 4 }, ext: { data: { pageType: 'article', @@ -2889,7 +2889,7 @@ describe('S2S Adapter', function () { }, user: { yob: '1984', - geo: {country: 'ca'}, + geo: { country: 'ca' }, ext: { data: { registered: true, @@ -2912,8 +2912,8 @@ describe('S2S Adapter', function () { }, commonSite); const ortb2Fragments = { - global: {site: commonSite, user: commonUser, badv, bcat}, - bidder: Object.fromEntries(allowedBidders.map(bidder => [bidder, {site, user, bcat, badv}])) + global: { site: commonSite, user: commonUser, badv, bcat }, + bidder: Object.fromEntries(allowedBidders.map(bidder => [bidder, { site, user, bcat, badv }])) }; // adapter.callBids({ ...REQUEST, s2sConfig: cfg }, BID_REQUESTS, addBidResponse, done, ajax); @@ -3021,7 +3021,7 @@ describe('S2S Adapter', function () { }) it('should be set on imp.ext.prebid.imp', () => { const s2sReq = utils.deepClone(REQUEST); - s2sReq.ad_units[0].ortb2Imp = {l0: 'adUnit'}; + s2sReq.ad_units[0].ortb2Imp = { l0: 'adUnit' }; s2sReq.ad_units[0].bids = [ { bidder: 'A', @@ -3060,8 +3060,8 @@ describe('S2S Adapter', function () { const req = JSON.parse(server.requests[0].requestBody); expect(req.imp[0].l0).to.eql('adUnit'); expect(req.imp[0].ext.prebid.imp).to.eql({ - A: {l2: 'A'}, - B: {l2: 'B'} + A: { l2: 'A' }, + B: { l2: 'B' } }); }); }); @@ -3120,7 +3120,7 @@ describe('S2S Adapter', function () { let success, error; beforeEach(() => { const mockAjax = function (_, callback) { - ({success, error} = callback); + ({ success, error } = callback); } config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, mockAjax); @@ -3136,7 +3136,7 @@ describe('S2S Adapter', function () { 'other errors': false }).forEach(([t, timedOut]) => { it(`passing timedOut = ${timedOut} on ${t}`, () => { - error('', {timedOut}); + error('', { timedOut }); sinon.assert.calledWith(done, timedOut); }) }) @@ -3314,12 +3314,12 @@ describe('S2S Adapter', function () { it('emits the PBS_ANALYTICS event and captures seatnonbid responses', function () { const original = CONFIG; CONFIG.extPrebid = { returnallbidstatus: true }; - const nonbidResponse = {...RESPONSE_OPENRTB, ext: {seatnonbid: [{}]}}; + const nonbidResponse = { ...RESPONSE_OPENRTB, ext: { seatnonbid: [{}] } }; config.setConfig({ CONFIG }); CONFIG = original; adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const responding = deepClone(nonbidResponse); - Object.assign(responding.ext.seatnonbid, [{auctionId: 2}]) + Object.assign(responding.ext.seatnonbid, [{ auctionId: 2 }]) server.requests[0].respond(200, {}, JSON.stringify(responding)); const event = events.emit.getCall(2).args; expect(event[0]).to.equal(EVENTS.PBS_ANALYTICS); @@ -3331,7 +3331,7 @@ describe('S2S Adapter', function () { it('emits the PBS_ANALYTICS event and captures atag responses', function () { const original = CONFIG; CONFIG.extPrebid = { returnallbidstatus: true }; - const atagResponse = {...RESPONSE_OPENRTB, ext: {prebid: {analytics: {tags: ['data']}}}}; + const atagResponse = { ...RESPONSE_OPENRTB, ext: { prebid: { analytics: { tags: ['data'] } } } }; config.setConfig({ CONFIG }); CONFIG = original; adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); @@ -3555,13 +3555,13 @@ describe('S2S Adapter', function () { if (FEATURES.NATIVE) { it('handles OpenRTB native responses', function () { const stub = sinon.stub(auctionManager, 'index'); - stub.get(() => stubAuctionIndex({adUnits: REQUEST.ad_units})); + stub.get(() => stubAuctionIndex({ adUnits: REQUEST.ad_units })); const s2sConfig = Object.assign({}, CONFIG, { endpoint: { p1Consent: 'https://prebidserverurl/openrtb2/auction?querystring=param' } }); - config.setConfig({s2sConfig}); + config.setConfig({ s2sConfig }); const s2sBidRequest = utils.deepClone(REQUEST); s2sBidRequest.s2sConfig = s2sConfig; @@ -3585,7 +3585,7 @@ describe('S2S Adapter', function () { config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const response = deepClone(RESPONSE_OPENRTB); - Object.assign(response.seatbid[0].bid[0], {w: null, h: null}); + Object.assign(response.seatbid[0].bid[0], { w: null, h: null }); server.requests[0].respond(200, {}, JSON.stringify(response)); expect(addBidResponse.reject.calledOnce).to.be.true; expect(addBidResponse.called).to.be.false; @@ -3617,25 +3617,25 @@ describe('S2S Adapter', function () { let bidReq, response; function mks2sReq(s2sConfig = CONFIG) { - return {...REQUEST, s2sConfig, ad_units: [{...REQUEST.ad_units[0], bids: [{bidder: null, bid_id: 'testId'}]}]}; + return { ...REQUEST, s2sConfig, ad_units: [{ ...REQUEST.ad_units[0], bids: [{ bidder: null, bid_id: 'testId' }] }] }; } beforeEach(() => { - bidReq = {...BID_REQUESTS[0], bidderCode: null, bids: [{...BID_REQUESTS[0].bids[0], bidder: null, bidId: 'testId'}]} + bidReq = { ...BID_REQUESTS[0], bidderCode: null, bids: [{ ...BID_REQUESTS[0].bids[0], bidder: null, bidId: 'testId' }] } response = deepClone(RESPONSE_OPENRTB); response.seatbid[0].seat = 'storedImpression'; }) it('uses "null" request\'s ID for all responses, when a null request is present', function () { - const cfg = {...CONFIG, allowUnknownBidderCodes: true}; - config.setConfig({s2sConfig: cfg}); + const cfg = { ...CONFIG, allowUnknownBidderCodes: true }; + config.setConfig({ s2sConfig: cfg }); adapter.callBids(mks2sReq(cfg), [bidReq], addBidResponse, done, ajax); server.requests[0].respond(200, {}, JSON.stringify(response)); - sinon.assert.calledWith(addBidResponse, sinon.match.any, sinon.match({bidderCode: 'storedImpression', requestId: 'testId'})) + sinon.assert.calledWith(addBidResponse, sinon.match.any, sinon.match({ bidderCode: 'storedImpression', requestId: 'testId' })) }); it('does not allow null requests (= stored impressions) if allowUnknownBidderCodes is not set', () => { - config.setConfig({s2sConfig: CONFIG}); + config.setConfig({ s2sConfig: CONFIG }); adapter.callBids(mks2sReq(), [bidReq], addBidResponse, done, ajax); server.requests[0].respond(200, {}, JSON.stringify(response)); expect(addBidResponse.called).to.be.false; @@ -3644,11 +3644,11 @@ describe('S2S Adapter', function () { }) it('copies ortb2Imp to response when there is only a null bid', () => { - const cfg = {...CONFIG}; - config.setConfig({s2sConfig: cfg}); - const ortb2Imp = {ext: {prebid: {storedrequest: 'value'}}}; - const req = {...REQUEST, s2sConfig: cfg, ad_units: [{...REQUEST.ad_units[0], bids: [{bidder: null, bid_id: 'testId'}], ortb2Imp}]}; - const bidReq = {...BID_REQUESTS[0], bidderCode: null, bids: [{...BID_REQUESTS[0].bids[0], bidder: null, bidId: 'testId'}]} + const cfg = { ...CONFIG }; + config.setConfig({ s2sConfig: cfg }); + const ortb2Imp = { ext: { prebid: { storedrequest: 'value' } } }; + const req = { ...REQUEST, s2sConfig: cfg, ad_units: [{ ...REQUEST.ad_units[0], bids: [{ bidder: null, bid_id: 'testId' }], ortb2Imp }] }; + const bidReq = { ...BID_REQUESTS[0], bidderCode: null, bids: [{ ...BID_REQUESTS[0].bids[0], bidder: null, bidId: 'testId' }] } adapter.callBids(req, [bidReq], addBidResponse, done, ajax); const actual = JSON.parse(server.requests[0].requestBody); sinon.assert.match(actual.imp[0], sinon.match(ortb2Imp)); @@ -3757,9 +3757,9 @@ describe('S2S Adapter', function () { }); it('should translate wurl and burl into eventtrackers', () => { - const burlEvent = {event: 1, method: 1, url: 'burl'}; - const winEvent = {event: 500, method: 1, url: 'events.win'}; - const trackerEvent = {event: 500, method: 1, url: 'eventtracker'}; + const burlEvent = { event: 1, method: 1, url: 'burl' }; + const winEvent = { event: 500, method: 1, url: 'events.win' }; + const trackerEvent = { event: 500, method: 1, url: 'eventtracker' }; const resp = utils.deepClone(RESPONSE_OPENRTB); resp.seatbid[0].bid[0].ext.eventtrackers = [ @@ -3918,7 +3918,7 @@ describe('S2S Adapter', function () { // Add syncEndpoint so that the request goes to the User Sync endpoint // Modify the bidders property to include an alias for Rubicon adapter - s2sConfig.syncEndpoint = {p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync'}; + s2sConfig.syncEndpoint = { p1Consent: 'https://prebid.adnxs.com/pbs/v1/cookie_sync' }; s2sConfig.bidders = ['appnexus', 'rubicon-alias']; setupAlias(s2sConfig); @@ -4056,7 +4056,7 @@ describe('S2S Adapter', function () { expect(requestBid.ext.prebid.floors).to.be.undefined; - config.setConfig({floors: {}}); + config.setConfig({ floors: {} }); adapter.callBids(REQUEST, bidRequest, addBidResponse, done, ajax); requestBid = JSON.parse(server.requests[1].requestBody); @@ -4118,16 +4118,16 @@ describe('S2S Adapter', function () { code: 'au1', transactionId: 't1', mediaTypes: { - banner: {sizes: [1, 1]} + banner: { sizes: [1, 1] } }, - bids: [{bidder: 'b1', bid_id: 1}] + bids: [{ bidder: 'b1', bid_id: 1 }] }, { code: 'au2', transactionId: 't2', - bids: [{bidder: 'b2', bid_id: 2}], + bids: [{ bidder: 'b2', bid_id: 2 }], mediaTypes: { - banner: {sizes: [1, 1]} + banner: { sizes: [1, 1] } } } ]; @@ -4192,16 +4192,16 @@ describe('S2S Adapter', function () { code: 'au1', transactionId: 't1', mediaTypes: { - banner: {sizes: [1, 1]} + banner: { sizes: [1, 1] } }, - bids: [{bidder: 'b1', bid_id: 1}] + bids: [{ bidder: 'b1', bid_id: 1 }] }, { code: 'au2', transactionId: 't2', - bids: [{bidder: 'b2', bid_id: 2}], + bids: [{ bidder: 'b2', bid_id: 2 }], mediaTypes: { - banner: {sizes: [1, 1]} + banner: { sizes: [1, 1] } }, ortb2Imp: { ext: { @@ -4259,12 +4259,12 @@ describe('S2S Adapter', function () { }, bidder: { bidderA: { - k1: {k3: 'val'} + k1: { k3: 'val' } } }, expected: { bidderA: { - k1: {k3: 'val'} + k1: { k3: 'val' } } } }, @@ -4275,19 +4275,19 @@ describe('S2S Adapter', function () { }, bidder: { bidderA: { - k: {inner: 'val'} + k: { inner: 'val' } } }, expected: { bidderA: { - k: {inner: 'val'} + k: { inner: 'val' } } } }, { t: 'uses bidder config on type mismatch (object/array)', global: { - k: {inner: 'val'} + k: { inner: 'val' } }, bidder: { bidderA: { @@ -4374,32 +4374,32 @@ describe('S2S Adapter', function () { { t: 'does not repeat equal elements', global: { - array: [{id: 1}] + array: [{ id: 1 }] }, bidder: { bidderA: { - array: [{id: 1}, {id: 2}] + array: [{ id: 1 }, { id: 2 }] } }, expected: { bidderA: { - array: [{id: 1}, {id: 2}] + array: [{ id: 1 }, { id: 2 }] } } } - ].forEach(({t, global, bidder, expected}) => { + ].forEach(({ t, global, bidder, expected }) => { it(t, () => { - expect(getPBSBidderConfig({global, bidder})).to.eql(expected); + expect(getPBSBidderConfig({ global, bidder })).to.eql(expected); }) }) }); describe('EID handling', () => { function mkEid(source, value = source) { - return {source, value}; + return { source, value }; } function eidEntry(source, value = source, bidders = false) { - return {eid: {source, value}, bidders}; + return { eid: { source, value }, bidders }; } describe('extractEids', () => { @@ -4501,9 +4501,9 @@ describe('S2S Adapter', function () { ] } } - ].forEach(({t, global = {}, bidder = {}, expected}) => { + ].forEach(({ t, global = {}, bidder = {}, expected }) => { it(t, () => { - const {eids, conflicts} = extractEids({global, bidder}); + const { eids, conflicts } = extractEids({ global, bidder }); expect(eids).to.have.deep.members(expected.eids); expect(Array.from(conflicts)).to.have.members(expected.conflicts || []); }) @@ -4539,7 +4539,7 @@ describe('S2S Adapter', function () { ] })).to.eql({ global: [mkEid('idA'), mkEid('idB')], - permissions: [{source: 'idB', bidders: ['bidderB']}], + permissions: [{ source: 'idB', bidders: ['bidderB'] }], bidder: {} }) }) @@ -4585,7 +4585,7 @@ describe('S2S Adapter', function () { conflicts: new Set(['idA']) })).to.eql({ global: [mkEid('idA', 'idA1'), mkEid('idB')], - permissions: [{source: 'idB', bidders: ['bidderB']}], + permissions: [{ source: 'idB', bidders: ['bidderB'] }], bidder: { bidderA: [mkEid('idA', 'idA2')] } diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 6212d757e61..02db3d8067c 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1856,13 +1856,13 @@ describe('addViewabilityToImp', () => { }); it('should add viewability to imp.ext when measurable', () => { - addViewabilityToImp(imp, {adUnitCode: 'Div1'}, { w: 300, h: 250 }); + addViewabilityToImp(imp, { adUnitCode: 'Div1' }, { w: 300, h: 250 }); expect(imp.ext).to.have.property('viewability'); }); it('should set viewability amount to "na" if not measurable (e.g., in iframe)', () => { const isIframeStub = sandbox.stub(utils, 'inIframe').returns(true); - addViewabilityToImp(imp, {adUnitCode: 'Div1'}, { w: 300, h: 250 }); + addViewabilityToImp(imp, { adUnitCode: 'Div1' }, { w: 300, h: 250 }); expect(imp.ext).to.have.property('viewability'); expect(imp.ext.viewability.amount).to.equal('na'); }); @@ -1870,13 +1870,13 @@ describe('addViewabilityToImp', () => { it('should not add viewability if element is not found', () => { document.getElementById.restore(); sandbox.stub(document, 'getElementById').returns(null); - addViewabilityToImp(imp, {adUnitCode: 'Div1'}, { w: 300, h: 250 }); + addViewabilityToImp(imp, { adUnitCode: 'Div1' }, { w: 300, h: 250 }); expect(imp.ext).to.not.have.property('viewability'); }); it('should create imp.ext if not present', () => { imp = {}; - addViewabilityToImp(imp, {adUnitCode: 'Div1'}, { w: 300, h: 250 }); + addViewabilityToImp(imp, { adUnitCode: 'Div1' }, { w: 300, h: 250 }); expect(imp.ext).to.exist; expect(imp.ext).to.have.property('viewability'); }); diff --git a/test/spec/modules/smaatoBidAdapter_spec.js b/test/spec/modules/smaatoBidAdapter_spec.js index 8e7a21a92bb..8edeabd466b 100644 --- a/test/spec/modules/smaatoBidAdapter_spec.js +++ b/test/spec/modules/smaatoBidAdapter_spec.js @@ -1,6 +1,6 @@ -import {spec} from 'modules/smaatoBidAdapter.js'; +import { spec } from 'modules/smaatoBidAdapter.js'; import * as utils from 'src/utils.js'; -import {config} from 'src/config.js'; +import { config } from 'src/config.js'; // load modules that register ORTB processors import 'src/prebid.js' @@ -72,32 +72,32 @@ describe('smaatoBidAdapterTest', () => { }); it('is invalid, when params object is empty', () => { - expect(spec.isBidRequestValid({params: {}})).to.be.false; + expect(spec.isBidRequestValid({ params: {} })).to.be.false; }); it('is invalid, when publisherId is present but of wrong type', () => { - expect(spec.isBidRequestValid({params: {publisherId: 123}})).to.be.false; + expect(spec.isBidRequestValid({ params: { publisherId: 123 } })).to.be.false; }); it('is invalid, when adbreakId param is present', () => { - expect(spec.isBidRequestValid({params: {publisherId: '123', adspaceId: '456', adbreakId: '42'}})).to.be.false; + expect(spec.isBidRequestValid({ params: { publisherId: '123', adspaceId: '456', adbreakId: '42' } })).to.be.false; }); describe('for supported requests', () => { it('is invalid, when adspaceId is missing', () => { - expect(spec.isBidRequestValid({params: {publisherId: '123'}})).to.be.false; + expect(spec.isBidRequestValid({ params: { publisherId: '123' } })).to.be.false; }); it('is invalid, when adspaceId is present but of wrong type', () => { - expect(spec.isBidRequestValid({params: {publisherId: '123', adspaceId: 456}})).to.be.false; + expect(spec.isBidRequestValid({ params: { publisherId: '123', adspaceId: 456 } })).to.be.false; }); it('is valid, when required params are present for minimal request', () => { - expect(spec.isBidRequestValid({params: {publisherId: '123', adspaceId: '456'}})).to.be.true; + expect(spec.isBidRequestValid({ params: { publisherId: '123', adspaceId: '456' } })).to.be.true; }); it('is invalid, when forbidden adbreakId param is present', () => { - expect(spec.isBidRequestValid({params: {publisherId: '123', adspaceId: '456', adbreakId: '42'}})).to.be.false; + expect(spec.isBidRequestValid({ params: { publisherId: '123', adspaceId: '456', adbreakId: '42' } })).to.be.false; }); }); }); @@ -273,7 +273,7 @@ describe('smaatoBidAdapterTest', () => { }, }; - const reqs = spec.buildRequests([singleBannerBidRequest], {...defaultBidderRequest, ortb2}); + const reqs = spec.buildRequests([singleBannerBidRequest], { ...defaultBidderRequest, ortb2 }); const req = extractPayloadOfFirstAndOnlyRequest(reqs); expect(req.site.id).to.exist.and.to.be.a('string'); @@ -298,7 +298,7 @@ describe('smaatoBidAdapterTest', () => { }, }; - const reqs = spec.buildRequests([singleBannerBidRequest], {...defaultBidderRequest, ortb2}); + const reqs = spec.buildRequests([singleBannerBidRequest], { ...defaultBidderRequest, ortb2 }); const req = extractPayloadOfFirstAndOnlyRequest(reqs); expect(req.dooh.id).to.exist.and.to.be.a('string'); @@ -328,7 +328,7 @@ describe('smaatoBidAdapterTest', () => { }, }; - const reqs = spec.buildRequests([singleBannerBidRequest], {...defaultBidderRequest, ortb2}); + const reqs = spec.buildRequests([singleBannerBidRequest], { ...defaultBidderRequest, ortb2 }); const req = extractPayloadOfFirstAndOnlyRequest(reqs); expect(req.device.language).to.equal(language); @@ -354,7 +354,7 @@ describe('smaatoBidAdapterTest', () => { }, }; - const reqs = spec.buildRequests([singleBannerBidRequest], {...defaultBidderRequest, ortb2}); + const reqs = spec.buildRequests([singleBannerBidRequest], { ...defaultBidderRequest, ortb2 }); const req = extractPayloadOfFirstAndOnlyRequest(reqs); expect(req.regs.coppa).to.equal(1); @@ -383,7 +383,7 @@ describe('smaatoBidAdapterTest', () => { } }; - const reqs = spec.buildRequests([singleBannerBidRequest], {...defaultBidderRequest, ortb2}); + const reqs = spec.buildRequests([singleBannerBidRequest], { ...defaultBidderRequest, ortb2 }); const req = extractPayloadOfFirstAndOnlyRequest(reqs); expect(req.regs.ext.gpp).to.eql('gppString'); @@ -398,8 +398,8 @@ describe('smaatoBidAdapterTest', () => { }); it('sends instl if instl exists', () => { - const instl = {instl: 1}; - const bidRequestWithInstl = Object.assign({}, singleBannerBidRequest, {ortb2Imp: instl}); + const instl = { instl: 1 }; + const bidRequestWithInstl = Object.assign({}, singleBannerBidRequest, { ortb2Imp: instl }); const reqs = spec.buildRequests([bidRequestWithInstl], defaultBidderRequest); @@ -444,7 +444,7 @@ describe('smaatoBidAdapterTest', () => { } }; - const reqs = spec.buildRequests([singleBannerBidRequest], {...defaultBidderRequest, ortb2}); + const reqs = spec.buildRequests([singleBannerBidRequest], { ...defaultBidderRequest, ortb2 }); const req = extractPayloadOfFirstAndOnlyRequest(reqs); expect(req.user.gender).to.equal('M'); @@ -494,7 +494,7 @@ describe('smaatoBidAdapterTest', () => { } }; - const reqs = spec.buildRequests([singleBannerBidRequest], {...defaultBidderRequest, ortb2}); + const reqs = spec.buildRequests([singleBannerBidRequest], { ...defaultBidderRequest, ortb2 }); const req = extractPayloadOfFirstAndOnlyRequest(reqs); expect(req.regs.ext.dsa.dsarequired).to.eql(2); @@ -511,7 +511,7 @@ describe('smaatoBidAdapterTest', () => { } }; - const reqs = spec.buildRequests([singleBannerBidRequest], {...defaultBidderRequest, ortb2}); + const reqs = spec.buildRequests([singleBannerBidRequest], { ...defaultBidderRequest, ortb2 }); const req = extractPayloadOfFirstAndOnlyRequest(reqs); expect(req.regs.ext.dsa).to.be.undefined; @@ -548,7 +548,7 @@ describe('smaatoBidAdapterTest', () => { skip: 1, skipmin: 5, api: [7], - ext: {rewarded: 0} + ext: { rewarded: 0 } }; const VIDEO_OUTSTREAM_OPENRTB_IMP = { mimes: ['video/mp4', 'video/quicktime', 'video/3gpp', 'video/x-m4v'], @@ -615,8 +615,8 @@ describe('smaatoBidAdapterTest', () => { }); it('sends instl if instl exists', () => { - const instl = {instl: 1}; - const bidRequestWithInstl = Object.assign({}, singleVideoBidRequest, {ortb2Imp: instl}); + const instl = { instl: 1 }; + const bidRequestWithInstl = Object.assign({}, singleVideoBidRequest, { ortb2Imp: instl }); const reqs = spec.buildRequests([bidRequestWithInstl], defaultBidderRequest); @@ -848,7 +848,7 @@ describe('smaatoBidAdapterTest', () => { it('when geo and ifa info present, then add both to device object', () => { const inAppBidRequest = utils.deepClone(inAppBidRequestWithoutAppParams); - inAppBidRequest.params.app = {ifa: DEVICE_ID, geo: LOCATION}; + inAppBidRequest.params.app = { ifa: DEVICE_ID, geo: LOCATION }; const reqs = spec.buildRequests([inAppBidRequest], defaultBidderRequest); @@ -869,9 +869,9 @@ describe('smaatoBidAdapterTest', () => { }; const inAppBidRequest = utils.deepClone(inAppBidRequestWithoutAppParams); - inAppBidRequest.params.app = {ifa: DEVICE_ID, geo: LOCATION}; + inAppBidRequest.params.app = { ifa: DEVICE_ID, geo: LOCATION }; - const reqs = spec.buildRequests([inAppBidRequest], {...defaultBidderRequest, ortb2}); + const reqs = spec.buildRequests([inAppBidRequest], { ...defaultBidderRequest, ortb2 }); const req = extractPayloadOfFirstAndOnlyRequest(reqs); expect(req.device.geo.lat).to.equal(53.5488); @@ -881,7 +881,7 @@ describe('smaatoBidAdapterTest', () => { it('when ifa is present but geo is missing, then add only ifa to device object', () => { const inAppBidRequest = utils.deepClone(inAppBidRequestWithoutAppParams); - inAppBidRequest.params.app = {ifa: DEVICE_ID}; + inAppBidRequest.params.app = { ifa: DEVICE_ID }; const reqs = spec.buildRequests([inAppBidRequest], defaultBidderRequest); @@ -892,7 +892,7 @@ describe('smaatoBidAdapterTest', () => { it('when geo is present but ifa is missing, then add only geo to device object', () => { const inAppBidRequest = utils.deepClone(inAppBidRequestWithoutAppParams); - inAppBidRequest.params.app = {geo: LOCATION}; + inAppBidRequest.params.app = { geo: LOCATION }; const reqs = spec.buildRequests([inAppBidRequest], defaultBidderRequest); @@ -935,7 +935,7 @@ describe('smaatoBidAdapterTest', () => { tdid: '89145' }, userIdAsEids: [ - {id: 1}, {id: 2} + { id: 1 }, { id: 2 } ] }; @@ -979,7 +979,7 @@ describe('smaatoBidAdapterTest', () => { }); describe('interpretResponse', () => { - function buildBidRequest(payloadAsJsObj = {imp: [{}]}) { + function buildBidRequest(payloadAsJsObj = { imp: [{}] }) { return { method: 'POST', url: 'https://prebid.ad.smaato.net/oapi/prebid', @@ -1074,7 +1074,7 @@ describe('smaatoBidAdapterTest', () => { adm = ''; break; case ADTYPE_NATIVE: - adm = JSON.stringify({native: NATIVE_RESPONSE}) + adm = JSON.stringify({ native: NATIVE_RESPONSE }) break; default: throw Error('Invalid AdType'); @@ -1125,7 +1125,7 @@ describe('smaatoBidAdapterTest', () => { }; it('returns empty array on no bid responses', () => { - const response_with_empty_body = {body: {}}; + const response_with_empty_body = { body: {} }; const bids = spec.interpretResponse(response_with_empty_body, buildBidRequest()); @@ -1264,7 +1264,7 @@ describe('smaatoBidAdapterTest', () => { } ] }, - headers: {get: () => undefined} + headers: { get: () => undefined } }; }); @@ -1290,7 +1290,7 @@ describe('smaatoBidAdapterTest', () => { it('uses net revenue flag send from server', () => { const resp = buildOpenRtbBidResponse(ADTYPE_IMG); - resp.body.seatbid[0].bid[0].ext = {net: false}; + resp.body.seatbid[0].bid[0].ext = { net: false }; const bids = spec.interpretResponse(resp, buildBidRequest()); @@ -1337,7 +1337,7 @@ describe('smaatoBidAdapterTest', () => { }) it('when pixelEnabled true then returns image sync', () => { - expect(spec.getUserSyncs({pixelEnabled: true}, null, null, null)).to.deep.equal( + expect(spec.getUserSyncs({ pixelEnabled: true }, null, null, null)).to.deep.equal( [ { type: 'image', @@ -1348,7 +1348,7 @@ describe('smaatoBidAdapterTest', () => { }) it('when iframeEnabled true then returns iframe sync', () => { - expect(spec.getUserSyncs({iframeEnabled: true}, null, null, null)).to.deep.equal( + expect(spec.getUserSyncs({ iframeEnabled: true }, null, null, null)).to.deep.equal( [ { type: 'iframe', @@ -1359,8 +1359,8 @@ describe('smaatoBidAdapterTest', () => { }) it('when iframeEnabled true and syncsPerBidder then returns iframe sync', () => { - config.setConfig({userSync: {syncsPerBidder: 5}}); - expect(spec.getUserSyncs({iframeEnabled: true}, null, null, null)).to.deep.equal( + config.setConfig({ userSync: { syncsPerBidder: 5 } }); + expect(spec.getUserSyncs({ iframeEnabled: true }, null, null, null)).to.deep.equal( [ { type: 'iframe', @@ -1371,7 +1371,7 @@ describe('smaatoBidAdapterTest', () => { }) it('when iframeEnabled and pixelEnabled true then returns iframe sync', () => { - expect(spec.getUserSyncs({pixelEnabled: true, iframeEnabled: true}, null, null, null)).to.deep.equal( + expect(spec.getUserSyncs({ pixelEnabled: true, iframeEnabled: true }, null, null, null)).to.deep.equal( [ { type: 'iframe', @@ -1382,7 +1382,7 @@ describe('smaatoBidAdapterTest', () => { }) it('when pixelEnabled true and gdprConsent then returns image sync with gdpr params', () => { - expect(spec.getUserSyncs({pixelEnabled: true}, null, {gdprApplies: true, consentString: CONSENT_STRING}, null)).to.deep.equal( + expect(spec.getUserSyncs({ pixelEnabled: true }, null, { gdprApplies: true, consentString: CONSENT_STRING }, null)).to.deep.equal( [ { type: 'image', @@ -1393,7 +1393,7 @@ describe('smaatoBidAdapterTest', () => { }) it('when iframeEnabled true and gdprConsent then returns iframe with gdpr params', () => { - expect(spec.getUserSyncs({iframeEnabled: true}, null, {gdprApplies: true, consentString: CONSENT_STRING}, null)).to.deep.equal( + expect(spec.getUserSyncs({ iframeEnabled: true }, null, { gdprApplies: true, consentString: CONSENT_STRING }, null)).to.deep.equal( [ { type: 'iframe', @@ -1404,7 +1404,7 @@ describe('smaatoBidAdapterTest', () => { }) it('when pixelEnabled true and gdprConsent without gdpr then returns pixel sync with gdpr_consent', () => { - expect(spec.getUserSyncs({pixelEnabled: true}, null, {consentString: CONSENT_STRING}, null), null).to.deep.equal( + expect(spec.getUserSyncs({ pixelEnabled: true }, null, { consentString: CONSENT_STRING }, null), null).to.deep.equal( [ { type: 'image', @@ -1415,7 +1415,7 @@ describe('smaatoBidAdapterTest', () => { }) it('when iframeEnabled true and gdprConsent without gdpr then returns iframe sync with gdpr_consent', () => { - expect(spec.getUserSyncs({iframeEnabled: true}, null, {consentString: CONSENT_STRING}, null), null).to.deep.equal( + expect(spec.getUserSyncs({ iframeEnabled: true }, null, { consentString: CONSENT_STRING }, null), null).to.deep.equal( [ { type: 'iframe', diff --git a/test/spec/modules/storageControl_spec.js b/test/spec/modules/storageControl_spec.js index b94f5a6fd67..ac1d86badc0 100644 --- a/test/spec/modules/storageControl_spec.js +++ b/test/spec/modules/storageControl_spec.js @@ -215,8 +215,8 @@ describe('storageControl', () => { it('should deny by default when enforcement is not set', () => { enforcement = undefined; - checkResult = {disclosed: false, parent: false, reason: 'denied'}; - expect(rule()).to.eql({allow: false, reason: 'denied'}); + checkResult = { disclosed: false, parent: false, reason: 'denied' }; + expect(rule()).to.eql({ allow: false, reason: 'denied' }); }); it('should allow when enforcement is allowAliases and disclosure is done by the aliased module', () => { diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index 72c6baff8cc..e9f205b6745 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -5,7 +5,7 @@ import { deepClone } from 'src/utils.js'; import { config } from 'src/config.js'; import prebid from 'package.json'; import * as utils from 'src/utils.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; const ENDPOINT = 'https://tlx.3lift.com/header/auction?'; const GDPR_CONSENT_STR = 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVA9LTOQ6gEaY'; @@ -645,7 +645,7 @@ describe('triplelift adapter', function () { it('should only parse sizes that are of the proper length and format', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); expect(request.data.imp[0].banner.format).to.have.length(2); - expect(request.data.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + expect(request.data.imp[0].banner.format).to.deep.equal([{ w: 300, h: 250 }, { w: 300, h: 600 }]); }); it('should be a post request and populate the payload', function () { @@ -654,7 +654,7 @@ describe('triplelift adapter', function () { expect(payload).to.exist; expect(payload.imp[0].tagid).to.equal('12345'); expect(payload.imp[0].floor).to.equal(1.0); - expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + expect(payload.imp[0].banner.format).to.deep.equal([{ w: 300, h: 250 }, { w: 300, h: 600 }]); // instream expect(payload.imp[1].tagid).to.equal('insteam_test'); expect(payload.imp[1].floor).to.equal(1.0); @@ -663,16 +663,16 @@ describe('triplelift adapter', function () { // banner and outstream video expect(payload.imp[2]).to.have.property('video'); expect(payload.imp[2]).to.have.property('banner'); - expect(payload.imp[2].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); - expect(payload.imp[2].video).to.deep.equal({'mimes': ['video/mp4'], 'maxduration': 30, 'minduration': 6, 'w': 640, 'h': 480, 'context': 'outstream'}); + expect(payload.imp[2].banner.format).to.deep.equal([{ w: 300, h: 250 }, { w: 300, h: 600 }]); + expect(payload.imp[2].video).to.deep.equal({ 'mimes': ['video/mp4'], 'maxduration': 30, 'minduration': 6, 'w': 640, 'h': 480, 'context': 'outstream' }); // banner and incomplete video expect(payload.imp[3]).to.not.have.property('video'); expect(payload.imp[3]).to.have.property('banner'); - expect(payload.imp[3].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + expect(payload.imp[3].banner.format).to.deep.equal([{ w: 300, h: 250 }, { w: 300, h: 600 }]); // incomplete mediatypes.banner and incomplete video expect(payload.imp[4]).to.not.have.property('video'); expect(payload.imp[4]).to.have.property('banner'); - expect(payload.imp[4].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + expect(payload.imp[4].banner.format).to.deep.equal([{ w: 300, h: 250 }, { w: 300, h: 600 }]); // banner and instream video expect(payload.imp[5]).to.not.have.property('banner'); expect(payload.imp[5]).to.have.property('video'); @@ -681,20 +681,20 @@ describe('triplelift adapter', function () { // banner and outream video and native expect(payload.imp[6]).to.have.property('video'); expect(payload.imp[6]).to.have.property('banner'); - expect(payload.imp[6].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); - expect(payload.imp[6].video).to.deep.equal({'mimes': ['video/mp4'], 'maxduration': 30, 'minduration': 6, 'w': 640, 'h': 480, 'context': 'outstream'}); + expect(payload.imp[6].banner.format).to.deep.equal([{ w: 300, h: 250 }, { w: 300, h: 600 }]); + expect(payload.imp[6].video).to.deep.equal({ 'mimes': ['video/mp4'], 'maxduration': 30, 'minduration': 6, 'w': 640, 'h': 480, 'context': 'outstream' }); // outstream video only expect(payload.imp[7]).to.have.property('video'); expect(payload.imp[7]).to.not.have.property('banner'); - expect(payload.imp[7].video).to.deep.equal({'mimes': ['video/mp4'], 'maxduration': 30, 'minduration': 6, 'w': 640, 'h': 480, 'context': 'outstream'}); + expect(payload.imp[7].video).to.deep.equal({ 'mimes': ['video/mp4'], 'maxduration': 30, 'minduration': 6, 'w': 640, 'h': 480, 'context': 'outstream' }); // banner and incomplete outstream (missing size); video request is permitted so banner can still monetize expect(payload.imp[8]).to.have.property('video'); expect(payload.imp[8]).to.have.property('banner'); - expect(payload.imp[8].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); - expect(payload.imp[8].video).to.deep.equal({'mimes': ['video/mp4'], 'maxduration': 30, 'minduration': 6, 'context': 'outstream'}); + expect(payload.imp[8].banner.format).to.deep.equal([{ w: 300, h: 250 }, { w: 300, h: 600 }]); + expect(payload.imp[8].video).to.deep.equal({ 'mimes': ['video/mp4'], 'maxduration': 30, 'minduration': 6, 'context': 'outstream' }); // outstream new plcmt value expect(payload.imp[13]).to.have.property('video'); - expect(payload.imp[13].video).to.deep.equal({'mimes': ['video/mp4'], 'maxduration': 30, 'minduration': 6, 'w': 640, 'h': 480, 'context': 'outstream', 'plcmt': 3}); + expect(payload.imp[13].video).to.deep.equal({ 'mimes': ['video/mp4'], 'maxduration': 30, 'minduration': 6, 'w': 640, 'h': 480, 'context': 'outstream', 'plcmt': 3 }); }); it('should check for valid outstream placement values', function () { @@ -779,7 +779,7 @@ describe('triplelift adapter', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.exist; - expect(payload.user).to.deep.equal({ext: {eids: [{source: 'adserver.org', uids: [{id: tdid, atype: 1, ext: {rtiPartner: 'TDID'}}]}]}}); + expect(payload.user).to.deep.equal({ ext: { eids: [{ source: 'adserver.org', uids: [{ id: tdid, atype: 1, ext: { rtiPartner: 'TDID' } }] }] } }); }); it('should add criteoId to the payload if included', function () { @@ -801,7 +801,7 @@ describe('triplelift adapter', function () { const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); const payload = request.data; expect(payload).to.exist; - expect(payload.user).to.deep.equal({ext: {eids: [{source: 'criteo.com', uids: [{id: id, atype: 1, ext: {rtiPartner: 'criteoId'}}]}]}}); + expect(payload.user).to.deep.equal({ ext: { eids: [{ source: 'criteo.com', uids: [{ id: id, atype: 1, ext: { rtiPartner: 'criteoId' } }] }] } }); }); it('should add tdid and criteoId to the payload if both are included', function () { @@ -1005,7 +1005,7 @@ describe('triplelift adapter', function () { } }; - const request = tripleliftAdapterSpec.buildRequests(bidRequests, {...bidderRequest, ortb2}); + const request = tripleliftAdapterSpec.buildRequests(bidRequests, { ...bidderRequest, ortb2 }); const { data: payload } = request; expect(payload.ext.ortb2).to.exist; expect(payload.ext.ortb2.site).to.deep.equal({ @@ -1033,7 +1033,7 @@ describe('triplelift adapter', function () { sens: sens, } } - const request = tripleliftAdapterSpec.buildRequests(bidRequests, {...bidderRequest, ortb2}); + const request = tripleliftAdapterSpec.buildRequests(bidRequests, { ...bidderRequest, ortb2 }); const { data: payload } = request; expect(payload.ext.fpd.user).to.not.exist; expect(payload.ext.fpd.context.ext.data).to.haveOwnProperty('category'); @@ -1349,7 +1349,7 @@ describe('triplelift adapter', function () { meta: {} } ]; - const result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); + const result = tripleliftAdapterSpec.interpretResponse(response, { bidderRequest }); expect(result).to.have.length(4); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); expect(Object.keys(result[1])).to.have.members(Object.keys(expectedResponse[1])); @@ -1358,7 +1358,7 @@ describe('triplelift adapter', function () { }); it('should identify format of bid and respond accordingly', function() { - const result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); + const result = tripleliftAdapterSpec.interpretResponse(response, { bidderRequest }); expect(result[0].meta.mediaType).to.equal('native'); expect(result[1].mediaType).to.equal('video'); expect(result[1].meta.mediaType).to.equal('video'); @@ -1371,25 +1371,25 @@ describe('triplelift adapter', function () { }) it('should return multiple responses to support SRA', function () { - const result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); + const result = tripleliftAdapterSpec.interpretResponse(response, { bidderRequest }); expect(result).to.have.length(4); }); it('should include the advertiser name in the meta field if available', function () { - const result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); + const result = tripleliftAdapterSpec.interpretResponse(response, { bidderRequest }); expect(result[0].meta.advertiserName).to.equal('fake advertiser name'); expect(result[1].meta).to.not.have.key('advertiserName'); }); it('should include the advertiser domain array in the meta field if available', function () { - const result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); + const result = tripleliftAdapterSpec.interpretResponse(response, { bidderRequest }); expect(result[0].meta.advertiserDomains[0]).to.equal('basspro.com'); expect(result[0].meta.advertiserDomains[1]).to.equal('internetalerts.org'); expect(result[1].meta).to.not.have.key('advertiserDomains'); }); it('should include networkId in the meta field if available', function () { - const result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); + const result = tripleliftAdapterSpec.interpretResponse(response, { bidderRequest }); expect(result[1].meta.networkId).to.equal('10092'); expect(result[2].meta.networkId).to.equal('5989'); expect(result[3].meta.networkId).to.equal('5989'); diff --git a/test/spec/modules/twistDigitalBidAdapter_spec.js b/test/spec/modules/twistDigitalBidAdapter_spec.js index 25a521d957d..97a27f79b65 100644 --- a/test/spec/modules/twistDigitalBidAdapter_spec.js +++ b/test/spec/modules/twistDigitalBidAdapter_spec.js @@ -1,15 +1,15 @@ -import {expect} from 'chai'; +import { expect } from 'chai'; import { spec as adapter, createDomain, storage } from 'modules/twistDigitalBidAdapter.js'; import * as utils from 'src/utils.js'; -import {version} from 'package.json'; -import {useFakeTimers} from 'sinon'; -import {BANNER, VIDEO} from '../../../src/mediaTypes.js'; -import {config} from '../../../src/config.js'; -import {deepSetValue} from 'src/utils.js'; +import { version } from 'package.json'; +import { useFakeTimers } from 'sinon'; +import { BANNER, VIDEO } from '../../../src/mediaTypes.js'; +import { config } from '../../../src/config.js'; +import { deepSetValue } from 'src/utils.js'; import { extractPID, extractCID, @@ -20,7 +20,7 @@ import { tryParseJSON, getUniqueDealId } from '../../../libraries/vidazooUtils/bidderUtils.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; export const TEST_ID_SYSTEMS = ['britepoolid', 'criteoId', 'id5id', 'idl_env', 'lipb', 'netId', 'parrableId', 'pubcid', 'tdid', 'pubProvidedId']; @@ -103,9 +103,9 @@ const ORTB2_DEVICE = { 'version': ['8', '0', '0'] }, 'browsers': [ - {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']}, - {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']}, - {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']} + { 'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0'] }, + { 'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119'] }, + { 'brand': 'Chromium', 'version': ['109', '0', '5414', '119'] } ], 'mobile': 1, 'model': 'SM-G955U', @@ -122,7 +122,7 @@ const ORTB2_DEVICE = { model: 'iPhone 12 Pro Max', os: 'iOS', osv: '17.4', - ext: {fiftyonedegrees_deviceId: '17595-133085-133468-18092'}, + ext: { fiftyonedegrees_deviceId: '17595-133085-133468-18092' }, }; const BIDDER_REQUEST = { @@ -149,8 +149,8 @@ const BIDDER_REQUEST = { 'segtax': 7 }, 'segments': [ - {'id': 'segId1'}, - {'id': 'segId2'} + { 'id': 'segId1' }, + { 'id': 'segId2' } ] }] } @@ -164,9 +164,9 @@ const BIDDER_REQUEST = { user: { data: [ { - ext: {segtax: 600, segclass: '1'}, + ext: { segtax: 600, segclass: '1' }, name: 'example.com', - segment: [{id: '243'}], + segment: [{ id: '243' }], }, ], } @@ -215,21 +215,21 @@ const VIDEO_SERVER_RESPONSE = { const ORTB2_OBJ = { "device": ORTB2_DEVICE, - "regs": {"coppa": 0, "gpp": "gpp_string", "gpp_sid": [7]}, + "regs": { "coppa": 0, "gpp": "gpp_string", "gpp_sid": [7] }, "site": { "cat": ["IAB2"], "content": { "data": [{ - "ext": {"segtax": 7}, + "ext": { "segtax": 7 }, "name": "example.com", - "segments": [{"id": "segId1"}, {"id": "segId2"}] + "segments": [{ "id": "segId1" }, { "id": "segId2" }] }], "language": "en" }, "pagecat": ["IAB2-2"] }, "user": { - "data": [{"ext": {"segclass": "1", "segtax": 600}, "name": "example.com", "segment": [{"id": "243"}]}] + "data": [{ "ext": { "segclass": "1", "segtax": 600 }, "name": "example.com", "segment": [{ "id": "243" }] }] } }; @@ -243,7 +243,7 @@ const REQUEST = { function getTopWindowQueryParams() { try { - const parsedUrl = utils.parseUrl(window.top.document.URL, {decodeSearchAsString: true}); + const parsedUrl = utils.parseUrl(window.top.document.URL, { decodeSearchAsString: true }); return parsedUrl.search; } catch (e) { return ''; @@ -369,9 +369,9 @@ describe('TwistDigitalBidAdapter', function () { 'version': ['8', '0', '0'] }, 'browsers': [ - {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']}, - {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']}, - {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']} + { 'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0'] }, + { 'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119'] }, + { 'brand': 'Chromium', 'version': ['109', '0', '5414', '119'] } ], 'mobile': 1, 'model': 'SM-G955U', @@ -387,15 +387,15 @@ describe('TwistDigitalBidAdapter', function () { 'segtax': 7 }, 'segments': [ - {'id': 'segId1'}, - {'id': 'segId2'} + { 'id': 'segId1' }, + { 'id': 'segId2' } ] }], userData: [ { - ext: {segtax: 600, segclass: '1'}, + ext: { segtax: 600, segclass: '1' }, name: 'example.com', - segment: [{id: '243'}], + segment: [{ id: '243' }], }, ], uniqueDealId: `${hashUrl}_${Date.now().toString()}`, @@ -453,9 +453,9 @@ describe('TwistDigitalBidAdapter', function () { 'version': ['8', '0', '0'] }, 'browsers': [ - {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']}, - {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']}, - {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']} + { 'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0'] }, + { 'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119'] }, + { 'brand': 'Chromium', 'version': ['109', '0', '5414', '119'] } ], 'mobile': 1, 'model': 'SM-G955U', @@ -493,15 +493,15 @@ describe('TwistDigitalBidAdapter', function () { 'segtax': 7 }, 'segments': [ - {'id': 'segId1'}, - {'id': 'segId2'} + { 'id': 'segId1' }, + { 'id': 'segId2' } ] }], userData: [ { - ext: {segtax: 600, segclass: '1'}, + ext: { segtax: 600, segclass: '1' }, name: 'example.com', - segment: [{id: '243'}], + segment: [{ id: '243' }], }, ] } @@ -544,9 +544,9 @@ describe('TwistDigitalBidAdapter', function () { 'version': ['8', '0', '0'] }, 'browsers': [ - {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']}, - {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']}, - {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']} + { 'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0'] }, + { 'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119'] }, + { 'brand': 'Chromium', 'version': ['109', '0', '5414', '119'] } ], 'mobile': 1, 'model': 'SM-G955U', @@ -582,15 +582,15 @@ describe('TwistDigitalBidAdapter', function () { 'segtax': 7 }, 'segments': [ - {'id': 'segId1'}, - {'id': 'segId2'} + { 'id': 'segId1' }, + { 'id': 'segId2' } ] }], userData: [ { - ext: {segtax: 600, segclass: '1'}, + ext: { segtax: 600, segclass: '1' }, name: 'example.com', - segment: [{id: '243'}], + segment: [{ id: '243' }], }, ] }; @@ -606,10 +606,12 @@ describe('TwistDigitalBidAdapter', function () { expect(requests[0]).to.deep.equal({ method: 'POST', url: `${createDomain(SUB_DOMAIN)}/prebid/multi/59db6b3b4ffaa70004f45cdc`, - data: {bids: [ - {...REQUEST_DATA, ortb2: ORTB2_OBJ, ortb2Imp: BID.ortb2Imp}, - {...REQUEST_DATA2, ortb2: ORTB2_OBJ, ortb2Imp: BID.ortb2Imp} - ]} + data: { + bids: [ + { ...REQUEST_DATA, ortb2: ORTB2_OBJ, ortb2Imp: BID.ortb2Imp }, + { ...REQUEST_DATA2, ortb2: ORTB2_OBJ, ortb2Imp: BID.ortb2Imp } + ] + } }); }); @@ -648,7 +650,7 @@ describe('TwistDigitalBidAdapter', function () { describe('getUserSyncs', function () { it('should have valid user sync with iframeEnabled', function () { - const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]); + const result = adapter.getUserSyncs({ iframeEnabled: true }, [SERVER_RESPONSE]); expect(result).to.deep.equal([{ type: 'iframe', @@ -657,7 +659,7 @@ describe('TwistDigitalBidAdapter', function () { }); it('should have valid user sync with cid on response', function () { - const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]); + const result = adapter.getUserSyncs({ iframeEnabled: true }, [SERVER_RESPONSE]); expect(result).to.deep.equal([{ type: 'iframe', url: 'https://sync.twist.win/api/sync/iframe/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy=&coppa=0' @@ -665,7 +667,7 @@ describe('TwistDigitalBidAdapter', function () { }); it('should have valid user sync with pixelEnabled', function () { - const result = adapter.getUserSyncs({pixelEnabled: true}, [SERVER_RESPONSE]); + const result = adapter.getUserSyncs({ pixelEnabled: true }, [SERVER_RESPONSE]); expect(result).to.deep.equal([{ 'url': 'https://sync.twist.win/api/sync/image/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy=&coppa=0', @@ -677,7 +679,7 @@ describe('TwistDigitalBidAdapter', function () { config.setConfig({ coppa: 1 }); - const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]); + const result = adapter.getUserSyncs({ iframeEnabled: true }, [SERVER_RESPONSE]); expect(result).to.deep.equal([{ type: 'iframe', url: 'https://sync.twist.win/api/sync/iframe/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy=&coppa=1' @@ -692,12 +694,12 @@ describe('TwistDigitalBidAdapter', function () { }); it('should return empty array when there is no ad', function () { - const responses = adapter.interpretResponse({price: 1, ad: ''}); + const responses = adapter.interpretResponse({ price: 1, ad: '' }); expect(responses).to.be.empty; }); it('should return empty array when there is no price', function () { - const responses = adapter.interpretResponse({price: null, ad: 'great ad'}); + const responses = adapter.interpretResponse({ price: null, ad: 'great ad' }); expect(responses).to.be.empty; }); @@ -793,9 +795,9 @@ describe('TwistDigitalBidAdapter', function () { const userId = (function () { switch (idSystemProvider) { case 'lipb': - return {lipbid: id}; + return { lipbid: id }; case 'id5id': - return {uid: id}; + return { uid: id }; default: return id; } @@ -816,7 +818,7 @@ describe('TwistDigitalBidAdapter', function () { bid.userIdAsEids = [ { "source": "audigent.com", - "uids": [{"id": "fakeidi6j6dlc6e"}] + "uids": [{ "id": "fakeidi6j6dlc6e" }] } ] const requests = adapter.buildRequests([bid], BIDDER_REQUEST); @@ -827,11 +829,11 @@ describe('TwistDigitalBidAdapter', function () { bid.userIdAsEids = [ { "source": "audigent.com", - "uids": [{"id": "fakeidi6j6dlc6e"}] + "uids": [{ "id": "fakeidi6j6dlc6e" }] }, { "source": "rwdcntrl.net", - "uids": [{"id": "fakeid6f35197d5c", "atype": 1}] + "uids": [{ "id": "fakeid6f35197d5c", "atype": 1 }] } ] const requests = adapter.buildRequests([bid], BIDDER_REQUEST); @@ -846,7 +848,7 @@ describe('TwistDigitalBidAdapter', function () { eids: [ { "source": "pubcid.org", - "uids": [{"id": "fakeid8888dlc6e"}] + "uids": [{ "id": "fakeid8888dlc6e" }] } ] } @@ -861,11 +863,11 @@ describe('TwistDigitalBidAdapter', function () { eids: [ { "source": "pubcid.org", - "uids": [{"id": "fakeid8888dlc6e"}] + "uids": [{ "id": "fakeid8888dlc6e" }] }, { "source": "adserver.org", - "uids": [{"id": "fakeid495ff1"}] + "uids": [{ "id": "fakeid495ff1" }] } ] } @@ -878,18 +880,18 @@ describe('TwistDigitalBidAdapter', function () { describe('alternate param names extractors', function () { it('should return undefined when param not supported', function () { - const cid = extractCID({'c_id': '1'}); - const pid = extractPID({'p_id': '1'}); - const subDomain = extractSubDomain({'sub_domain': 'prebid'}); + const cid = extractCID({ 'c_id': '1' }); + const pid = extractPID({ 'p_id': '1' }); + const subDomain = extractSubDomain({ 'sub_domain': 'prebid' }); expect(cid).to.be.undefined; expect(pid).to.be.undefined; expect(subDomain).to.be.undefined; }); it('should return value when param supported', function () { - const cid = extractCID({'cID': '1'}); - const pid = extractPID({'Pid': '2'}); - const subDomain = extractSubDomain({'subDOMAIN': 'prebid'}); + const cid = extractCID({ 'cID': '1' }); + const pid = extractPID({ 'Pid': '2' }); + const subDomain = extractSubDomain({ 'subDOMAIN': 'prebid' }); expect(cid).to.be.equal('1'); expect(pid).to.be.equal('2'); expect(subDomain).to.be.equal('prebid'); @@ -962,7 +964,7 @@ describe('TwistDigitalBidAdapter', function () { now }); setStorageItem(storage, 'myKey', 2020); - const {value, created} = getStorageItem(storage, 'myKey'); + const { value, created } = getStorageItem(storage, 'myKey'); expect(created).to.be.equal(now); expect(value).to.be.equal(2020); expect(typeof value).to.be.equal('number'); @@ -978,8 +980,8 @@ describe('TwistDigitalBidAdapter', function () { }); it('should parse JSON value', function () { - const data = JSON.stringify({event: 'send'}); - const {event} = tryParseJSON(data); + const data = JSON.stringify({ event: 'send' }); + const { event } = tryParseJSON(data); expect(event).to.be.equal('send'); }); diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index b7ad994dc96..d8326ab64c8 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -1,9 +1,9 @@ -import {expect} from 'chai'; -import {spec} from 'modules/undertoneBidAdapter.js'; -import {BANNER, VIDEO} from '../../../src/mediaTypes.js'; -import {deepClone, getWinDimensions} from '../../../src/utils.js'; +import { expect } from 'chai'; +import { spec } from 'modules/undertoneBidAdapter.js'; +import { BANNER, VIDEO } from '../../../src/mediaTypes.js'; +import { deepClone, getWinDimensions } from '../../../src/utils.js'; import * as adUnits from 'src/utils/adUnits'; -import {getAdUnitElement} from 'src/utils/adUnits'; +import { getAdUnitElement } from 'src/utils/adUnits'; const URL = 'https://hb.undertone.com/hb'; const BIDDER_CODE = 'undertone'; @@ -155,7 +155,7 @@ const bidReqUserIds = [{ userId: { idl_env: '1111', tdid: '123456', - digitrustid: {data: {id: 'DTID', keyv: 4, privacy: {optout: false}, producer: 'ABC', version: 2}}, + digitrustid: { data: { id: 'DTID', keyv: 4, privacy: { optout: false }, producer: 'ABC', version: 2 } }, id5id: { uid: '1111' } } }, @@ -527,12 +527,12 @@ describe('Undertone Adapter', () => { describe('interpretResponse', () => { it('should build bid array', () => { - const result = spec.interpretResponse({body: bidResponse}); + const result = spec.interpretResponse({ body: bidResponse }); expect(result.length).to.equal(1); }); it('should have all relevant fields', () => { - const result = spec.interpretResponse({body: bidResponse}); + const result = spec.interpretResponse({ body: bidResponse }); const bid = result[0]; expect(bid.requestId).to.equal('263be71e91dd9d'); @@ -547,8 +547,8 @@ describe('Undertone Adapter', () => { }); it('should return empty array when response is incorrect', () => { - expect(spec.interpretResponse({body: {}}).length).to.equal(0); - expect(spec.interpretResponse({body: []}).length).to.equal(0); + expect(spec.interpretResponse({ body: {} }).length).to.equal(0); + expect(spec.interpretResponse({ body: [] }).length).to.equal(0); }); it('should only use valid bid responses', () => { @@ -556,7 +556,7 @@ describe('Undertone Adapter', () => { }); it('should detect video response', () => { - const videoResult = spec.interpretResponse({body: bidVideoResponse}); + const videoResult = spec.interpretResponse({ body: bidVideoResponse }); const vbid = videoResult[0]; expect(vbid.mediaType).to.equal('video'); @@ -575,7 +575,7 @@ describe('Undertone Adapter', () => { }, { name: 'with iframe and gdpr on', - arguments: [{ iframeEnabled: true, pixelEnabled: true }, {}, {gdprApplies: true, consentString: '234234'}], + arguments: [{ iframeEnabled: true, pixelEnabled: true }, {}, { gdprApplies: true, consentString: '234234' }], expect: { type: 'iframe', pixels: ['https://cdn.undertone.com/js/usersync.html?gdpr=1&gdprstr=234234'] @@ -591,7 +591,7 @@ describe('Undertone Adapter', () => { }, { name: 'with iframe and no gdpr off or ccpa', - arguments: [{ iframeEnabled: true, pixelEnabled: true }, {}, {gdprApplies: false}], + arguments: [{ iframeEnabled: true, pixelEnabled: true }, {}, { gdprApplies: false }], expect: { type: 'iframe', pixels: ['https://cdn.undertone.com/js/usersync.html?gdpr=0&gdprstr='] @@ -599,7 +599,7 @@ describe('Undertone Adapter', () => { }, { name: 'with iframe and gdpr and ccpa', - arguments: [{ iframeEnabled: true, pixelEnabled: true }, {}, {gdprApplies: true, consentString: '234234'}, 'YN12'], + arguments: [{ iframeEnabled: true, pixelEnabled: true }, {}, { gdprApplies: true, consentString: '234234' }, 'YN12'], expect: { type: 'iframe', pixels: ['https://cdn.undertone.com/js/usersync.html?gdpr=1&gdprstr=234234&ccpa=YN12'] @@ -616,7 +616,7 @@ describe('Undertone Adapter', () => { }, { name: 'with pixels and gdpr on', - arguments: [{ pixelEnabled: true }, {}, {gdprApplies: true, consentString: '234234'}], + arguments: [{ pixelEnabled: true }, {}, { gdprApplies: true, consentString: '234234' }], expect: { type: 'image', pixels: ['https://usr.undertone.com/userPixel/syncOne?id=1&of=2&gdpr=1&gdprstr=234234', @@ -634,7 +634,7 @@ describe('Undertone Adapter', () => { }, { name: 'with pixels and gdpr off', - arguments: [{ pixelEnabled: true }, {}, {gdprApplies: false}], + arguments: [{ pixelEnabled: true }, {}, { gdprApplies: false }], expect: { type: 'image', pixels: ['https://usr.undertone.com/userPixel/syncOne?id=1&of=2&gdpr=0&gdprstr=', @@ -643,7 +643,7 @@ describe('Undertone Adapter', () => { }, { name: 'with pixels and gdpr and ccpa on', - arguments: [{ pixelEnabled: true }, {}, {gdprApplies: true, consentString: '234234'}, 'YN12'], + arguments: [{ pixelEnabled: true }, {}, { gdprApplies: true, consentString: '234234' }, 'YN12'], expect: { type: 'image', pixels: ['https://usr.undertone.com/userPixel/syncOne?id=1&of=2&gdpr=1&gdprstr=234234&ccpa=YN12', diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js index 77aaeb8a458..08b68058cd2 100644 --- a/test/spec/modules/vidazooBidAdapter_spec.js +++ b/test/spec/modules/vidazooBidAdapter_spec.js @@ -1,4 +1,4 @@ -import {expect} from 'chai'; +import { expect } from 'chai'; import { spec as adapter, storage, @@ -19,12 +19,12 @@ import { getVidazooSessionId } from 'libraries/vidazooUtils/bidderUtils.js' import * as utils from 'src/utils.js'; -import {version} from 'package.json'; -import {useFakeTimers} from 'sinon'; -import {BANNER, VIDEO} from '../../../src/mediaTypes.js'; -import {config} from '../../../src/config.js'; -import {deepSetValue} from 'src/utils.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; +import { version } from 'package.json'; +import { useFakeTimers } from 'sinon'; +import { BANNER, VIDEO } from '../../../src/mediaTypes.js'; +import { config } from '../../../src/config.js'; +import { deepSetValue } from 'src/utils.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; export const TEST_ID_SYSTEMS = ['criteoId', 'id5id', 'idl_env', 'lipb', 'netId', 'pubcid', 'tdid', 'pubProvidedId']; @@ -107,9 +107,9 @@ const ORTB2_DEVICE = { 'version': ['8', '0', '0'] }, 'browsers': [ - {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']}, - {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']}, - {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']} + { 'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0'] }, + { 'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119'] }, + { 'brand': 'Chromium', 'version': ['109', '0', '5414', '119'] } ], 'mobile': 1, 'model': 'SM-G955U', @@ -126,7 +126,7 @@ const ORTB2_DEVICE = { model: 'iPhone 12 Pro Max', os: 'iOS', osv: '17.4', - ext: {fiftyonedegrees_deviceId: '17595-133085-133468-18092'}, + ext: { fiftyonedegrees_deviceId: '17595-133085-133468-18092' }, }; const BIDDER_REQUEST = { @@ -153,8 +153,8 @@ const BIDDER_REQUEST = { 'segtax': 7 }, 'segments': [ - {'id': 'segId1'}, - {'id': 'segId2'} + { 'id': 'segId1' }, + { 'id': 'segId2' } ] }] } @@ -168,9 +168,9 @@ const BIDDER_REQUEST = { user: { data: [ { - ext: {segtax: 600, segclass: '1'}, + ext: { segtax: 600, segclass: '1' }, name: 'example.com', - segment: [{id: '243'}], + segment: [{ id: '243' }], }, ], }, @@ -225,22 +225,22 @@ const VIDEO_SERVER_RESPONSE = { const ORTB2_OBJ = { "device": ORTB2_DEVICE, - "regs": {"coppa": 0, "gpp": "gpp_string", "gpp_sid": [7]}, + "regs": { "coppa": 0, "gpp": "gpp_string", "gpp_sid": [7] }, "site": { "cat": ["IAB2"], "content": { "data": [{ - "ext": {"segtax": 7}, + "ext": { "segtax": 7 }, "name": "example.com", - "segments": [{"id": "segId1"}, {"id": "segId2"}] + "segments": [{ "id": "segId1" }, { "id": "segId2" }] }], "language": "en" }, "pagecat": ["IAB2-2"] }, - "source": {"ext": {"omidpn": "MyIntegrationPartner", "omidpv": "7.1"}}, + "source": { "ext": { "omidpn": "MyIntegrationPartner", "omidpv": "7.1" } }, "user": { - "data": [{"ext": {"segclass": "1", "segtax": 600}, "name": "example.com", "segment": [{"id": "243"}]}] + "data": [{ "ext": { "segclass": "1", "segtax": 600 }, "name": "example.com", "segment": [{ "id": "243" }] }] } }; @@ -375,9 +375,9 @@ describe('VidazooBidAdapter', function () { 'version': ['8', '0', '0'] }, 'browsers': [ - {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']}, - {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']}, - {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']} + { 'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0'] }, + { 'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119'] }, + { 'brand': 'Chromium', 'version': ['109', '0', '5414', '119'] } ], 'mobile': 1, 'model': 'SM-G955U', @@ -393,15 +393,15 @@ describe('VidazooBidAdapter', function () { 'segtax': 7 }, 'segments': [ - {'id': 'segId1'}, - {'id': 'segId2'} + { 'id': 'segId1' }, + { 'id': 'segId2' } ] }], userData: [ { - ext: {segtax: 600, segclass: '1'}, + ext: { segtax: 600, segclass: '1' }, name: 'example.com', - segment: [{id: '243'}], + segment: [{ id: '243' }], }, ], uniqueDealId: `${hashUrl}_${Date.now().toString()}`, @@ -462,9 +462,9 @@ describe('VidazooBidAdapter', function () { 'version': ['8', '0', '0'] }, 'browsers': [ - {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']}, - {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']}, - {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']} + { 'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0'] }, + { 'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119'] }, + { 'brand': 'Chromium', 'version': ['109', '0', '5414', '119'] } ], 'mobile': 1, 'model': 'SM-G955U', @@ -506,15 +506,15 @@ describe('VidazooBidAdapter', function () { 'segtax': 7 }, 'segments': [ - {'id': 'segId1'}, - {'id': 'segId2'} + { 'id': 'segId1' }, + { 'id': 'segId2' } ] }], userData: [ { - ext: {segtax: 600, segclass: '1'}, + ext: { segtax: 600, segclass: '1' }, name: 'example.com', - segment: [{id: '243'}], + segment: [{ id: '243' }], }, ], webSessionId: webSessionId @@ -558,9 +558,9 @@ describe('VidazooBidAdapter', function () { 'version': ['8', '0', '0'] }, 'browsers': [ - {'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0']}, - {'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119']}, - {'brand': 'Chromium', 'version': ['109', '0', '5414', '119']} + { 'brand': 'Not_A Brand', 'version': ['99', '0', '0', '0'] }, + { 'brand': 'Google Chrome', 'version': ['109', '0', '5414', '119'] }, + { 'brand': 'Chromium', 'version': ['109', '0', '5414', '119'] } ], 'mobile': 1, 'model': 'SM-G955U', @@ -600,15 +600,15 @@ describe('VidazooBidAdapter', function () { 'segtax': 7 }, 'segments': [ - {'id': 'segId1'}, - {'id': 'segId2'} + { 'id': 'segId1' }, + { 'id': 'segId2' } ] }], userData: [ { - ext: {segtax: 600, segclass: '1'}, + ext: { segtax: 600, segclass: '1' }, name: 'example.com', - segment: [{id: '243'}], + segment: [{ id: '243' }], }, ], webSessionId: webSessionId @@ -626,10 +626,12 @@ describe('VidazooBidAdapter', function () { expect(requests[0]).to.deep.equal({ method: 'POST', url: `${createDomain(SUB_DOMAIN)}/prebid/multi/59db6b3b4ffaa70004f45cdc`, - data: {bids: [ - {...REQUEST_DATA, ortb2: ORTB2_OBJ, ortb2Imp: BID.ortb2Imp}, - {...REQUEST_DATA2, ortb2: ORTB2_OBJ, ortb2Imp: BID.ortb2Imp} - ]} + data: { + bids: [ + { ...REQUEST_DATA, ortb2: ORTB2_OBJ, ortb2Imp: BID.ortb2Imp }, + { ...REQUEST_DATA2, ortb2: ORTB2_OBJ, ortb2Imp: BID.ortb2Imp } + ] + } }); }); @@ -668,7 +670,7 @@ describe('VidazooBidAdapter', function () { describe('getUserSyncs', function () { it('should have valid user sync with iframeEnabled', function () { - const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]); + const result = adapter.getUserSyncs({ iframeEnabled: true }, [SERVER_RESPONSE]); expect(result).to.deep.equal([{ type: 'iframe', @@ -677,7 +679,7 @@ describe('VidazooBidAdapter', function () { }); it('should have valid user sync with cid on response', function () { - const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]); + const result = adapter.getUserSyncs({ iframeEnabled: true }, [SERVER_RESPONSE]); expect(result).to.deep.equal([{ type: 'iframe', url: 'https://sync.cootlogix.com/api/sync/iframe/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy=&coppa=0' @@ -685,7 +687,7 @@ describe('VidazooBidAdapter', function () { }); it('should have valid user sync with pixelEnabled', function () { - const result = adapter.getUserSyncs({pixelEnabled: true}, [SERVER_RESPONSE]); + const result = adapter.getUserSyncs({ pixelEnabled: true }, [SERVER_RESPONSE]); expect(result).to.deep.equal([{ 'url': 'https://sync.cootlogix.com/api/sync/image/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy=&coppa=0', @@ -697,7 +699,7 @@ describe('VidazooBidAdapter', function () { config.setConfig({ coppa: 1 }); - const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]); + const result = adapter.getUserSyncs({ iframeEnabled: true }, [SERVER_RESPONSE]); expect(result).to.deep.equal([{ type: 'iframe', url: 'https://sync.cootlogix.com/api/sync/iframe/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy=&coppa=1' @@ -712,12 +714,12 @@ describe('VidazooBidAdapter', function () { }); it('should return empty array when there is no ad', function () { - const responses = adapter.interpretResponse({price: 1, ad: ''}); + const responses = adapter.interpretResponse({ price: 1, ad: '' }); expect(responses).to.be.empty; }); it('should return empty array when there is no price', function () { - const responses = adapter.interpretResponse({price: null, ad: 'great ad'}); + const responses = adapter.interpretResponse({ price: null, ad: 'great ad' }); expect(responses).to.be.empty; }); @@ -813,9 +815,9 @@ describe('VidazooBidAdapter', function () { const userId = (function () { switch (idSystemProvider) { case 'lipb': - return {lipbid: id}; + return { lipbid: id }; case 'id5id': - return {uid: id}; + return { uid: id }; default: return id; } @@ -836,7 +838,7 @@ describe('VidazooBidAdapter', function () { bid.userIdAsEids = [ { "source": "audigent.com", - "uids": [{"id": "fakeidi6j6dlc6e"}] + "uids": [{ "id": "fakeidi6j6dlc6e" }] } ] const requests = adapter.buildRequests([bid], BIDDER_REQUEST); @@ -847,11 +849,11 @@ describe('VidazooBidAdapter', function () { bid.userIdAsEids = [ { "source": "audigent.com", - "uids": [{"id": "fakeidi6j6dlc6e"}] + "uids": [{ "id": "fakeidi6j6dlc6e" }] }, { "source": "rwdcntrl.net", - "uids": [{"id": "fakeid6f35197d5c", "atype": 1}] + "uids": [{ "id": "fakeid6f35197d5c", "atype": 1 }] } ] const requests = adapter.buildRequests([bid], BIDDER_REQUEST); @@ -866,7 +868,7 @@ describe('VidazooBidAdapter', function () { eids: [ { "source": "pubcid.org", - "uids": [{"id": "fakeid8888dlc6e"}] + "uids": [{ "id": "fakeid8888dlc6e" }] } ] } @@ -881,11 +883,11 @@ describe('VidazooBidAdapter', function () { eids: [ { "source": "pubcid.org", - "uids": [{"id": "fakeid8888dlc6e"}] + "uids": [{ "id": "fakeid8888dlc6e" }] }, { "source": "adserver.org", - "uids": [{"id": "fakeid495ff1"}] + "uids": [{ "id": "fakeid495ff1" }] } ] } @@ -898,18 +900,18 @@ describe('VidazooBidAdapter', function () { describe('alternate param names extractors', function () { it('should return undefined when param not supported', function () { - const cid = extractCID({'c_id': '1'}); - const pid = extractPID({'p_id': '1'}); - const subDomain = extractSubDomain({'sub_domain': 'prebid'}); + const cid = extractCID({ 'c_id': '1' }); + const pid = extractPID({ 'p_id': '1' }); + const subDomain = extractSubDomain({ 'sub_domain': 'prebid' }); expect(cid).to.be.undefined; expect(pid).to.be.undefined; expect(subDomain).to.be.undefined; }); it('should return value when param supported', function () { - const cid = extractCID({'cID': '1'}); - const pid = extractPID({'Pid': '2'}); - const subDomain = extractSubDomain({'subDOMAIN': 'prebid'}); + const cid = extractCID({ 'cID': '1' }); + const pid = extractPID({ 'Pid': '2' }); + const subDomain = extractSubDomain({ 'subDOMAIN': 'prebid' }); expect(cid).to.be.equal('1'); expect(pid).to.be.equal('2'); expect(subDomain).to.be.equal('prebid'); @@ -1022,7 +1024,7 @@ describe('VidazooBidAdapter', function () { now }); setStorageItem(storage, 'myKey', 2020); - const {value, created} = getStorageItem(storage, 'myKey'); + const { value, created } = getStorageItem(storage, 'myKey'); expect(created).to.be.equal(now); expect(value).to.be.equal(2020); expect(typeof value).to.be.equal('number'); @@ -1038,8 +1040,8 @@ describe('VidazooBidAdapter', function () { }); it('should parse JSON value', function () { - const data = JSON.stringify({event: 'send'}); - const {event} = tryParseJSON(data); + const data = JSON.stringify({ event: 'send' }); + const { event } = tryParseJSON(data); expect(event).to.be.equal('send'); }); diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index db7c01d7067..218bc364a0c 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -7,7 +7,7 @@ import { makeSlot } from '../integration/faker/googletag.js'; import { mergeDeep } from '../../../src/utils.js'; import { setConfig as setCurrencyConfig } from '../../../modules/currency.js'; import { addFPDToBidderRequest } from '../../helpers/fpd.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; import * as adUnits from 'src/utils/adUnits'; describe('VisxAdapter', function () { @@ -110,15 +110,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -140,8 +140,8 @@ describe('VisxAdapter', function () { const schainObject = { ver: '1.0', nodes: [ - {asi: 'exchange2.com', sid: 'abcd', hp: 1}, - {asi: 'exchange1.com', sid: '1234!abcd', hp: 1, name: 'publisher, Inc.', domain: 'publisher.com'} + { asi: 'exchange2.com', sid: 'abcd', hp: 1 }, + { asi: 'exchange1.com', sid: '1234!abcd', hp: 1, name: 'publisher, Inc.', domain: 'publisher.com' } ] }; const bidRequests = [ @@ -202,18 +202,18 @@ describe('VisxAdapter', function () { const expectedFullImps = [{ 'id': '30b31c1838de1e', - 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, - 'ext': {'bidder': {'uid': 903535, 'adslotExists': false}} + 'banner': { 'format': [{ 'w': 300, 'h': 250 }, { 'w': 300, 'h': 600 }] }, + 'ext': { 'bidder': { 'uid': 903535, 'adslotExists': false } } }, { 'id': '3150ccb55da321', - 'banner': {'format': [{'w': 728, 'h': 90}, {'w': 300, 'h': 250}]}, - 'ext': {'bidder': {'uid': 903535, 'adslotExists': false}} + 'banner': { 'format': [{ 'w': 728, 'h': 90 }, { 'w': 300, 'h': 250 }] }, + 'ext': { 'bidder': { 'uid': 903535, 'adslotExists': false } } }, { 'id': '42dbe3a7168a6a', - 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, - 'ext': {'bidder': {'uid': 903536, 'adslotExists': false}} + 'banner': { 'format': [{ 'w': 300, 'h': 250 }, { 'w': 300, 'h': 600 }] }, + 'ext': { 'bidder': { 'uid': 903536, 'adslotExists': false } } }, { 'id': '39a4e3a7168a6a', @@ -225,7 +225,7 @@ describe('VisxAdapter', function () { 'minduration': 5, 'maxduration': 30 }, - 'ext': {'bidder': {'uid': 903537}} + 'ext': { 'bidder': { 'uid': 903537 } } }]; before(() => { @@ -261,7 +261,7 @@ describe('VisxAdapter', function () { 'imp': [expectedFullImps[0]], 'tmax': 3000, 'cur': ['EUR'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'source': { 'ext': { 'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$' } }, 'device': { 'w': 1259, 'h': 934, @@ -276,15 +276,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -316,7 +316,7 @@ describe('VisxAdapter', function () { 'imp': expectedFullImps, 'tmax': 3000, 'cur': ['EUR'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'source': { 'ext': { 'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$' } }, 'device': { 'w': 1259, 'h': 934, @@ -331,15 +331,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -359,7 +359,7 @@ describe('VisxAdapter', function () { }); it('should add currency from currency.bidderCurrencyDefault', function () { - config.setConfig({currency: {bidderCurrencyDefault: {visx: 'GBP'}}}) + config.setConfig({ currency: { bidderCurrencyDefault: { visx: 'GBP' } } }) const request = spec.buildRequests(bidRequests, bidderRequest); const payload = parseRequest(request.url); expect(payload).to.be.an('object'); @@ -372,7 +372,7 @@ describe('VisxAdapter', function () { 'imp': expectedFullImps, 'tmax': 3000, 'cur': ['GBP'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'source': { 'ext': { 'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$' } }, 'device': { 'w': 1259, 'h': 934, @@ -387,15 +387,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -432,7 +432,7 @@ describe('VisxAdapter', function () { }); it('if gdprConsent is present payload must have gdpr params', function () { - const request = spec.buildRequests(bidRequests, Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: true}}, bidderRequest)); + const request = spec.buildRequests(bidRequests, Object.assign({ gdprConsent: { consentString: 'AAA', gdprApplies: true } }, bidderRequest)); const postData = request.data; expect(postData).to.be.an('object'); @@ -441,7 +441,7 @@ describe('VisxAdapter', function () { 'imp': expectedFullImps, 'tmax': 3000, 'cur': ['EUR'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'source': { 'ext': { 'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$' } }, 'device': { 'w': 1259, 'h': 934, @@ -456,15 +456,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -485,12 +485,12 @@ describe('VisxAdapter', function () { }, 'page': 'http://localhost:9999/integrationExamples/gpt/hello_world.html' }, - 'user': {'ext': {'consent': 'AAA'}}, + 'user': { 'ext': { 'consent': 'AAA' } }, }); }); it('if gdprApplies is false gdpr_applies must be 0', function () { - const request = spec.buildRequests(bidRequests, Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: false}}, bidderRequest)); + const request = spec.buildRequests(bidRequests, Object.assign({ gdprConsent: { consentString: 'AAA', gdprApplies: false } }, bidderRequest)); const postData = request.data; expect(postData).to.be.an('object'); @@ -499,7 +499,7 @@ describe('VisxAdapter', function () { 'imp': expectedFullImps, 'tmax': 3000, 'cur': ['EUR'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'source': { 'ext': { 'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$' } }, 'device': { 'w': 1259, 'h': 934, @@ -514,15 +514,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -538,13 +538,13 @@ describe('VisxAdapter', function () { }, 'page': 'http://localhost:9999/integrationExamples/gpt/hello_world.html' }, - 'user': {'ext': {'consent': 'AAA'}}, - 'regs': {'ext': {'gdpr': 0}} + 'user': { 'ext': { 'consent': 'AAA' } }, + 'regs': { 'ext': { 'gdpr': 0 } } }); }); it('if gdprApplies is undefined gdpr_applies must be 1', function () { - const request = spec.buildRequests(bidRequests, Object.assign({gdprConsent: {consentString: 'AAA'}}, bidderRequest)); + const request = spec.buildRequests(bidRequests, Object.assign({ gdprConsent: { consentString: 'AAA' } }, bidderRequest)); const postData = request.data; expect(postData).to.be.an('object'); @@ -553,7 +553,7 @@ describe('VisxAdapter', function () { 'imp': expectedFullImps, 'tmax': 3000, 'cur': ['EUR'], - 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'source': { 'ext': { 'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$' } }, 'device': { 'w': 1259, 'h': 934, @@ -568,15 +568,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -592,14 +592,14 @@ describe('VisxAdapter', function () { }, 'page': 'http://localhost:9999/integrationExamples/gpt/hello_world.html' }, - 'user': {'ext': {'consent': 'AAA'}}, - 'regs': {'ext': {'gdpr': 1}} + 'user': { 'ext': { 'consent': 'AAA' } }, + 'regs': { 'ext': { 'gdpr': 1 } } }); }); it('if schain is present payload must have schain param', function () { const schainBidRequests = [ - Object.assign({ortb2: {source: {ext: {schain: schainObject}}}}, bidRequests[0]), + Object.assign({ ortb2: { source: { ext: { schain: schainObject } } } }, bidRequests[0]), bidRequests[1], bidRequests[2] ]; @@ -636,15 +636,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -684,12 +684,14 @@ describe('VisxAdapter', function () { } ]; const userIdBidRequests = [ - Object.assign({userId: { - tdid: '111', - id5id: { uid: '222' }, - digitrustid: {data: {id: 'DTID', keyv: 4, privacy: {optout: false}, producer: 'ABC', version: 2}} - }, - userIdAsEids: eids}, bidRequests[0]), + Object.assign({ + userId: { + tdid: '111', + id5id: { uid: '222' }, + digitrustid: { data: { id: 'DTID', keyv: 4, privacy: { optout: false }, producer: 'ABC', version: 2 } } + }, + userIdAsEids: eids + }, bidRequests[0]), bidRequests[1], bidRequests[2] ]; @@ -722,15 +724,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -746,7 +748,7 @@ describe('VisxAdapter', function () { }, 'page': 'http://localhost:9999/integrationExamples/gpt/hello_world.html' }, - 'user': {'ext': {'eids': eids}} + 'user': { 'ext': { 'eids': eids } } }); }); @@ -780,15 +782,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -849,15 +851,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -925,8 +927,8 @@ describe('VisxAdapter', function () { 'id': '22edbae2733bf6', 'imp': [{ 'id': '39aff3a7169a6a', - 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, - 'ext': {'bidder': {'uid': 903538, 'adslotExists': false}} + 'banner': { 'format': [{ 'w': 300, 'h': 250 }, { 'w': 300, 'h': 600 }] }, + 'ext': { 'bidder': { 'uid': 903538, 'adslotExists': false } } }], 'tmax': 3000, 'cur': ['EUR'], @@ -1014,15 +1016,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -1070,7 +1072,7 @@ describe('VisxAdapter', function () { before(function() { sandbox = sinon.createSandbox(); - sandbox.stub(adUnits, 'getAdUnitElement').callsFake(({adUnitCode}) => { + sandbox.stub(adUnits, 'getAdUnitElement').callsFake(({ adUnitCode }) => { return ['visx-adunit-code-1', 'visx-adunit-code-2'].includes(adUnitCode); }) @@ -1104,8 +1106,8 @@ describe('VisxAdapter', function () { 'id': '22edbae2733bf6', 'imp': [{ 'id': '30b31c1838de1e', - 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, - 'ext': {'bidder': {'uid': 903535, 'adslotExists': true}} + 'banner': { 'format': [{ 'w': 300, 'h': 250 }, { 'w': 300, 'h': 600 }] }, + 'ext': { 'bidder': { 'uid': 903535, 'adslotExists': true } } }], 'tmax': 3000, 'cur': ['EUR'], @@ -1129,15 +1131,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -1157,7 +1159,7 @@ describe('VisxAdapter', function () { }); it('should find ad slot by ad unit code as adUnitPath', function () { - makeSlot({code: 'visx-adunit-code-2', divId: 'visx-adunit-element-2'}); + makeSlot({ code: 'visx-adunit-code-2', divId: 'visx-adunit-element-2' }); const request = spec.buildRequests([bidRequests[1]], bidderRequest); const payload = parseRequest(request.url); @@ -1170,8 +1172,8 @@ describe('VisxAdapter', function () { 'id': '22edbae2733bf6', 'imp': [{ 'id': '30b31c1838de1e', - 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, - 'ext': {'bidder': {'uid': 903535, 'adslotExists': true}} + 'banner': { 'format': [{ 'w': 300, 'h': 250 }, { 'w': 300, 'h': 600 }] }, + 'ext': { 'bidder': { 'uid': 903535, 'adslotExists': true } } }], 'tmax': 3000, 'cur': ['EUR'], @@ -1195,15 +1197,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -1225,14 +1227,14 @@ describe('VisxAdapter', function () { describe('interpretResponse', function () { const responses = [ - {'bid': [{'price': 1.15, 'impid': '300bfeb0d71a5b', 'adm': '
test content 1
', 'auid': 903535, 'crid': 'visx_1', 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'adomain': ['some_domain.com'], 'ext': {'prebid': {'targeting': {'hb_visx_product': 'understitial', 'hb_visx_width': 300, 'hb_visx_height': 250}}}}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'impid': '4dff80cc4ee346', 'adm': '
test content 2
', 'auid': 903536, 'crid': 'visx_2', 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'impid': '5703af74d0472a', 'adm': '
test content 3
', 'auid': 903535, 'crid': 'visx_3', 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0, 'impid': '300bfeb0d7190gf', 'auid': 903537, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, - {'bid': [{'price': 0, 'adm': '
test content 5
', 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + { 'bid': [{ 'price': 1.15, 'impid': '300bfeb0d71a5b', 'adm': '
test content 1
', 'auid': 903535, 'crid': 'visx_1', 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'adomain': ['some_domain.com'], 'ext': { 'prebid': { 'targeting': { 'hb_visx_product': 'understitial', 'hb_visx_width': 300, 'hb_visx_height': 250 } } } }], 'seat': '1' }, + { 'bid': [{ 'price': 0.5, 'impid': '4dff80cc4ee346', 'adm': '
test content 2
', 'auid': 903536, 'crid': 'visx_2', 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner' }], 'seat': '1' }, + { 'bid': [{ 'price': 0.15, 'impid': '5703af74d0472a', 'adm': '
test content 3
', 'auid': 903535, 'crid': 'visx_3', 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner' }], 'seat': '1' }, + { 'bid': [{ 'price': 0, 'impid': '300bfeb0d7190gf', 'auid': 903537, 'h': 250, 'w': 300, 'cur': 'EUR' }], 'seat': '1' }, + { 'bid': [{ 'price': 0, 'adm': '
test content 5
', 'h': 250, 'w': 300, 'cur': 'EUR' }], 'seat': '1' }, undefined, - {'bid': [], 'seat': '1'}, - {'seat': '1'}, + { 'bid': [], 'seat': '1' }, + { 'seat': '1' }, ]; it('should get correct bid response', function () { @@ -1281,7 +1283,7 @@ describe('VisxAdapter', function () { } ]; - const result = spec.interpretResponse({'body': {'seatbid': [responses[0]]}}, request); + const result = spec.interpretResponse({ 'body': { 'seatbid': [responses[0]] } }, request); expect(result).to.deep.equal(expectedResponse); }); @@ -1385,7 +1387,7 @@ describe('VisxAdapter', function () { } ]; - const result = spec.interpretResponse({'body': {'seatbid': responses.slice(0, 3)}}, request); + const result = spec.interpretResponse({ 'body': { 'seatbid': responses.slice(0, 3) } }, request); expect(result).to.deep.equal(expectedResponse); }); @@ -1437,8 +1439,8 @@ describe('VisxAdapter', function () { ]; const response = Object.assign({}, responses[0]); - response.bid = [Object.assign({}, response.bid[0], {'cur': 'PLN'})]; - const result = spec.interpretResponse({'body': {'seatbid': [response]}}, request); + response.bid = [Object.assign({}, response.bid[0], { 'cur': 'PLN' })]; + const result = spec.interpretResponse({ 'body': { 'seatbid': [response] } }, request); expect(result).to.deep.equal(expectedResponse); getConfigStub.restore(); }); @@ -1480,17 +1482,17 @@ describe('VisxAdapter', function () { } ]; const request = spec.buildRequests(bidRequests); - const result = spec.interpretResponse({'body': {'seatbid': responses.slice(3)}}, request); + const result = spec.interpretResponse({ 'body': { 'seatbid': responses.slice(3) } }, request); expect(result.length).to.equal(0); }); it('complicated case', function () { const fullResponse = [ - {'bid': [{'price': 1.15, 'impid': '2164be6358b9', 'adm': '
test content 1
', 'auid': 903535, 'crid': 'visx_1', 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'adomain': ['some_domain.com']}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'impid': '4e111f1b66e4', 'adm': '
test content 2
', 'auid': 903536, 'crid': 'visx_1', 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'impid': '26d6f897b516', 'adm': '
test content 3
', 'auid': 903535, 'crid': 'visx_1', 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'impid': '326bde7fbf69', 'adm': '
test content 4
', 'auid': 903535, 'crid': 'visx_1', 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'impid': '1751cd90161', 'adm': '
test content 5
', 'auid': 903536, 'crid': 'visx_1', 'h': 600, 'w': 350, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + { 'bid': [{ 'price': 1.15, 'impid': '2164be6358b9', 'adm': '
test content 1
', 'auid': 903535, 'crid': 'visx_1', 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'adomain': ['some_domain.com'] }], 'seat': '1' }, + { 'bid': [{ 'price': 0.5, 'impid': '4e111f1b66e4', 'adm': '
test content 2
', 'auid': 903536, 'crid': 'visx_1', 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner' }], 'seat': '1' }, + { 'bid': [{ 'price': 0.15, 'impid': '26d6f897b516', 'adm': '
test content 3
', 'auid': 903535, 'crid': 'visx_1', 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner' }], 'seat': '1' }, + { 'bid': [{ 'price': 0.15, 'impid': '326bde7fbf69', 'adm': '
test content 4
', 'auid': 903535, 'crid': 'visx_1', 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner' }], 'seat': '1' }, + { 'bid': [{ 'price': 0.5, 'impid': '1751cd90161', 'adm': '
test content 5
', 'auid': 903536, 'crid': 'visx_1', 'h': 600, 'w': 350, 'cur': 'EUR', 'mediaType': 'banner' }], 'seat': '1' }, ]; const bidRequests = [ { @@ -1633,14 +1635,14 @@ describe('VisxAdapter', function () { } ]; - const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + const result = spec.interpretResponse({ 'body': { 'seatbid': fullResponse } }, request); expect(result).to.deep.equal(expectedResponse); }); it('dublicate uids and sizes in one slot', function () { const fullResponse = [ - {'bid': [{'price': 1.15, 'impid': '5126e301f4be', 'adm': '
test content 1
', 'auid': 903535, 'crid': 'visx_1', 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'impid': '57b2ebe70e16', 'adm': '
test content 2
', 'auid': 903535, 'crid': 'visx_1', 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + { 'bid': [{ 'price': 1.15, 'impid': '5126e301f4be', 'adm': '
test content 1
', 'auid': 903535, 'crid': 'visx_1', 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner' }], 'seat': '1' }, + { 'bid': [{ 'price': 0.5, 'impid': '57b2ebe70e16', 'adm': '
test content 2
', 'auid': 903535, 'crid': 'visx_1', 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner' }], 'seat': '1' }, ]; const bidRequests = [ { @@ -1713,13 +1715,13 @@ describe('VisxAdapter', function () { } ]; - const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + const result = spec.interpretResponse({ 'body': { 'seatbid': fullResponse } }, request); expect(result).to.deep.equal(expectedResponse); }); it('handles video bid', function () { const fullResponse = [ - {'bid': [{'price': 0.5, 'impid': '2164be6358b9', 'adm': '', 'auid': 903537, 'crid': 'visx_1', 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video'}], 'seat': '1'}, + { 'bid': [{ 'price': 0.5, 'impid': '2164be6358b9', 'adm': '', 'auid': 903537, 'crid': 'visx_1', 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video' }], 'seat': '1' }, ]; const bidRequests = [ { @@ -1762,13 +1764,13 @@ describe('VisxAdapter', function () { }, } ]; - const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + const result = spec.interpretResponse({ 'body': { 'seatbid': fullResponse } }, request); expect(result).to.deep.equal(expectedResponse); }); it('handles multiformat bid response with outstream+banner as banner', function () { const fullResponse = [ - {'bid': [{'price': 0.5, 'impid': '2164be6358b9', 'adm': '', 'auid': 903537, 'crid': 'visx_1', 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video'}], 'seat': '1'}, + { 'bid': [{ 'price': 0.5, 'impid': '2164be6358b9', 'adm': '', 'auid': 903537, 'crid': 'visx_1', 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video' }], 'seat': '1' }, ]; const bidRequests = [ { @@ -1813,7 +1815,7 @@ describe('VisxAdapter', function () { }, } ]; - const result = spec.interpretResponse({'body': {'seatbid': fullResponse}}, request); + const result = spec.interpretResponse({ 'body': { 'seatbid': fullResponse } }, request); expect(result).to.deep.equal(expectedResponse); }); @@ -1880,7 +1882,7 @@ describe('VisxAdapter', function () { utils.deepSetValue(serverResponse.bid[0], 'ext.visx.events', { runtime: runtimeUrl }); - const result = spec.interpretResponse({'body': {'seatbid': [serverResponse]}}, request); + const result = spec.interpretResponse({ 'body': { 'seatbid': [serverResponse] } }, request); expect(result).to.deep.equal(expectedResponse); }); }); @@ -1973,7 +1975,7 @@ describe('VisxAdapter', function () { const { path, query } = parseUrl(syncs[0].url); expect(path).to.equal('push_sync'); - expect(query).to.deep.equal({iframe: '1'}); + expect(query).to.deep.equal({ iframe: '1' }); }); it('should call image', function () { @@ -2034,15 +2036,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 @@ -2167,15 +2169,15 @@ describe('VisxAdapter', function () { 'browsers': [ { 'brand': 'Chromium', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Google Chrome', - 'version': [ '124' ] + 'version': ['124'] }, { 'brand': 'Not-A.Brand', - 'version': [ '99' ] + 'version': ['99'] } ], 'mobile': 0 diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index 488f00c9a65..f134be9984b 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -18,10 +18,10 @@ import { import { NATIVE_KEYS } from 'src/constants.js'; import { stubAuctionIndex } from '../helpers/indexStub.js'; import { convertOrtbRequestToProprietaryNative, fromOrtbNativeRequest } from '../../src/native.js'; -import {auctionManager} from '../../src/auctionManager.js'; -import {getRenderingData} from '../../src/adRendering.js'; -import {getCreativeRendererSource, PUC_MIN_VERSION} from '../../src/creativeRenderers.js'; -import {deepSetValue} from '../../src/utils.js'; +import { auctionManager } from '../../src/auctionManager.js'; +import { getRenderingData } from '../../src/adRendering.js'; +import { getCreativeRendererSource, PUC_MIN_VERSION } from '../../src/creativeRenderers.js'; +import { deepSetValue } from '../../src/utils.js'; import { EVENT_TYPE_IMPRESSION, TRACKER_METHOD_IMG, TRACKER_METHOD_JS } from 'src/eventTrackers.js'; const utils = require('src/utils'); @@ -249,15 +249,15 @@ describe('native.js', function () { }, withRenderer: false } - }).forEach(([t, {renderDataHook, renderSourceHook, withRenderer}]) => { + }).forEach(([t, { renderDataHook, renderSourceHook, withRenderer }]) => { describe(`when getRenderingData ${t}`, () => { before(() => { getRenderingData.before(renderDataHook, 100); getCreativeRendererSource.before(renderSourceHook, 100); }); after(() => { - getRenderingData.getHooks({hook: renderDataHook}).remove(); - getCreativeRendererSource.getHooks({hook: renderSourceHook}).remove(); + getRenderingData.getHooks({ hook: renderDataHook }).remove(); + getCreativeRendererSource.getHooks({ hook: renderSourceHook }).remove(); }); function checkRenderer(message) { @@ -441,7 +441,7 @@ describe('native.js', function () { action: 'allAssetRequest', adId: '123', }; - adUnit = {mediaTypes: {native: {ortb: ortbRequest}}, nativeOrtbRequest: ortbRequest} + adUnit = { mediaTypes: { native: { ortb: ortbRequest } }, nativeOrtbRequest: ortbRequest } const message = getAllAssetsMessage(messageRequest, bid); const expected = toOrtbNativeResponse(bid.native, ortbRequest) expect(message.ortb).to.eql(expected); @@ -477,7 +477,7 @@ describe('native.js', function () { { event: 1, method: 1, url: 'https://sampleurl.com' }, { event: 1, method: 2, url: 'https://sampleurljs.com' } ], - imptrackers: [ 'https://sample-imp.com' ] + imptrackers: ['https://sample-imp.com'] } describe('toLegacyResponse', () => { it('returns assets in legacy format for ortb responses', () => { @@ -492,8 +492,8 @@ describe('native.js', function () { }); ['img.type', 'title.text', 'data.type'].forEach(prop => { it(`does not choke when the request does not have ${prop}, but the response does`, () => { - const request = {ortb: {assets: [{id: 1}]}}; - const response = {ortb: {assets: [{id: 1}]}}; + const request = { ortb: { assets: [{ id: 1 }] } }; + const response = { ortb: { assets: [{ id: 1 }] } }; deepSetValue(response, `assets.0.${prop}`, 'value'); toLegacyResponse(response, request); }) @@ -541,7 +541,7 @@ describe('native.js', function () { }); it('sets rendererUrl', () => { - adUnit.nativeParams.rendererUrl = {url: 'renderer'}; + adUnit.nativeParams.rendererUrl = { url: 'renderer' }; setNativeResponseProperties(bid, adUnit); expect(bid.native.rendererUrl).to.eql('renderer'); }); @@ -1056,17 +1056,17 @@ describe('validate native', function () { describe('legacyPropertiesToOrtbNative', () => { describe('click trakckers', () => { it('should convert clickUrl to link.url', () => { - const native = legacyPropertiesToOrtbNative({clickUrl: 'some-url'}); + const native = legacyPropertiesToOrtbNative({ clickUrl: 'some-url' }); expect(native.link.url).to.eql('some-url'); }); it('should convert single clickTrackers to link.clicktrackers', () => { - const native = legacyPropertiesToOrtbNative({clickTrackers: 'some-url'}); + const native = legacyPropertiesToOrtbNative({ clickTrackers: 'some-url' }); expect(native.link.clicktrackers).to.eql([ 'some-url' ]) }); it('should convert multiple clickTrackers into link.clicktrackers', () => { - const native = legacyPropertiesToOrtbNative({clickTrackers: ['url1', 'url2']}); + const native = legacyPropertiesToOrtbNative({ clickTrackers: ['url1', 'url2'] }); expect(native.link.clicktrackers).to.eql([ 'url1', 'url2' @@ -1075,7 +1075,7 @@ describe('legacyPropertiesToOrtbNative', () => { }); describe('impressionTrackers', () => { it('should convert a single tracker into an eventtracker entry', () => { - const native = legacyPropertiesToOrtbNative({impressionTrackers: 'some-url'}); + const native = legacyPropertiesToOrtbNative({ impressionTrackers: 'some-url' }); expect(native.eventtrackers).to.eql([ { event: 1, @@ -1086,7 +1086,7 @@ describe('legacyPropertiesToOrtbNative', () => { }); it('should convert an array into corresponding eventtracker entries', () => { - const native = legacyPropertiesToOrtbNative({impressionTrackers: ['url1', 'url2']}); + const native = legacyPropertiesToOrtbNative({ impressionTrackers: ['url1', 'url2'] }); expect(native.eventtrackers).to.eql([ { event: 1, @@ -1103,17 +1103,17 @@ describe('legacyPropertiesToOrtbNative', () => { }); describe('javascriptTrackers', () => { it('should convert a single value into jstracker', () => { - const native = legacyPropertiesToOrtbNative({javascriptTrackers: 'some-markup'}); + const native = legacyPropertiesToOrtbNative({ javascriptTrackers: 'some-markup' }); expect(native.jstracker).to.eql('some-markup'); }) it('should merge multiple values into a single jstracker', () => { - const native = legacyPropertiesToOrtbNative({javascriptTrackers: ['some-markup', 'some-other-markup']}); + const native = legacyPropertiesToOrtbNative({ javascriptTrackers: ['some-markup', 'some-other-markup'] }); expect(native.jstracker).to.eql('some-markupsome-other-markup'); }) }); describe('privacylink', () => { it('should convert privacyLink to privacy', () => { - const native = legacyPropertiesToOrtbNative({privacyLink: 'https:/my-privacy-link.com'}); + const native = legacyPropertiesToOrtbNative({ privacyLink: 'https:/my-privacy-link.com' }); expect(native.privacy).to.eql('https:/my-privacy-link.com'); }) }) @@ -1127,7 +1127,7 @@ describe('fireImpressionTrackers', () => { }) function runTrackers(resp) { - fireImpressionTrackers(resp, {}, {runMarkup, fetchURL}) + fireImpressionTrackers(resp, {}, { runMarkup, fetchURL }) } it('should run markup in jstracker', () => { @@ -1148,7 +1148,7 @@ describe('fireImpressionTrackers', () => { it('should fetch each url in eventtrackers that use the image method', () => { const urls = ['url1', 'url2']; runTrackers({ - eventtrackers: urls.map(url => ({event: 1, method: 1, url})) + eventtrackers: urls.map(url => ({ event: 1, method: 1, url })) }); urls.forEach(url => sinon.assert.calledWith(fetchURL, url)) }); @@ -1156,7 +1156,7 @@ describe('fireImpressionTrackers', () => { it('should load as a script each url in eventtrackers that use the js method', () => { const urls = ['url1', 'url2']; runTrackers({ - eventtrackers: urls.map(url => ({event: 1, method: 2, url})) + eventtrackers: urls.map(url => ({ event: 1, method: 2, url })) }); urls.forEach(url => sinon.assert.calledWith(runMarkup, sinon.match(`script async src="${url}"`))) }); @@ -1285,7 +1285,7 @@ describe('fireClickTrackers', () => { }); function runTrackers(resp, assetId = null) { - fireClickTrackers(resp, assetId, {fetchURL}); + fireClickTrackers(resp, assetId, { fetchURL }); } it('should load each URL in link.clicktrackers', () => { diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index ff390b95268..153bccab5ca 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -1,21 +1,21 @@ -import {isValid, newBidder, registerBidder} from 'src/adapters/bidderFactory.js'; +import { isValid, newBidder, registerBidder } from 'src/adapters/bidderFactory.js'; import adapterManager from 'src/adapterManager.js'; import * as ajax from 'src/ajax.js'; -import {expect} from 'chai'; -import {userSync} from 'src/userSync.js'; +import { expect } from 'chai'; +import { userSync } from 'src/userSync.js'; import * as utils from 'src/utils.js'; -import {config} from 'src/config.js'; +import { config } from 'src/config.js'; import { EVENTS, DEBUG_MODE } from 'src/constants.js'; import * as events from 'src/events.js'; -import {hook} from '../../../../src/hook.js'; -import {auctionManager} from '../../../../src/auctionManager.js'; -import {stubAuctionIndex} from '../../../helpers/indexStub.js'; -import {bidderSettings} from '../../../../src/bidderSettings.js'; -import {decorateAdUnitsWithNativeParams} from '../../../../src/native.js'; +import { hook } from '../../../../src/hook.js'; +import { auctionManager } from '../../../../src/auctionManager.js'; +import { stubAuctionIndex } from '../../../helpers/indexStub.js'; +import { bidderSettings } from '../../../../src/bidderSettings.js'; +import { decorateAdUnitsWithNativeParams } from '../../../../src/native.js'; import * as activityRules from 'src/activities/rules.js'; -import {MODULE_TYPE_BIDDER} from '../../../../src/activities/modules.js'; -import {ACTIVITY_TRANSMIT_TID, ACTIVITY_TRANSMIT_UFPD} from '../../../../src/activities/activities.js'; -import {getGlobal} from '../../../../src/prebidGlobal.js'; +import { MODULE_TYPE_BIDDER } from '../../../../src/activities/modules.js'; +import { ACTIVITY_TRANSMIT_TID, ACTIVITY_TRANSMIT_UFPD } from '../../../../src/activities/activities.js'; +import { getGlobal } from '../../../../src/prebidGlobal.js'; const CODE = 'sampleBidder'; const MOCK_BIDS_REQUEST = { @@ -118,7 +118,7 @@ describe('bidderFactory', () => { aliasSyncEnabled: false, shouldRegister: false } - ].forEach(({t, alias, aliasSyncEnabled, shouldRegister}) => { + ].forEach(({ t, alias, aliasSyncEnabled, shouldRegister }) => { describe(t, () => { it(shouldRegister ? 'should register sync' : 'should NOT register sync', () => { config.setConfig({ @@ -199,10 +199,10 @@ describe('bidderFactory', () => { } } } - ].forEach(({t, userSync, expected}) => { + ].forEach(({ t, userSync, expected }) => { describe(`when ${t}`, () => { beforeEach(() => { - config.setConfig({userSync}); + config.setConfig({ userSync }); }); Object.entries(expected).forEach(([bidderCode, syncOptions]) => { @@ -221,7 +221,7 @@ describe('bidderFactory', () => { describe('transaction IDs', () => { beforeEach(() => { activityRules.isActivityAllowed.resetHistory(); - ajaxStub.callsFake((_, callback) => callback.success(null, {getResponseHeader: sinon.stub()})); + ajaxStub.callsFake((_, callback) => callback.success(null, { getResponseHeader: sinon.stub() })); spec.interpretResponse.callsFake(() => [ { requestId: 'bid', @@ -255,7 +255,7 @@ describe('bidderFactory', () => { expect(br.transactionId).to.eql('bidder-ext-tid'); }, }, - }).forEach(([t, {allowed, checkBidderRequest, checkBidRequest}]) => { + }).forEach(([t, { allowed, checkBidderRequest, checkBidRequest }]) => { it(`should ${t} from the spec logic when the transmitTid activity is${allowed ? '' : ' not'} allowed`, () => { spec.isBidRequestValid.callsFake(br => { checkBidRequest(br); @@ -264,7 +264,7 @@ describe('bidderFactory', () => { spec.buildRequests.callsFake((bidReqs, bidderReq) => { checkBidderRequest(bidderReq); bidReqs.forEach(checkBidRequest); - return {method: 'POST'}; + return { method: 'POST' }; }); activityRules.isActivityAllowed.callsFake(() => allowed); @@ -615,7 +615,7 @@ describe('bidderFactory', () => { url, sinon.match.any, sinon.match.any, - sinon.match({browsingTopics: shouldBeSet, suppressTopicsEnrollmentWarning: true}) + sinon.match({ browsingTopics: shouldBeSet, suppressTopicsEnrollmentWarning: true }) ); }); }); @@ -686,7 +686,7 @@ describe('bidderFactory', () => { it('should call onTimelyResponse', () => { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); - spec.buildRequests.returns({method: 'POST', url: 'test', data: {}}); + spec.buildRequests.returns({ method: 'POST', url: 'test', data: {} }); bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); sinon.assert.called(onTimelyResponseStub); }) @@ -755,7 +755,7 @@ describe('bidderFactory', () => { netRevenue: true, ttl: 300, bidderCode: 'sampleBidder', - sampleBidder: {advertiserId: '12345', networkId: '111222'} + sampleBidder: { advertiserId: '12345', networkId: '111222' } } bidderRequest = utils.deepClone(MOCK_BIDS_REQUEST); bidderRequest.bids[0].bidder = 'sampleBidder'; @@ -789,7 +789,7 @@ describe('bidderFactory', () => { expect(doneStub.calledOnce).to.equal(true); expect(logErrorSpy.callCount).to.equal(0); expect(auctionBid.meta).to.exist; - expect(auctionBid.meta).to.deep.equal({advertiserId: '12345', networkId: '111222'}); + expect(auctionBid.meta).to.deep.equal({ advertiserId: '12345', networkId: '111222' }); }); describe('if request has deferBilling = true', () => { @@ -816,7 +816,7 @@ describe('bidderFactory', () => { deferRendering: true, shouldDefer: true } - ].forEach(({onBidBillable, deferRendering, shouldDefer}) => { + ].forEach(({ onBidBillable, deferRendering, shouldDefer }) => { it(`sets response deferRendering = ${shouldDefer} when adapter ${onBidBillable ? 'supports' : 'does not support'} onBidBillable, and sayd deferRender = ${deferRendering}`, () => { if (onBidBillable) { spec.onBidBillable = sinon.stub(); @@ -991,10 +991,10 @@ describe('bidderFactory', () => { 'other errors': false }).forEach(([t, timedOut]) => { it(`should ${timedOut ? 'NOT ' : ''}call onTimelyResponse on ${t}`, () => { - Object.assign(xhrErrorMock, {timedOut}); + Object.assign(xhrErrorMock, { timedOut }); const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); - spec.buildRequests.returns({method: 'POST', url: 'test', data: {}}); + spec.buildRequests.returns({ method: 'POST', url: 'test', data: {} }); bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); sinon.assert[timedOut ? 'notCalled' : 'called'](onTimelyResponseStub); }) @@ -1142,7 +1142,7 @@ describe('bidderFactory', () => { const thisSpec = Object.assign(newEmptySpec(), { supportedMediaTypes: ['video'] }); registerBidder(thisSpec); expect(registerBidAdapterStub.calledOnce).to.equal(true); - expect(registerBidAdapterStub.firstCall.args[2]).to.deep.equal({supportedMediaTypes: ['video']}); + expect(registerBidAdapterStub.firstCall.args[2]).to.deep.equal({ supportedMediaTypes: ['video'] }); }); it('should register bidders with the appropriate aliases', function () { @@ -1253,7 +1253,7 @@ describe('bidderFactory', () => { indexStub = sinon.stub(auctionManager, 'index'); adUnits = []; bidderRequests = []; - indexStub.get(() => stubAuctionIndex({adUnits: adUnits, bidderRequests: bidderRequests})) + indexStub.get(() => stubAuctionIndex({ adUnits: adUnits, bidderRequests: bidderRequests })) }); afterEach(function () { @@ -1267,7 +1267,7 @@ describe('bidderFactory', () => { adUnits = [{ adUnitId: 'au', nativeParams: { - title: {'required': true}, + title: { 'required': true }, } }] decorateAdUnitsWithNativeParams(adUnits); @@ -1309,7 +1309,7 @@ describe('bidderFactory', () => { adUnits = [{ transactionId: 'au', nativeParams: { - title: {'required': true}, + title: { 'required': true }, }, }]; decorateAdUnitsWithNativeParams(adUnits); @@ -1351,7 +1351,7 @@ describe('bidderFactory', () => { adUnits = [{ transactionId: 'au', mediaTypes: { - video: {context: 'outstream'} + video: { context: 'outstream' } } }] const bidRequest = { @@ -1371,7 +1371,7 @@ describe('bidderFactory', () => { { bidderCode: CODE, mediaType: 'video', - renderer: {render: () => true, url: 'render.js'}, + renderer: { render: () => true, url: 'render.js' }, } ); @@ -1428,7 +1428,7 @@ describe('bidderFactory', () => { }] }; const bidder = newBidder(spec); - spec.interpretResponse.returns(Object.assign({}, bids[0], {transactionId: 'ignored', auctionId: 'ignored'})); + spec.interpretResponse.returns(Object.assign({}, bids[0], { transactionId: 'ignored', auctionId: 'ignored' })); bidder.callBids(bidderRequest, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); sinon.assert.calledWith(addBidResponseStub, sinon.match.any, sinon.match({ transactionId: 'tid', @@ -1577,7 +1577,7 @@ describe('bidderFactory', () => { it('should not accept the bid, when bidder is an alias but bidderSetting is missing for the bidder. It should fallback to standard setting and reject the bid', function () { bidderSettingStub.withArgs(CODE, 'allowAlternateBidderCodes').returns(false); - aliasRegistry = {'validAlternateBidder': CODE}; + aliasRegistry = { 'validAlternateBidder': CODE }; const bidder = newBidder(spec); spec.interpretResponse.returns(bids1); @@ -1671,23 +1671,23 @@ describe('bidderFactory', () => { } function checkValid(bid) { - return isValid('au', bid, {index: stubAuctionIndex({bidRequests: [req]})}); + return isValid('au', bid, { index: stubAuctionIndex({ bidRequests: [req] }) }); } it('should succeed when response has a size that was in request', () => { - expect(checkValid(mkResponse({width: 3, height: 4}))).to.be.true; + expect(checkValid(mkResponse({ width: 3, height: 4 }))).to.be.true; }); describe('using w/hratio', () => { beforeEach(() => { req.ortb2Imp = { banner: { - format: [{wratio: 1, hratio: 2}] + format: [{ wratio: 1, hratio: 2 }] } } }) it('should accept wratio/hratio', () => { - expect(checkValid(mkResponse({wratio: 1, hratio: 2}))).to.be.true; + expect(checkValid(mkResponse({ wratio: 1, hratio: 2 }))).to.be.true; }); }); }) diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 1f4d386a413..658451b3d61 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -1,4 +1,4 @@ -import {expect} from 'chai'; +import { expect } from 'chai'; import { filters, getGPTSlotsForAdUnits, @@ -6,16 +6,16 @@ import { sortByDealAndPriceBucketOrCpm, targeting as targetingInstance } from 'src/targeting.js'; -import {config} from 'src/config.js'; -import {createBidReceived} from 'test/fixtures/fixtures.js'; -import {DEFAULT_TARGETING_KEYS, JSON_MAPPING, NATIVE_KEYS, TARGETING_KEYS} from 'src/constants.js'; -import {auctionManager} from 'src/auctionManager.js'; +import { config } from 'src/config.js'; +import { createBidReceived } from 'test/fixtures/fixtures.js'; +import { DEFAULT_TARGETING_KEYS, JSON_MAPPING, NATIVE_KEYS, TARGETING_KEYS } from 'src/constants.js'; +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, setupBeforeHookFnOnce} from '../../../../src/hook.js'; -import {getHighestCpm} from '../../../../src/utils/reducers.js'; -import {getGlobal} from '../../../../src/prebidGlobal.js'; +import { deepClone } from 'src/utils.js'; +import { createBid } from '../../../../src/bidfactory.js'; +import { hook, setupBeforeHookFnOnce } from '../../../../src/hook.js'; +import { getHighestCpm } from '../../../../src/utils/reducers.js'; +import { getGlobal } from '../../../../src/prebidGlobal.js'; import { getAdUnitBidLimitMap } from '../../../../src/targeting.js'; function mkBid(bid) { @@ -289,7 +289,7 @@ describe('targeting tests', function () { bid.ttlBuffer = ttlBuffer }, 'setConfig({ttlBuffer})': (_, ttlBuffer) => { - config.setConfig({ttlBuffer}) + config.setConfig({ ttlBuffer }) }, }).forEach(([t, setup]) => { describe(`respects ${t}`, () => { @@ -491,11 +491,11 @@ describe('targeting tests', function () { sandbox.stub(auctionManager, 'getAdUnits').callsFake(() => ([ { code: 'au1', - [JSON_MAPPING.ADSERVER_TARGETING]: {'aut': 'v1'} + [JSON_MAPPING.ADSERVER_TARGETING]: { 'aut': 'v1' } }, { code: 'au2', - [JSON_MAPPING.ADSERVER_TARGETING]: {'aut': 'v2'} + [JSON_MAPPING.ADSERVER_TARGETING]: { 'aut': 'v2' } } ])); expect(targetingInstance.getAllTargeting('au1').au2).to.not.exist; @@ -1028,7 +1028,7 @@ describe('targeting tests', function () { it('should merge custom targeting from all bids when allBidsCustomTargeting: true', function () { // Default behavior - no specific configuration - config.setConfig({targetingControls: {allBidsCustomTargeting: true}}); + config.setConfig({ targetingControls: { allBidsCustomTargeting: true } }); const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); // Custom key values from both bids should be combined to maintain existing functionality @@ -1185,10 +1185,10 @@ describe('targeting tests', function () { it('should use bids from pool to get Winning Bid', function () { const bidsReceived = [ - createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1'}), - createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2'}), - createBidReceived({bidder: 'appnexus', cpm: 6, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3'}), - createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4'}), + createBidReceived({ bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1' }), + createBidReceived({ bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2' }), + createBidReceived({ bidder: 'appnexus', cpm: 6, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3' }), + createBidReceived({ bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4' }), ]; const adUnitCodes = ['code-0', 'code-1']; @@ -1203,8 +1203,8 @@ describe('targeting tests', function () { useBidCache = true; auctionManagerStub.returns([ - createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1'}), - createBidReceived({bidder: 'appnexus', cpm: 5, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-2'}), + createBidReceived({ bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1' }), + createBidReceived({ bidder: 'appnexus', cpm: 5, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-2' }), ]); const adUnitCodes = ['code-0']; @@ -1227,14 +1227,14 @@ describe('targeting tests', function () { it('should use bidCacheFilterFunction', function() { auctionManagerStub.returns([ - createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', mediaType: 'banner'}), - createBidReceived({bidder: 'appnexus', cpm: 5, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-2', mediaType: 'banner'}), - createBidReceived({bidder: 'appnexus', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-3', mediaType: 'banner'}), - createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4', mediaType: 'banner'}), - createBidReceived({bidder: 'appnexus', cpm: 27, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-2', adId: 'adid-5', mediaType: 'video'}), - createBidReceived({bidder: 'appnexus', cpm: 25, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-2', adId: 'adid-6', mediaType: 'video'}), - createBidReceived({bidder: 'appnexus', cpm: 26, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-3', adId: 'adid-7', mediaType: 'video'}), - createBidReceived({bidder: 'appnexus', cpm: 28, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-3', adId: 'adid-8', mediaType: 'video'}), + createBidReceived({ bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', mediaType: 'banner' }), + createBidReceived({ bidder: 'appnexus', cpm: 5, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-2', mediaType: 'banner' }), + createBidReceived({ bidder: 'appnexus', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-3', mediaType: 'banner' }), + createBidReceived({ bidder: 'appnexus', cpm: 8, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4', mediaType: 'banner' }), + createBidReceived({ bidder: 'appnexus', cpm: 27, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-2', adId: 'adid-5', mediaType: 'video' }), + createBidReceived({ bidder: 'appnexus', cpm: 25, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-2', adId: 'adid-6', mediaType: 'video' }), + createBidReceived({ bidder: 'appnexus', cpm: 26, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-3', adId: 'adid-7', mediaType: 'video' }), + createBidReceived({ bidder: 'appnexus', cpm: 28, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-3', adId: 'adid-8', mediaType: 'video' }), ]); const adUnitCodes = ['code-0', 'code-1', 'code-2', 'code-3']; @@ -1334,10 +1334,10 @@ describe('targeting tests', function () { it('should not use rendered bid to get winning bid', function () { const bidsReceived = [ - createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'rendered'}), - createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2'}), - createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3'}), - createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4'}), + createBidReceived({ bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'rendered' }), + createBidReceived({ bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2' }), + createBidReceived({ bidder: 'appnexus', cpm: 7, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3' }), + createBidReceived({ bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4' }), ]; auctionManagerStub.returns(bidsReceived); @@ -1352,10 +1352,10 @@ describe('targeting tests', function () { it('should use highest cpm bid from bid pool to get winning bid', function () { // Pool is having 4 bids from 2 auctions. There are 2 bids from rubicon, #2 which is highest cpm bid will be selected to take part in auction. const bidsReceived = [ - createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1'}), - createBidReceived({bidder: 'rubicon', cpm: 9, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-0', adId: 'adid-2'}), - createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3'}), - createBidReceived({bidder: 'rubicon', cpm: 8, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-0', adId: 'adid-4'}), + createBidReceived({ bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1' }), + createBidReceived({ bidder: 'rubicon', cpm: 9, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-0', adId: 'adid-2' }), + createBidReceived({ bidder: 'appnexus', cpm: 7, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3' }), + createBidReceived({ bidder: 'rubicon', cpm: 8, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-0', adId: 'adid-4' }), ]; auctionManagerStub.returns(bidsReceived); @@ -1379,10 +1379,10 @@ describe('targeting tests', function () { timestampStub.returns(200000); // Pool is having 4 bids from 2 auctions. All the bids are expired and only bid #3 is passing the bidExpiry check. const bidsReceived = [ - createBidReceived({bidder: 'appnexus', cpm: 18, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', ttl: 150}), - createBidReceived({bidder: 'sampleBidder', cpm: 16, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-0', adId: 'adid-2', ttl: 100}), - createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3', ttl: 300}), - createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-0', adId: 'adid-4', ttl: 50}), + createBidReceived({ bidder: 'appnexus', cpm: 18, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', ttl: 150 }), + createBidReceived({ bidder: 'sampleBidder', cpm: 16, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-0', adId: 'adid-2', ttl: 100 }), + createBidReceived({ bidder: 'appnexus', cpm: 7, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3', ttl: 300 }), + createBidReceived({ bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-0', adId: 'adid-4', ttl: 50 }), ]; auctionManagerStub.returns(bidsReceived); @@ -1573,7 +1573,7 @@ describe('targeting tests', function () { before(() => { if (window.apntag?.setKeywords == null) { const orig = window.apntag; - window.apntag = {setKeywords: () => {}} + window.apntag = { setKeywords: () => {} } after(() => { window.apntag = orig; }) @@ -1592,28 +1592,28 @@ describe('targeting tests', function () { it('should set single addUnit code', function() { const adUnitCode = 'testdiv-abc-ad-123456-0'; sandbox.stub(targetingInstance, 'getAllTargeting').returns({ - 'testdiv1-abc-ad-123456-0': {hb_bidder: 'appnexus'} + 'testdiv1-abc-ad-123456-0': { hb_bidder: 'appnexus' } }); targetingInstance.setTargetingForAst(adUnitCode); expect(targetingInstance.getAllTargeting.called).to.equal(true); expect(targetingInstance.resetPresetTargetingAST.called).to.equal(true); expect(apnTagStub.callCount).to.equal(1); expect(apnTagStub.getCall(0).args[0]).to.deep.equal('testdiv1-abc-ad-123456-0'); - expect(apnTagStub.getCall(0).args[1]).to.deep.equal({HB_BIDDER: 'appnexus'}); + expect(apnTagStub.getCall(0).args[1]).to.deep.equal({ HB_BIDDER: 'appnexus' }); }); it('should set array of addUnit codes', function() { const adUnitCodes = ['testdiv1-abc-ad-123456-0', 'testdiv2-abc-ad-123456-0'] sandbox.stub(targetingInstance, 'getAllTargeting').returns({ - 'testdiv1-abc-ad-123456-0': {hb_bidder: 'appnexus'}, - 'testdiv2-abc-ad-123456-0': {hb_bidder: 'appnexus'} + 'testdiv1-abc-ad-123456-0': { hb_bidder: 'appnexus' }, + 'testdiv2-abc-ad-123456-0': { hb_bidder: 'appnexus' } }); targetingInstance.setTargetingForAst(adUnitCodes); expect(targetingInstance.getAllTargeting.called).to.equal(true); expect(targetingInstance.resetPresetTargetingAST.called).to.equal(true); expect(apnTagStub.callCount).to.equal(2); expect(apnTagStub.getCall(1).args[0]).to.deep.equal('testdiv2-abc-ad-123456-0'); - expect(apnTagStub.getCall(1).args[1]).to.deep.equal({HB_BIDDER: 'appnexus'}); + expect(apnTagStub.getCall(1).args[1]).to.deep.equal({ HB_BIDDER: 'appnexus' }); }); }); @@ -1641,12 +1641,12 @@ describe('targeting tests', function () { it('can find slots by ad unit path', () => { const paths = ['slot/1', 'slot/2'] - expect(getGPTSlotsForAdUnits(paths, () => slots)).to.eql({[paths[0]]: [slots[0], slots[2]], [paths[1]]: [slots[1]]}); + expect(getGPTSlotsForAdUnits(paths, () => slots)).to.eql({ [paths[0]]: [slots[0], slots[2]], [paths[1]]: [slots[1]] }); }) it('can find slots by ad element ID', () => { const elementIds = ['div-1', 'div-2'] - expect(getGPTSlotsForAdUnits(elementIds, () => slots)).to.eql({[elementIds[0]]: [slots[0]], [elementIds[1]]: [slots[1]]}); + expect(getGPTSlotsForAdUnits(elementIds, () => slots)).to.eql({ [elementIds[0]]: [slots[0]], [elementIds[1]]: [slots[1]] }); }) it('returns empty list on no match', () => { diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 257b86f2992..bbc4d3cc424 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -8,25 +8,25 @@ import { getTargetingKeys, getTargetingKeysBidLandscape } from 'test/fixtures/fixtures.js'; -import {auctionManager, newAuctionManager} from 'src/auctionManager.js'; -import {filters, newTargeting, targeting} from 'src/targeting.js'; -import {config as configObj} from 'src/config.js'; +import { auctionManager, newAuctionManager } from 'src/auctionManager.js'; +import { filters, newTargeting, targeting } from 'src/targeting.js'; +import { config as configObj } from 'src/config.js'; import * as ajaxLib from 'src/ajax.js'; import * as auctionModule from 'src/auction.js'; -import {resetAuctionState} from 'src/auction.js'; -import {registerBidder} from 'src/adapters/bidderFactory.js'; +import { resetAuctionState } from 'src/auction.js'; +import { registerBidder } from 'src/adapters/bidderFactory.js'; import * as pbjsModule from 'src/prebid.js'; -import pbjs, {resetQueSetup, startAuction} from 'src/prebid.js'; -import {hook} from '../../../src/hook.js'; -import {reset as resetDebugging} from '../../../src/debugging.js'; -import {stubAuctionIndex} from '../../helpers/indexStub.js'; -import {createBid} from '../../../src/bidfactory.js'; -import {enrichFPD} from '../../../src/fpd/enrichment.js'; -import {mockFpdEnrichments} from '../../helpers/fpd.js'; -import {deepAccess, deepSetValue, generateUUID} from '../../../src/utils.js'; -import {getCreativeRenderer} from '../../../src/creativeRenderers.js'; -import {BID_STATUS, EVENTS, GRANULARITY_OPTIONS, PB_LOCATOR, TARGETING_KEYS} from 'src/constants.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; +import pbjs, { resetQueSetup, startAuction } from 'src/prebid.js'; +import { hook } from '../../../src/hook.js'; +import { reset as resetDebugging } from '../../../src/debugging.js'; +import { stubAuctionIndex } from '../../helpers/indexStub.js'; +import { createBid } from '../../../src/bidfactory.js'; +import { enrichFPD } from '../../../src/fpd/enrichment.js'; +import { mockFpdEnrichments } from '../../helpers/fpd.js'; +import { deepAccess, deepSetValue, generateUUID } from '../../../src/utils.js'; +import { getCreativeRenderer } from '../../../src/creativeRenderers.js'; +import { BID_STATUS, EVENTS, GRANULARITY_OPTIONS, PB_LOCATOR, TARGETING_KEYS } from 'src/constants.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; var assert = require('chai').assert; var expect = require('chai').expect; @@ -49,7 +49,7 @@ let auction; function resetAuction() { if (auction == null) { - auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout: timeout, labels: undefined, auctionId: auctionId}); + auction = auctionManager.createAuction({ adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout: timeout, labels: undefined, auctionId: auctionId }); } pbjs.setConfig({ enableSendAllBids: false }); auction.getBidRequests = getBidRequests; @@ -335,12 +335,12 @@ describe('Unit: Prebid Module', function () { }); afterEach(() => { - pbjsModule.requestBids.getHooks({hook: deferringHook}).remove(); + pbjsModule.requestBids.getHooks({ hook: deferringHook }).remove(); pbjs.adUnits.splice(0, pbjs.adUnits.length); }) Object.entries({ - 'addAdUnits': (g) => g.addAdUnits({code: 'three'}), + 'addAdUnits': (g) => g.addAdUnits({ code: 'three' }), 'removeAdUnit': (g) => g.removeAdUnit('one') }).forEach(([method, op]) => { it(`once called, should not be affected by ${method}`, () => { @@ -607,8 +607,7 @@ describe('Unit: Prebid Module', function () { 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] }, - 'viewability': { - 'config': ''} + 'viewability': { 'config': '' } }] }] }; @@ -672,7 +671,7 @@ describe('Unit: Prebid Module', function () { }] }]; const adUnitCodes = ['div-gpt-ad-1460505748561-0']; - auction = auctionManagerInstance.createAuction({adUnits, adUnitCodes}); + auction = auctionManagerInstance.createAuction({ adUnits, adUnitCodes }); indexStub = sinon.stub(auctionManager, 'index'); indexStub.get(() => auctionManagerInstance.index); ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder').callsFake(function() { @@ -761,8 +760,7 @@ describe('Unit: Prebid Module', function () { 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] }, - 'viewability': { - 'config': ''} + 'viewability': { 'config': '' } }] }] }; @@ -795,8 +793,7 @@ describe('Unit: Prebid Module', function () { 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] }] }, - 'viewability': { - 'config': ''} + 'viewability': { 'config': '' } }] }] }; @@ -1026,7 +1023,7 @@ describe('Unit: Prebid Module', function () { it('should return expected bid responses when not passed an adunitCode', function () { auctionManager.getLastAuctionId = () => 654321; var result = pbjs.getBidResponses(); - var compare = Object.fromEntries(Object.entries(getBidResponsesFromAPI()).map(([code, {bids}]) => { + var compare = Object.fromEntries(Object.entries(getBidResponsesFromAPI()).map(([code, { bids }]) => { const arr = bids.slice(); arr.bids = arr; return [code, arr]; @@ -1068,7 +1065,7 @@ describe('Unit: Prebid Module', function () { window.googletag.pubads().setSlots(slots); pbjs.setTargetingForGPTAsync([config.adUnitCodes[0]]); - pbjs.setConfig({ targetingControls: {allBidsCustomTargeting: true }}); + pbjs.setConfig({ targetingControls: { allBidsCustomTargeting: true } }); slots.forEach(function(slot) { targeting = {}; @@ -1122,7 +1119,7 @@ describe('Unit: Prebid Module', function () { slots[0].spySetTargeting.resetHistory(); slots[1].spySetTargeting.resetHistory(); window.googletag.pubads().setSlots(slots); - pbjs.setConfig({ targetingControls: {allBidsCustomTargeting: true }}); + pbjs.setConfig({ targetingControls: { allBidsCustomTargeting: true } }); pbjs.setTargetingForGPTAsync([config.adUnitCodes[0]]); var expected = getTargetingKeys(); @@ -1401,7 +1398,7 @@ describe('Unit: Prebid Module', function () { ad: "" }); return renderAd(document, bidId).then(() => { - sinon.assert.calledWith(events.emit, EVENTS.AD_RENDER_SUCCEEDED, sinon.match({adId: bidId})); + sinon.assert.calledWith(events.emit, EVENTS.AD_RENDER_SUCCEEDED, sinon.match({ adId: bidId })); }); }); @@ -1452,7 +1449,7 @@ describe('Unit: Prebid Module', function () { ad: '
ad
', source: 's2s', eventtrackers: [ - {event: 1, method: 1, url} + { event: 1, method: 1, url } ] }); @@ -1521,7 +1518,7 @@ describe('Unit: Prebid Module', function () { var onStaleEvent = sinon.stub(); // Setting suppressStaleRender to true explicitly - configObj.setConfig({'auctionOptions': {'suppressStaleRender': true}}); + configObj.setConfig({ 'auctionOptions': { 'suppressStaleRender': true } }); pbjs.onEvent(EVENTS.BID_WON, onWonEvent); pbjs.onEvent(EVENTS.STALE_RENDER, onStaleEvent); @@ -1561,7 +1558,7 @@ describe('Unit: Prebid Module', function () { // Clean up pbjs.offEvent(EVENTS.BID_WON, onWonEvent); pbjs.offEvent(EVENTS.STALE_RENDER, onStaleEvent); - configObj.setConfig({'auctionOptions': {}}); + configObj.setConfig({ 'auctionOptions': {} }); }); }); }); @@ -1629,11 +1626,11 @@ describe('Unit: Prebid Module', function () { transactionId: 'mock-tid', adUnitId: 'mock-au', bids: [ - {bidder: BIDDER_CODE, params: {placementId: 'id'}}, + { bidder: BIDDER_CODE, params: { placementId: 'id' } }, ] }]; indexStub = sinon.stub(auctionManager, 'index'); - indexStub.get(() => stubAuctionIndex({adUnits, bidRequests})) + indexStub.get(() => stubAuctionIndex({ adUnits, bidRequests })) sinon.stub(adapterManager, 'callBids').callsFake((_, bidrequests, addBidResponse, adapterDone) => { completeAuction = (bidsReceived) => { bidsReceived.forEach((bid) => addBidResponse(bid.adUnitCode, Object.assign(createBid(), bid))); @@ -1660,7 +1657,7 @@ describe('Unit: Prebid Module', function () { }; registerBidder(spec); - spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.buildRequests.returns([{ 'id': 123, 'method': 'POST' }]); spec.isBidRequestValid.returns(true); spec.interpretResponse.returns(bids); }); @@ -1745,7 +1742,7 @@ describe('Unit: Prebid Module', function () { pbjsModule.requestBids.before(requestBidsHook, 999); }) after(() => { - pbjsModule.requestBids.getHooks({hook: requestBidsHook}).remove(); + pbjsModule.requestBids.getHooks({ hook: requestBidsHook }).remove(); }) beforeEach(() => { @@ -1856,7 +1853,7 @@ describe('Unit: Prebid Module', function () { }); afterEach(() => { - pbjsModule.requestBids.getHooks({hook: delayHook}).remove(); + pbjsModule.requestBids.getHooks({ hook: delayHook }).remove(); }); Object.entries({ @@ -1864,13 +1861,13 @@ describe('Unit: Prebid Module', function () { 'after bidsBackHandler': (() => { const bidsBackHandler = sinon.stub(); return function (req) { - return pbjs.requestBids({...req, bidsBackHandler}).then(({bids, timedOut, auctionId}) => { + return pbjs.requestBids({ ...req, bidsBackHandler }).then(({ bids, timedOut, auctionId }) => { sinon.assert.calledWith(bidsBackHandler, bids, timedOut, auctionId); - return {bids, timedOut, auctionId}; + return { bids, timedOut, auctionId }; }) } })(), - 'after a bidsBackHandler that throws': (req) => pbjs.requestBids({...req, bidsBackHandler: () => { throw new Error() }}) + 'after a bidsBackHandler that throws': (req) => pbjs.requestBids({ ...req, bidsBackHandler: () => { throw new Error() } }) }).forEach(([t, requestBids]) => { describe(t, () => { it('with no args, when no adUnits are defined', () => { @@ -1888,7 +1885,7 @@ describe('Unit: Prebid Module', function () { auctionId: 'mock-auctionId', adUnits, timeout: 10 - }).then(({timedOut, bids, auctionId}) => { + }).then(({ timedOut, bids, auctionId }) => { expect(timedOut).to.be.true; expect(bids).to.eql({}); expect(auctionId).to.eql('mock-auctionId'); @@ -1906,7 +1903,7 @@ describe('Unit: Prebid Module', function () { } requestBids({ adUnits, - }).then(({bids}) => { + }).then(({ bids }) => { sinon.assert.match(bids[bid.adUnitCode].bids[0], bid) done(); }); @@ -1922,7 +1919,7 @@ describe('Unit: Prebid Module', function () { it('should transfer ttlBuffer to adUnit.ttlBuffer', async () => { await runAuction({ ttlBuffer: 123, - adUnits: [adUnits[0], {...adUnits[0], ttlBuffer: 0}] + adUnits: [adUnits[0], { ...adUnits[0], ttlBuffer: 0 }] }); sinon.assert.calledWithMatch(auctionModule.newAuction, { adUnits: sinon.match((units) => units[0].ttlBuffer === 123 && units[1].ttlBuffer === 0) @@ -1949,11 +1946,11 @@ describe('Unit: Prebid Module', function () { adUnits: [ { code: 'test1', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [], }, { code: 'test2', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [], } ], @@ -1978,7 +1975,7 @@ describe('Unit: Prebid Module', function () { configObj.resetConfig(); }); afterEach(() => { - pbjsModule.startAuction.getHooks({hook: saHook}).remove(); + pbjsModule.startAuction.getHooks({ hook: saHook }).remove(); }) after(() => { configObj.resetConfig(); @@ -2058,19 +2055,19 @@ describe('Unit: Prebid Module', function () { }); it('merged from setConfig and requestBids', async () => { - configObj.setConfig({ortb2: globalFPD}); - await runAuction({ortb2: auctionFPD}); + configObj.setConfig({ ortb2: globalFPD }); + await runAuction({ ortb2: auctionFPD }); sinon.assert.calledWith(startAuctionStub, sinon.match({ - ortb2Fragments: {global: mergedFPD} + ortb2Fragments: { global: mergedFPD } })); }); it('that cannot alter global config', () => { - configObj.setConfig({ortb2: {value: 'old'}}); - startAuctionStub.callsFake(({ortb2Fragments}) => { + configObj.setConfig({ ortb2: { value: 'old' } }); + startAuctionStub.callsFake(({ ortb2Fragments }) => { ortb2Fragments.global.value = 'new' }); - pbjs.requestBids({ortb2: auctionFPD}); + pbjs.requestBids({ ortb2: auctionFPD }); expect(configObj.getAnyConfig('ortb2').value).to.eql('old'); }); @@ -2078,13 +2075,13 @@ describe('Unit: Prebid Module', function () { configObj.setBidderConfig({ bidders: ['mockBidder'], config: { - ortb2: {value: 'old'} + ortb2: { value: 'old' } } }) - startAuctionStub.callsFake(({ortb2Fragments}) => { + startAuctionStub.callsFake(({ ortb2Fragments }) => { ortb2Fragments.bidder.mockBidder.value = 'new'; }) - pbjs.requestBids({ortb2: auctionFPD}); + pbjs.requestBids({ ortb2: auctionFPD }); expect(configObj.getBidderConfig().mockBidder.ortb2.value).to.eql('old'); }) @@ -2098,31 +2095,31 @@ describe('Unit: Prebid Module', function () { enrichFPD.before(enrich); try { - configObj.setConfig({ortb2: globalFPD}); - await runAuction({ortb2: auctionFPD}); + configObj.setConfig({ ortb2: globalFPD }); + await runAuction({ ortb2: auctionFPD }); sinon.assert.calledWith(startAuctionStub, sinon.match({ - ortb2Fragments: {global: {...mergedFPD, enrich: true}} + ortb2Fragments: { global: { ...mergedFPD, enrich: true } } })); } finally { - enrichFPD.getHooks({hook: enrich}).remove(); + enrichFPD.getHooks({ hook: enrich }).remove(); } }) }); it('filtering adUnits by adUnitCodes', async () => { await runAuction({ - adUnits: [{code: 'one'}, {code: 'two'}], + adUnits: [{ code: 'one' }, { code: 'two' }], adUnitCodes: 'two' }); sinon.assert.calledWith(startAuctionStub, sinon.match({ - adUnits: [{code: 'two'}], + adUnits: [{ code: 'two' }], adUnitCodes: ['two'] })); }); it('does not repeat ad unit codes on twin ad units', async () => { await runAuction({ - adUnits: [{code: 'au1'}, {code: 'au2'}, {code: 'au1'}, {code: 'au2'}], + adUnits: [{ code: 'au1' }, { code: 'au2' }, { code: 'au1' }, { code: 'au2' }], }); sinon.assert.calledWith(startAuctionStub, sinon.match({ adUnitCodes: ['au1', 'au2'] @@ -2130,7 +2127,7 @@ describe('Unit: Prebid Module', function () { }); it('filters out repeated ad unit codes from input', async () => { - await runAuction({adUnitCodes: ['au1', 'au1', 'au2']}); + await runAuction({ adUnitCodes: ['au1', 'au1', 'au2'] }); sinon.assert.calledWith(startAuctionStub, sinon.match({ adUnitCodes: ['au1', 'au2'] })); @@ -2194,12 +2191,12 @@ describe('Unit: Prebid Module', function () { }); it('passes ortb2 fragments to createAuction', async () => { - const ortb2Fragments = {global: {}, bidder: {}}; + const ortb2Fragments = { global: {}, bidder: {} }; pbjsModule.startAuction({ adUnits: [{ code: 'au', - mediaTypes: {banner: {sizes: [[300, 250]]}}, - bids: [{bidder: 'bd'}] + mediaTypes: { banner: { sizes: [[300, 250]] } }, + bids: [{ bidder: 'bd' }] }], adUnitCodes: ['au'], ortb2Fragments @@ -2273,11 +2270,11 @@ describe('Unit: Prebid Module', function () { { code: 'test1', transactionId: 'd0676a3c-ff32-45a5-af65-8175a8e7ddca', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] }, { code: 'test2', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] } ] @@ -2295,11 +2292,11 @@ describe('Unit: Prebid Module', function () { adUnits: [ { code: 'twin', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] }, { code: 'twin', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] } ] @@ -2314,11 +2311,11 @@ describe('Unit: Prebid Module', function () { adUnits: [ { code: 'twin', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [], }, { code: 'twin', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [], ortb2Imp: { ext: { @@ -2336,7 +2333,7 @@ describe('Unit: Prebid Module', function () { adUnits: [ { code: 'twin', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [], ortb2Imp: { ext: { @@ -2345,7 +2342,7 @@ describe('Unit: Prebid Module', function () { } }, { code: 'twin', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [], ortb2Imp: { ext: { @@ -2363,16 +2360,16 @@ describe('Unit: Prebid Module', function () { adUnits: [ { code: 'single', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] }, { code: 'twin', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] }, { code: 'twin', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] } ] @@ -2406,7 +2403,7 @@ describe('Unit: Prebid Module', function () { it('should be set to ortb2Imp.ext.tid, if specified', async () => { await runAuction({ adUnits: [ - {...adUnit, ortb2Imp: {ext: {tid: 'custom-tid'}}} + { ...adUnit, ortb2Imp: { ext: { tid: 'custom-tid' } } } ] }); sinon.assert.match(auctionArgs.adUnits[0], { @@ -2435,11 +2432,11 @@ describe('Unit: Prebid Module', function () { adUnits: [ { code: 'test1', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] }, { code: 'test2', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] } ] @@ -2459,11 +2456,11 @@ describe('Unit: Prebid Module', function () { adUnits: [ { code: 'test1', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] }, { code: 'test2', - mediaTypes: {banner: {sizes: []}}, + mediaTypes: { banner: { sizes: [] } }, bids: [] } ] @@ -2723,7 +2720,7 @@ describe('Unit: Prebid Module', function () { }); ['ortb2Imp.banner.format', 'mediaTypes.banner.format'].forEach(prop => { it(`should accept ${prop} instead of sizes`, async () => { - deepSetValue(au, prop, [{w: 123, h: 321}, {w: 444, h: 555}]); + deepSetValue(au, prop, [{ w: 123, h: 321 }, { w: 444, h: 555 }]); await runAuction({ adUnits: [au] }) @@ -2731,7 +2728,7 @@ describe('Unit: Prebid Module', function () { }); it(`should make ${prop} available under both mediaTypes.banner and ortb2Imp.format`, async () => { - const format = [{w: 123, h: 321}]; + const format = [{ w: 123, h: 321 }]; deepSetValue(au, prop, format); await runAuction({ adUnits: [au] @@ -2741,14 +2738,14 @@ describe('Unit: Prebid Module', function () { }) it(`should transform wratio/hratio from ${prop} into placeholder sizes`, async () => { - deepSetValue(au, prop, [{w: 123, h: 321}, {wratio: 2, hratio: 1}]); + deepSetValue(au, prop, [{ w: 123, h: 321 }, { wratio: 2, hratio: 1 }]); await runAuction({ adUnits: [au] }) expect(auctionArgs.adUnits[0].mediaTypes.banner.sizes).to.deep.equal([[123, 321], [2, 1]]); }); it(`should ignore ${prop} elements that specify both w/h and wratio/hratio`, async () => { - deepSetValue(au, prop, [{w: 333, hratio: 2}, {w: 123, h: 321}]); + deepSetValue(au, prop, [{ w: 333, hratio: 2 }, { w: 123, h: 321 }]); await runAuction({ adUnits: [au] }) @@ -2756,7 +2753,7 @@ describe('Unit: Prebid Module', function () { }); it('should ignore incomplete formats', async () => { - deepSetValue(au, prop, [{w: 123, h: 321}, {w: 123}, {wratio: 2}]); + deepSetValue(au, prop, [{ w: 123, h: 321 }, { w: 123 }, { wratio: 2 }]); await runAuction({ adUnits: [au] }) @@ -2890,9 +2887,9 @@ describe('Unit: Prebid Module', function () { if (FEATURES.NATIVE) { Object.entries({ missing: {}, - negative: {id: -1}, - 'not an integer': {id: 1.23}, - NaN: {id: 'garbage'} + negative: { id: -1 }, + 'not an integer': { id: 1.23 }, + NaN: { id: 'garbage' } }).forEach(([t, props]) => { it(`should reject native ortb when asset ID is ${t}`, async () => { const adUnit = { @@ -2904,7 +2901,7 @@ describe('Unit: Prebid Module', function () { } } }, - bids: [{bidder: 'appnexus'}] + bids: [{ bidder: 'appnexus' }] }; await runAuction({ adUnits: [adUnit] @@ -2923,7 +2920,7 @@ describe('Unit: Prebid Module', function () { [key]: {} } }, - bids: [{bidder: 'appnexus'}] + bids: [{ bidder: 'appnexus' }] }; await runAuction({ adUnits: [adUnit] @@ -2941,7 +2938,7 @@ describe('Unit: Prebid Module', function () { sizes: [300, 400] } }, - bids: [{code: 'appnexus', params: 1234}] + bids: [{ code: 'appnexus', params: 1234 }] }, { code: 'bad-ad-unit-2', mediaTypes: { @@ -2979,12 +2976,12 @@ describe('Unit: Prebid Module', function () { }, sizes: [[300, 250], [300, 600]], bids: [ - {bidder: 'appnexus', params: {placementId: 'id'}}, - {bidder: 'sampleBidder', params: {placementId: 'banner-only-bidder'}} + { bidder: 'appnexus', params: { placementId: 'id' } }, + { bidder: 'sampleBidder', params: { placementId: 'banner-only-bidder' } } ] }]; adUnitCodes = ['adUnit-code']; - configObj.setConfig({maxRequestsPerOrigin: Number.MAX_SAFE_INTEGER || 99999999}); + configObj.setConfig({ maxRequestsPerOrigin: Number.MAX_SAFE_INTEGER || 99999999 }); auctionStarted = new Promise(resolve => { sinon.stub(adapterManager, 'callBids').callsFake(function() { resolve(); @@ -2998,7 +2995,7 @@ describe('Unit: Prebid Module', function () { }); it('bidders that support one of the declared formats are allowed to participate', async function () { - pbjs.requestBids({adUnits}); + pbjs.requestBids({ adUnits }); await auctionStarted; sinon.assert.calledOnce(adapterManager.callBids); @@ -3012,7 +3009,7 @@ describe('Unit: Prebid Module', function () { it('bidders that do not support one of the declared formats are dropped', async function () { delete adUnits[0].mediaTypes.banner; - pbjs.requestBids({adUnits}); + pbjs.requestBids({ adUnits }); await auctionStarted; sinon.assert.calledOnce(adapterManager.callBids); @@ -3029,7 +3026,7 @@ describe('Unit: Prebid Module', function () { ortb2Imp: {} }); - pbjs.requestBids({adUnits}); + pbjs.requestBids({ adUnits }); await auctionStarted; expect(adapterManager.callBids.getCall(0).args[0][0].bids.length).to.eql(2); }) @@ -3067,34 +3064,34 @@ describe('Unit: Prebid Module', function () { code: 'adUnit-code', mediaTypes: { native: {} }, bids: [ - {bidder: 'appnexus', params: {placementId: '10433394'}} + { bidder: 'appnexus', params: { placementId: '10433394' } } ] }]; - await runAuction({adUnits}); + await runAuction({ adUnits }); sinon.assert.calledOnce(adapterManager.callBids); }); it('should call callBids function on adapterManager', async function () { adUnits = [{ code: 'adUnit-code', - mediaTypes: {banner: {sizes: [[300, 250], [300, 600]]}}, + mediaTypes: { banner: { sizes: [[300, 250], [300, 600]] } }, bids: [ - {bidder: 'appnexus', params: {placementId: '10433394'}} + { bidder: 'appnexus', params: { placementId: '10433394' } } ] }]; - await runAuction({adUnits}); + await runAuction({ adUnits }); assert.ok(spyCallBids.called, 'called adapterManager.callBids'); }); it('splits native type to individual native assets', async function () { adUnits = [{ code: 'adUnit-code', - mediaTypes: {native: {type: 'image'}}, + mediaTypes: { native: { type: 'image' } }, bids: [ - {bidder: 'appnexus', params: {placementId: 'id'}} + { bidder: 'appnexus', params: { placementId: 'id' } } ] }]; - await runAuction({adUnits}); + await runAuction({ adUnits }); const spyArgs = adapterManager.callBids.getCall(0); const nativeRequest = spyArgs.args[1][0].bids[0].nativeParams; expect(nativeRequest.ortb.assets).to.deep.equal([ @@ -3149,13 +3146,13 @@ describe('Unit: Prebid Module', function () { return adUnit.code === '/19968336/header-bid-tag1'; }); const adUnitCodes1 = getAdUnits().map(unit => unit.code); - const auction1 = auctionManagerInstance.createAuction({adUnits: adUnits1, adUnitCodes: adUnitCodes1}); + const auction1 = auctionManagerInstance.createAuction({ adUnits: adUnits1, adUnitCodes: adUnitCodes1 }); const adUnits2 = getAdUnits().filter((adUnit) => { return adUnit.code === '/19968336/header-bid-tag-0'; }); const adUnitCodes2 = getAdUnits().map(unit => unit.code); - const auction2 = auctionManagerInstance.createAuction({adUnits: adUnits2, adUnitCodes: adUnitCodes2}); + const auction2 = auctionManagerInstance.createAuction({ adUnits: adUnits2, adUnitCodes: adUnitCodes2 }); let spyCallBids; auction1.getBidRequests = function() { @@ -3226,7 +3223,7 @@ describe('Unit: Prebid Module', function () { }; assert.equal(auctionManager.getBidsReceived().length, 8, '_bidsReceived contains 8 bids'); - pbjs.setConfig({ targetingControls: {allBidsCustomTargeting: true }}); + pbjs.setConfig({ targetingControls: { allBidsCustomTargeting: true } }); pbjs.requestBids(requestObj1); pbjs.requestBids(requestObj2); await auctionsStarted; @@ -3921,7 +3918,7 @@ describe('Unit: Prebid Module', function () { Object.entries({ 'events=true': { mark(options = {}) { - pbjs.markWinningBidAsUsed(Object.assign({events: true}, options)) + pbjs.markWinningBidAsUsed(Object.assign({ events: true }, options)) }, checkBidWon() { sinon.assert.calledWith(events.emit, EVENTS.BID_WON, markedBid); @@ -3935,7 +3932,7 @@ describe('Unit: Prebid Module', function () { sinon.assert.notCalled(events.emit) } } - }).forEach(([t, {mark, checkBidWon}]) => { + }).forEach(([t, { mark, checkBidWon }]) => { describe(`when ${t}`, () => { it('marks the bid object as used for the given adUnitCode/adId combination', function () { mark({ adUnitCode, adId: winningBid.adId }); @@ -4102,10 +4099,10 @@ describe('Unit: Prebid Module', function () { it('should warn and return prebid auction winning bids', function () { const bidsReceived = [ - createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'targetingSet', requestId: 'reqid-1'}), - createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2', requestId: 'reqid-2'}), - createBidReceived({bidder: 'appnexus', cpm: 6, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3', requestId: 'reqid-3'}), - createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4', requestId: 'reqid-4'}), + createBidReceived({ bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'targetingSet', requestId: 'reqid-1' }), + createBidReceived({ bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2', requestId: 'reqid-2' }), + createBidReceived({ bidder: 'appnexus', cpm: 6, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-3', requestId: 'reqid-3' }), + createBidReceived({ bidder: 'rubicon', cpm: 6, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4', requestId: 'reqid-4' }), ]; auctionManagerStub.returns(bidsReceived) const bids = pbjs.getAllPrebidWinningBids(); @@ -4120,14 +4117,14 @@ describe('Unit: Prebid Module', function () { let bid; beforeEach(function () { - bid = { adapterCode: 'pubmatic', bidder: 'pubmatic', params: {placementId: '10433394'}, adUnitCode: 'adUnit-code-1', adUnitId: '1234567890', adId: 'abcdefg' }; + bid = { adapterCode: 'pubmatic', bidder: 'pubmatic', params: { placementId: '10433394' }, adUnitCode: 'adUnit-code-1', adUnitId: '1234567890', adId: 'abcdefg' }; sandbox.spy(adapterManager, 'triggerBilling'); sandbox.stub(auctionManager, 'getAllWinningBids').returns([bid]); }); Object.entries({ 'bid': () => bid, - 'adUnitCode': () => ({adUnitCode: bid.adUnitCode}) + 'adUnitCode': () => ({ adUnitCode: bid.adUnitCode }) }).forEach(([t, val]) => { it(`should trigger billing when invoked with ${t}`, () => { pbjs.triggerBilling(val()); diff --git a/test/spec/unit/secureCreatives_spec.js b/test/spec/unit/secureCreatives_spec.js index 5be5bca5f39..d451424772d 100644 --- a/test/spec/unit/secureCreatives_spec.js +++ b/test/spec/unit/secureCreatives_spec.js @@ -1,22 +1,22 @@ -import {getReplier, receiveMessage, resizeAnchor, resizeRemoteCreative} from 'src/secureCreatives.js'; +import { getReplier, receiveMessage, resizeAnchor, resizeRemoteCreative } from 'src/secureCreatives.js'; import * as utils from 'src/utils.js'; -import {getAdUnits, getBidRequests, getBidResponses} from 'test/fixtures/fixtures.js'; -import {auctionManager} from 'src/auctionManager.js'; +import { getAdUnits, getBidRequests, getBidResponses } from 'test/fixtures/fixtures.js'; +import { auctionManager } from 'src/auctionManager.js'; import * as auctionModule from 'src/auction.js'; import * as native from 'src/native.js'; -import {fireNativeTrackers, getAllAssetsMessage} from 'src/native.js'; +import { fireNativeTrackers, getAllAssetsMessage } from 'src/native.js'; import * as events from 'src/events.js'; -import {config as configObj} from 'src/config.js'; +import { config as configObj } from 'src/config.js'; import * as creativeRenderers from 'src/creativeRenderers.js'; import 'src/prebid.js'; import 'modules/nativeRendering.js'; import * as adUnits from 'src/utils/adUnits'; -import {expect} from 'chai'; +import { expect } from 'chai'; -import {AD_RENDER_FAILED_REASON, BID_STATUS, EVENTS} from 'src/constants.js'; -import {PUC_MIN_VERSION} from 'src/creativeRenderers.js'; -import {getGlobal} from '../../../src/prebidGlobal.js'; +import { AD_RENDER_FAILED_REASON, BID_STATUS, EVENTS } from 'src/constants.js'; +import { PUC_MIN_VERSION } from 'src/creativeRenderers.js'; +import { getGlobal } from '../../../src/prebidGlobal.js'; describe('secureCreatives', () => { let sandbox; @@ -30,7 +30,7 @@ describe('secureCreatives', () => { }); function makeEvent(ev) { - return Object.assign({origin: 'mock-origin', ports: []}, ev) + return Object.assign({ origin: 'mock-origin', ports: [] }, ev) } function receive(ev) { @@ -125,7 +125,7 @@ describe('secureCreatives', () => { const adUnitCodes = getAdUnits().map(unit => unit.code); const bidsBackHandler = function() {}; const timeout = 2000; - auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout: timeout}); + auction = auctionManager.createAuction({ adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout: timeout }); resetAuction(); }); @@ -150,7 +150,7 @@ describe('secureCreatives', () => { describe('Prebid Request', function() { it('should render', function () { pushBidResponseToAuction({ - renderer: {render: sinon.stub(), url: 'some url'} + renderer: { render: sinon.stub(), url: 'some url' } }); const data = { @@ -177,7 +177,7 @@ describe('secureCreatives', () => { it('should allow stale rendering without config', function () { pushBidResponseToAuction({ - renderer: {render: sinon.stub(), url: 'some url'} + renderer: { render: sinon.stub(), url: 'some url' } }); const data = { @@ -209,10 +209,10 @@ describe('secureCreatives', () => { }); it('should stop stale rendering with config', function () { - configObj.setConfig({'auctionOptions': {'suppressStaleRender': true}}); + configObj.setConfig({ 'auctionOptions': { 'suppressStaleRender': true } }); pushBidResponseToAuction({ - renderer: {render: sinon.stub(), url: 'some url'} + renderer: { render: sinon.stub(), url: 'some url' } }); const data = { @@ -243,7 +243,7 @@ describe('secureCreatives', () => { sinon.assert.notCalled(adResponse.renderer.render); sinon.assert.neverCalledWith(stubEmit, EVENTS.BID_WON, adResponse); sinon.assert.calledWith(stubEmit, EVENTS.STALE_RENDER, adResponse); - configObj.setConfig({'auctionOptions': {}}); + configObj.setConfig({ 'auctionOptions': {} }); }); }); @@ -288,11 +288,11 @@ describe('secureCreatives', () => { source: { postMessage: sinon.stub() }, - data: JSON.stringify({adId: bidId, message: 'Prebid Request'}) + data: JSON.stringify({ adId: bidId, message: 'Prebid Request' }) }); return receive(ev).then(() => { sinon.assert.calledWith(ev.source.postMessage, sinon.match(ob => { - const {renderer, rendererVersion} = JSON.parse(ob); + const { renderer, rendererVersion } = JSON.parse(ob); return renderer === 'mock-renderer' && rendererVersion === PUC_MIN_VERSION; })); }); @@ -323,7 +323,7 @@ describe('secureCreatives', () => { source: { postMessage: sinon.stub() }, - data: JSON.stringify({adId: bidId, message: 'Prebid Request'}) + data: JSON.stringify({ adId: bidId, message: 'Prebid Request' }) }) return receive(ev).then(() => { sinon.assert.calledWith(ev.source.postMessage, sinon.match(ob => { @@ -335,7 +335,7 @@ describe('secureCreatives', () => { adTemplate: bid.native.adTemplate, rendererUrl: bid.native.rendererUrl, }) - expect(Object.fromEntries(native.assets.map(({key, value}) => [key, value]))).to.eql({ + expect(Object.fromEntries(native.assets.map(({ key, value }) => [key, value]))).to.eql({ adTemplate: bid.native.adTemplate, rendererUrl: bid.native.rendererUrl, body: 'vbody' @@ -645,7 +645,7 @@ describe('secureCreatives', () => { it('should not change dimensions until they have been set externally', () => { const pm = resizeAnchor(ins, 100, 200); clock.tick(200); - expect(ins.style).to.eql({width: 'auto', height: 'auto'}); + expect(ins.style).to.eql({ width: 'auto', height: 'auto' }); setSize(); clock.tick(200); return pm.then(() => { diff --git a/test/spec/utils/adUnits_spec.js b/test/spec/utils/adUnits_spec.js index 89e11232359..f2652baf3a0 100644 --- a/test/spec/utils/adUnits_spec.js +++ b/test/spec/utils/adUnits_spec.js @@ -1,4 +1,4 @@ -import {getAdUnitElement} from '../../../src/utils/adUnits.js'; +import { getAdUnitElement } from '../../../src/utils/adUnits.js'; describe('ad unit utils', () => { let sandbox; @@ -10,7 +10,7 @@ describe('ad unit utils', () => { }); describe('getAdUnitElement', () => { beforeEach(() => { - sandbox.stub(document, 'getElementById').callsFake((id) => ({id})); + sandbox.stub(document, 'getElementById').callsFake((id) => ({ id })); }); it('should return null on invalid input', () => { expect(getAdUnitElement({})).to.eql(null); From 69b42b5f74e384e59e4f3f01a67e46fd1a4b2136 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Tue, 10 Mar 2026 16:29:41 -0400 Subject: [PATCH 31/48] Prebid 11: document encouraging TypeScript for new source files (#14488) * Docs: require TypeScript for new src/modules/libraries files * Encourage TypeScript for new files in specific directories Rephrase recommendation for TypeScript usage in new files. * Update PR_REVIEW.md * CI: comment on newly added JS files in TS paths (#14526) * Reword to focus on public interface * Update linter.yml Linter check comment --------- Co-authored-by: Demetrio Girardi --- .github/workflows/linter.yml | 40 +++++++++++++++++++++++++++--------- AGENTS.md | 1 + CONTRIBUTING.md | 3 +++ PR_REVIEW.md | 1 + 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index e4a736c0b25..96d4f027324 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v6 with: - node-version: '20' + node-version: "20" - name: Checkout code uses: actions/checkout@v6 @@ -35,6 +35,9 @@ jobs: - name: Get the diff run: git diff --name-only origin/${{ github.event.pull_request.base.ref }}...refs/remotes/pull/${{ github.event.pull_request.number }}/merge | grep '^\(modules\|src\|libraries\|creative\)/.*\.js$' > __changed_files.txt || true + - name: Get newly added JS files in TS migration paths + run: git diff --name-only --diff-filter=A origin/${{ github.event.pull_request.base.ref }}...refs/remotes/pull/${{ github.event.pull_request.number }}/merge | grep '^\(modules\|src\|libraries\)/.*\.js$' > __new_js_files.txt || true + - name: Run linter on base branch run: npx eslint --no-inline-config --format json $(cat __changed_files.txt | xargs stat --printf '%n\n' 2> /dev/null) > __base.json || true @@ -56,7 +59,7 @@ jobs: const fs = require('fs'); const path = require('path'); const process = require('process'); - + function parse(fn) { return JSON.parse(fs.readFileSync(fn)).reduce((memo, data) => { const file = path.relative(process.cwd(), data.filePath); @@ -67,7 +70,7 @@ jobs: return memo; }, {}) } - + function mkDiff(old, new_) { const files = Object.fromEntries( Object.entries(new_) @@ -83,12 +86,23 @@ jobs: return memo; }, {errors: 0, warnings: 0, files}) } - - function mkComment({errors, warnings, files}) { + + function mkComment({errors, warnings, files}, newJsFiles) { function pl(noun, number) { return noun + (number === 1 ? '' : 's') } - if (errors === 0 && warnings === 0) return; + const comments = []; + + if (newJsFiles.length > 0) { + let jsComment = 'Whoa there partner! This project is migrating to typescript. Consider changing the new JS files to TS, with well-defined types for what interacts with the prebid public API (for example: bid params and configuration). Thanks!\n\n'; + newJsFiles.forEach((file) => { + jsComment += ` * \`${file}\`\n`; + }); + comments.push(jsComment); + } + + if (errors === 0 && warnings === 0) return comments.length > 0 ? comments.join('\n') : undefined; + const summary = []; if (errors) summary.push(`**${errors}** linter ${pl('error', errors)}`) if (warnings) summary.push(`**${warnings}** linter ${pl('warning', warnings)}`) @@ -99,12 +113,18 @@ jobs: if (warnings) summary.push(`+${warnings} ${pl('warning', warnings)}`) cm += ` * \`${file}\` (${summary.join(', ')})\n` }) - return cm; + comments.push(cm); + return comments.join('\n'); + } + + function readLines(fn) { + if (!fs.existsSync(fn)) return []; + return fs.readFileSync(fn, 'utf8').split('\n').map(line => line.trim()).filter(Boolean); } - + const [base, pr] = ['__base.json', '__pr.json'].map(parse); - const comment = mkComment(mkDiff(base, pr)); - + const comment = mkComment(mkDiff(base, pr), readLines('__new_js_files.txt')); + if (comment) { fs.writeFileSync("${{ runner.temp }}/comment.json", JSON.stringify({ issue_number: context.issue.number, diff --git a/AGENTS.md b/AGENTS.md index c340fee56ff..8e285fd5135 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,6 +21,7 @@ This file contains instructions for the Codex agent and its friends when working ## General guidance - Node.js `>=20` is required; dependencies are managed with `npm`. +- Whenever possible, new modules should provide Typescript types for their public interface. - Added or modified code must have at least 80% unit test coverage. - Link any required documentation PRs in the PR description. - Avoid modifying files in `node_modules` or generated build artifacts under `build`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b7a797beeb4..8ff2fd54055 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,6 +6,9 @@ master branch. Pull requests must have 80% code coverage before being considered for merge. Additional details about the process can be found [here](./PR_REVIEW.md). +Whenever possible, new modules should provide Typescript types for their public interface. +Examples of public interface are bid parameters and configuration (including configuration for analytics, userId, or real time data modules). + There are more details available if you'd like to contribute a [bid adapter](https://docs.prebid.org/dev-docs/bidder-adaptor.html) or [analytics adapter](https://docs.prebid.org/dev-docs/integrate-with-the-prebid-analytics-api.html). ## Issues diff --git a/PR_REVIEW.md b/PR_REVIEW.md index 94fe06c0f0c..75e3e0b35a6 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -19,6 +19,7 @@ General gulp commands include separate commands for serving the codebase on a bu ### General PR review Process +- Whenever possible, new modules should provide Typescript types for their public interface. Examples of public interface are bid parameters and configuration (including configuration for analytics, userId, or real time data modules). - All required global and bidder-adapter rules defined in the [Module Rules](https://docs.prebid.org/dev-docs/module-rules.html) must be followed. Please review these rules often - we depend on reviewers to enforce them. - Checkout the branch (these instructions are available on the GitHub PR page as well). - Verify PR is a single change type. Example, refactor OR bugfix. If more than 1 type, ask submitter to break out requests. From 89950b53906a8a3b0f7e97869d50f5e2152a1524 Mon Sep 17 00:00:00 2001 From: mkomorski Date: Wed, 11 Mar 2026 01:09:08 +0100 Subject: [PATCH 32/48] Prebid 11: Bid viewability event trackers (#14505) * Prebid 11: Bid viewability event trackers * naming conflict fix * sspBCBidAdapter vurls fallback * removing firePixels config, fixing event listener, removing gdpr, adding lib spec file * native & js handling * lint * revert adapter changes * revert * remove gpt impression listener first * sspBCBidAdapter refactor * sspBCBidAdapter tests fix * missing import * Update bidViewability.js --------- Co-authored-by: Patrick McCann --- libraries/bidViewabilityPixels/index.js | 47 +++++ modules/bidViewability.js | 40 +--- modules/bidViewabilityIO.js | 2 + modules/sspBCBidAdapter.js | 2 + .../libraries/bidViewabilityPixels_spec.js | 178 ++++++++++++++++++ test/spec/modules/bidViewabilityIO_spec.js | 46 +++++ test/spec/modules/bidViewability_spec.js | 126 +------------ test/spec/modules/sspBCBidAdapter_spec.js | 8 +- 8 files changed, 293 insertions(+), 156 deletions(-) create mode 100644 libraries/bidViewabilityPixels/index.js create mode 100644 test/spec/libraries/bidViewabilityPixels_spec.js diff --git a/libraries/bidViewabilityPixels/index.js b/libraries/bidViewabilityPixels/index.js new file mode 100644 index 00000000000..1114e608548 --- /dev/null +++ b/libraries/bidViewabilityPixels/index.js @@ -0,0 +1,47 @@ +import { EVENT_TYPE_VIEWABLE, parseEventTrackers, TRACKER_METHOD_IMG, TRACKER_METHOD_JS } from '../../src/eventTrackers.js'; +import { filterEventTrackers, legacyPropertiesToOrtbNative } from '../../src/native.js'; +import { triggerPixel, insertHtmlIntoIframe } from '../../src/utils.js'; + +/** + * Collects viewable tracking URLs from bid.eventtrackers for EVENT_TYPE_VIEWABLE (IMG and JS methods). + * @param {Object} bid - bid object that may have eventtrackers array + * @returns {{ img: string[], js: string[] }} img and js URLs to fire + */ +export function getViewabilityTrackersFromBid(bid) { + const eventTrackers = bid?.eventtrackers; + if (!eventTrackers || !Array.isArray(eventTrackers)) return { img: [], js: [] }; + const parsed = parseEventTrackers(eventTrackers); + const viewableTrackers = parsed[EVENT_TYPE_VIEWABLE]; + if (!viewableTrackers || typeof viewableTrackers !== 'object') return { img: [], js: [] }; + const img = viewableTrackers[TRACKER_METHOD_IMG]; + const js = viewableTrackers[TRACKER_METHOD_JS]; + return { + img: Array.isArray(img) ? img : [], + js: Array.isArray(js) ? js : [] + }; +} + +/** + * Fires viewability trackers for a bid. IMG URLs via triggerPixel, JS URLs via insertHtmlIntoIframe (script tag). + * Uses EVENT_TYPE_VIEWABLE trackers only (both TRACKER_METHOD_IMG and TRACKER_METHOD_JS). + * @param {Object} bid - bid with eventtrackers + */ +export function fireViewabilityPixels(bid) { + let { img, js } = getViewabilityTrackersFromBid(bid); + + const nativeResponse = bid.native && (bid?.native?.ortb || legacyPropertiesToOrtbNative(bid.native)); + if (nativeResponse && nativeResponse.eventtrackers) { + const filteredEventTrackers = filterEventTrackers(nativeResponse, bid); + const { [TRACKER_METHOD_IMG]: nativeImg = [], [TRACKER_METHOD_JS]: nativeJs = [] } = parseEventTrackers( + filteredEventTrackers || [] + )[EVENT_TYPE_VIEWABLE] || {}; + img = img.concat(Array.isArray(nativeImg) ? nativeImg : []); + js = js.concat(Array.isArray(nativeJs) ? nativeJs : []); + } + + img.forEach(triggerPixel); + if (js.length > 0) { + const markup = js.map(url => ``).join('\n'); + insertHtmlIntoIframe(markup); + } +} diff --git a/modules/bidViewability.js b/modules/bidViewability.js index d1a4640b991..0b367b6d149 100644 --- a/modules/bidViewability.js +++ b/modules/bidViewability.js @@ -5,15 +5,13 @@ import { config } from '../src/config.js'; import * as events from '../src/events.js'; import { EVENTS } from '../src/constants.js'; -import { isAdUnitCodeMatchingSlot, logWarn, triggerPixel } from '../src/utils.js'; +import { isAdUnitCodeMatchingSlot, logWarn } from '../src/utils.js'; import { getGlobal } from '../src/prebidGlobal.js'; -import adapterManager, { gppDataHandler, uspDataHandler } from '../src/adapterManager.js'; -import { gdprParams } from '../libraries/dfpUtils/dfpUtils.js'; +import adapterManager from '../src/adapterManager.js'; +import { fireViewabilityPixels } from '../libraries/bidViewabilityPixels/index.js'; const MODULE_NAME = 'bidViewability'; const CONFIG_ENABLED = 'enabled'; -const CONFIG_FIRE_PIXELS = 'firePixels'; -const BID_VURL_ARRAY = 'vurls'; const GPT_IMPRESSION_VIEWABLE_EVENT = 'impressionViewable'; export const getMatchingWinningBidForGPTSlot = (slot) => { @@ -24,33 +22,6 @@ export const getMatchingWinningBidForGPTSlot = (slot) => { ) || null; }; -export const fireViewabilityPixels = (globalModuleConfig, bid) => { - if (globalModuleConfig[CONFIG_FIRE_PIXELS] === true && bid.hasOwnProperty(BID_VURL_ARRAY)) { - const queryParams = gdprParams(); - - const uspConsent = uspDataHandler.getConsentData(); - if (uspConsent) { queryParams.us_privacy = uspConsent; } - - const gppConsent = gppDataHandler.getConsentData(); - if (gppConsent) { - // TODO - need to know what to set here for queryParams... - } - - bid[BID_VURL_ARRAY].forEach(url => { - // add '?' if not present in URL - if (Object.keys(queryParams).length > 0 && url.indexOf('?') === -1) { - url += '?'; - } - // append all query params, `&key=urlEncoded(value)` - url += Object.keys(queryParams).reduce((prev, key) => { - prev += `&${key}=${encodeURIComponent(queryParams[key])}`; - return prev; - }, ''); - triggerPixel(url) - }); - } -}; - export const logWinningBidNotFound = (slot) => { logWarn(`bid details could not be found for ${slot.getSlotElementId()}, probable reasons: a non-prebid bid is served OR check the prebid.AdUnit.code to GPT.AdSlot relation.`); }; @@ -62,8 +33,7 @@ export const impressionViewableHandler = (globalModuleConfig, event) => { if (respectiveBid === null) { logWinningBidNotFound(slot); } else { - // if config is enabled AND VURL array is present then execute each pixel - fireViewabilityPixels(globalModuleConfig, respectiveBid); + fireViewabilityPixels(respectiveBid); // trigger respective bidder's onBidViewable handler adapterManager.callBidViewableBidder(respectiveBid.adapterCode || respectiveBid.bidder, respectiveBid); @@ -84,7 +54,6 @@ const handleSetConfig = (config) => { // do nothing if module-config.enabled is not set to true // this way we are adding a way for bidders to know (using pbjs.getConfig('bidViewability').enabled === true) whether this module is added in build and is enabled const impressionViewableHandlerWrapper = (event) => { - window.googletag.pubads().removeEventListener(GPT_IMPRESSION_VIEWABLE_EVENT, impressionViewableHandlerWrapper); impressionViewableHandler(globalModuleConfig, event); }; @@ -96,6 +65,7 @@ const handleSetConfig = (config) => { } // add the GPT event listener window.googletag.cmd.push(() => { + window.googletag.pubads().removeEventListener(GPT_IMPRESSION_VIEWABLE_EVENT, impressionViewableHandlerWrapper); window.googletag.pubads().addEventListener(GPT_IMPRESSION_VIEWABLE_EVENT, impressionViewableHandlerWrapper); }); } diff --git a/modules/bidViewabilityIO.js b/modules/bidViewabilityIO.js index 5281c82f130..5e7480654d6 100644 --- a/modules/bidViewabilityIO.js +++ b/modules/bidViewabilityIO.js @@ -2,6 +2,7 @@ import { logMessage } from '../src/utils.js'; import { config } from '../src/config.js'; import * as events from '../src/events.js'; import { EVENTS } from '../src/constants.js'; +import { fireViewabilityPixels } from '../libraries/bidViewabilityPixels/index.js'; import { getAdUnitElement } from '../src/utils/adUnits.js'; const MODULE_NAME = 'bidViewabilityIO'; @@ -43,6 +44,7 @@ export const getViewableOptions = (bid) => { export const markViewed = (bid, entry, observer) => { return () => { observer.unobserve(entry.target); + fireViewabilityPixels(bid); events.emit(EVENTS.BID_VIEWABLE, bid); _logMessage(`id: ${entry.target.getAttribute('id')} code: ${bid.adUnitCode} was viewed`); } diff --git a/modules/sspBCBidAdapter.js b/modules/sspBCBidAdapter.js index ee8c8df847f..72caeb713e4 100644 --- a/modules/sspBCBidAdapter.js +++ b/modules/sspBCBidAdapter.js @@ -6,6 +6,7 @@ import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import { getCurrencyFromBidderRequest } from '../libraries/ortb2Utils/currency.js'; +import { EVENT_TYPE_VIEWABLE, TRACKER_METHOD_IMG } from '../src/eventTrackers.js'; const BIDDER_CODE = 'sspBC'; const BIDDER_URL = 'https://ssp.wp.pl/bidder/'; @@ -737,6 +738,7 @@ const spec = { }, netRevenue: true, vurls, + eventtrackers: vurls.map(url => ({ event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_IMG, url })), }; // mediaType and ad data for instream / native / banner diff --git a/test/spec/libraries/bidViewabilityPixels_spec.js b/test/spec/libraries/bidViewabilityPixels_spec.js new file mode 100644 index 00000000000..05f248c30ba --- /dev/null +++ b/test/spec/libraries/bidViewabilityPixels_spec.js @@ -0,0 +1,178 @@ +import { fireViewabilityPixels, getViewabilityTrackersFromBid } from 'libraries/bidViewabilityPixels/index.js'; +import * as utils from 'src/utils.js'; +import * as sinon from 'sinon'; +import { expect } from 'chai'; +import { EVENT_TYPE_IMPRESSION, EVENT_TYPE_VIEWABLE, TRACKER_METHOD_IMG, TRACKER_METHOD_JS } from 'src/eventTrackers.js'; +import { auctionManager } from 'src/auctionManager.js'; + +const VIEWABILITY_PIXEL_URLS = [ + 'https://domain-1.com/end-point?a=1', + 'https://domain-2.com/end-point/', + 'https://domain-3.com/end-point?a=1' +]; + +const bidWithViewabilityTrackers = { + adUnitCode: 'test-unit', + bidder: 'test-bidder', + eventtrackers: VIEWABILITY_PIXEL_URLS.map(url => ({ + event: EVENT_TYPE_VIEWABLE, + method: TRACKER_METHOD_IMG, + url + })) +}; + +describe('bidViewabilityPixels library', function () { + let sandbox; + let triggerPixelSpy; + let insertHtmlIntoIframeSpy; + + beforeEach(function () { + sandbox = sinon.createSandbox(); + triggerPixelSpy = sandbox.spy(utils, 'triggerPixel'); + insertHtmlIntoIframeSpy = sandbox.spy(utils, 'insertHtmlIntoIframe'); + }); + + afterEach(function () { + sandbox.restore(); + }); + + describe('getViewabilityTrackersFromBid', function () { + it('should return { img: [], js: [] } when bid is null, undefined, or has no valid eventtrackers', function () { + const empty = { img: [], js: [] }; + expect(getViewabilityTrackersFromBid(null)).to.deep.equal(empty); + expect(getViewabilityTrackersFromBid(undefined)).to.deep.equal(empty); + expect(getViewabilityTrackersFromBid({ adUnitCode: 'x' })).to.deep.equal(empty); + expect(getViewabilityTrackersFromBid({ eventtrackers: {} })).to.deep.equal(empty); + expect(getViewabilityTrackersFromBid({ eventtrackers: 'trackers' })).to.deep.equal(empty); + expect(getViewabilityTrackersFromBid({ eventtrackers: [] })).to.deep.equal(empty); + }); + + it('should return img and js URLs for viewable trackers', function () { + const bid = { + eventtrackers: [ + { event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_IMG, url: 'https://img.com' }, + { event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_JS, url: 'https://js.com' } + ] + }; + expect(getViewabilityTrackersFromBid(bid)).to.deep.equal({ + img: ['https://img.com'], + js: ['https://js.com'] + }); + }); + + it('should return only viewable trackers when eventtrackers has mixed event types', function () { + const bid = { + eventtrackers: [ + { event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_IMG, url: 'https://viewable.com' }, + { event: EVENT_TYPE_IMPRESSION, method: TRACKER_METHOD_IMG, url: 'https://impression.com' } + ] + }; + expect(getViewabilityTrackersFromBid(bid)).to.deep.equal({ + img: ['https://viewable.com'], + js: [] + }); + }); + + it('should return only js when viewable trackers have JS method only', function () { + const bid = { + eventtrackers: [ + { event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_JS, url: 'https://viewable-js.com' } + ] + }; + expect(getViewabilityTrackersFromBid(bid)).to.deep.equal({ + img: [], + js: ['https://viewable-js.com'] + }); + }); + }); + + describe('fireViewabilityPixels', function () { + it('should not call triggerPixel or insertHtmlIntoIframe when bid has no eventtrackers', function () { + fireViewabilityPixels({ adUnitCode: 'x' }); + expect(triggerPixelSpy.callCount).to.equal(0); + expect(insertHtmlIntoIframeSpy.callCount).to.equal(0); + }); + + it('should not call triggerPixel or insertHtmlIntoIframe when eventtrackers is empty array', function () { + fireViewabilityPixels({ eventtrackers: [] }); + expect(triggerPixelSpy.callCount).to.equal(0); + expect(insertHtmlIntoIframeSpy.callCount).to.equal(0); + }); + + it('should fire one pixel per viewable img URL in eventtrackers', function () { + fireViewabilityPixels(bidWithViewabilityTrackers); + expect(triggerPixelSpy.callCount).to.equal(VIEWABILITY_PIXEL_URLS.length); + VIEWABILITY_PIXEL_URLS.forEach((url, i) => { + expect(triggerPixelSpy.getCall(i).args[0]).to.equal(url); + }); + }); + + it('should fire viewable JS trackers via insertHtmlIntoIframe with script tag', function () { + const bid = { + eventtrackers: [ + { event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_JS, url: 'https://viewable-js.com' } + ] + }; + fireViewabilityPixels(bid); + expect(triggerPixelSpy.callCount).to.equal(0); + expect(insertHtmlIntoIframeSpy.callCount).to.equal(1); + expect(insertHtmlIntoIframeSpy.getCall(0).args[0]).to.include('script async src="https://viewable-js.com"'); + }); + + it('should fire both img (triggerPixel) and js (insertHtmlIntoIframe) viewable trackers', function () { + const bid = { + eventtrackers: [ + { event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_IMG, url: 'https://img.com' }, + { event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_JS, url: 'https://js.com' } + ] + }; + fireViewabilityPixels(bid); + expect(triggerPixelSpy.callCount).to.equal(1); + expect(triggerPixelSpy.getCall(0).args[0]).to.equal('https://img.com'); + expect(insertHtmlIntoIframeSpy.callCount).to.equal(1); + expect(insertHtmlIntoIframeSpy.getCall(0).args[0]).to.include('script async src="https://js.com"'); + }); + + it('should only fire EVENT_TYPE_VIEWABLE URLs', function () { + const bid = { + eventtrackers: [ + { event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_IMG, url: 'https://viewable-img.com' }, + { event: EVENT_TYPE_IMPRESSION, method: TRACKER_METHOD_IMG, url: 'https://impression.com' } + ] + }; + fireViewabilityPixels(bid); + expect(triggerPixelSpy.callCount).to.equal(1); + expect(triggerPixelSpy.getCall(0).args[0]).to.equal('https://viewable-img.com'); + }); + + describe('when bid has native response with eventtrackers (viewable)', function () { + let indexStub; + let getMediaTypesStub; + + beforeEach(function () { + getMediaTypesStub = sinon.stub(); + indexStub = sandbox.stub(auctionManager, 'index').get(() => ({ getMediaTypes: getMediaTypesStub })); + }); + + it('should fire viewable trackers from bid.native.ortb.eventtrackers in addition to bid.eventtrackers', function () { + getMediaTypesStub.returns({}); + const bid = { + eventtrackers: [ + { event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_IMG, url: 'https://from-bid.com' } + ], + native: { + ortb: { + eventtrackers: [ + { event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_IMG, url: 'https://from-native.com' } + ] + } + } + }; + fireViewabilityPixels(bid); + expect(triggerPixelSpy.callCount).to.equal(2); + expect(triggerPixelSpy.getCall(0).args[0]).to.equal('https://from-bid.com'); + expect(triggerPixelSpy.getCall(1).args[0]).to.equal('https://from-native.com'); + }); + }); + }); +}); diff --git a/test/spec/modules/bidViewabilityIO_spec.js b/test/spec/modules/bidViewabilityIO_spec.js index 947d9227ca5..e23e886c3d8 100644 --- a/test/spec/modules/bidViewabilityIO_spec.js +++ b/test/spec/modules/bidViewabilityIO_spec.js @@ -4,6 +4,7 @@ import * as utils from 'src/utils.js'; import * as sinon from 'sinon'; import { expect } from 'chai'; import { EVENTS } from 'src/constants.js'; +import { EVENT_TYPE_VIEWABLE, TRACKER_METHOD_IMG } from 'src/eventTrackers.js'; describe('#bidViewabilityIO', function() { const makeElement = (id) => { @@ -101,6 +102,51 @@ describe('#bidViewabilityIO', function() { }); }) + describe('viewability pixels', function() { + let sandbox; + let triggerPixelSpy; + const mockObserver = { unobserve: sinon.spy() }; + const mockEntry = { target: makeElement('pixel_target_id') }; + + const VIEWABILITY_PIXEL_URLS = [ + 'https://io-viewable-1.com/pixel', + 'https://io-viewable-2.com/track' + ]; + + const bidWithEventTrackers = { + adUnitCode: 'banner_id', + mediaType: 'banner', + width: 728, + height: 90, + eventtrackers: VIEWABILITY_PIXEL_URLS.map(url => ({ event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_IMG, url })) + }; + + beforeEach(function() { + sandbox = sinon.createSandbox(); + triggerPixelSpy = sandbox.spy(utils, ['triggerPixel']); + }); + + afterEach(function() { + sandbox.restore(); + }); + + it('fires viewability pixels when markViewed callback runs with bid that has eventTrackers (EVENT_TYPE_VIEWABLE)', function() { + const func = bidViewabilityIO.markViewed(bidWithEventTrackers, mockEntry, mockObserver); + func(); + expect(triggerPixelSpy.callCount).to.equal(VIEWABILITY_PIXEL_URLS.length); + VIEWABILITY_PIXEL_URLS.forEach((url, i) => { + expect(triggerPixelSpy.getCall(i).args[0]).to.equal(url); + }); + }); + + it('does not fire pixels when bid has empty eventTrackers', function() { + const bidWithEmptyTrackers = { ...banner_bid, eventtrackers: [] }; + const func = bidViewabilityIO.markViewed(bidWithEmptyTrackers, mockEntry, mockObserver); + func(); + expect(triggerPixelSpy.callCount).to.equal(0); + }); + }) + describe('viewCallbackFactory tests', function() { let sandbox; diff --git a/test/spec/modules/bidViewability_spec.js b/test/spec/modules/bidViewability_spec.js index da2430e9d33..11257c0d03a 100644 --- a/test/spec/modules/bidViewability_spec.js +++ b/test/spec/modules/bidViewability_spec.js @@ -8,6 +8,7 @@ import * as prebidGlobal from 'src/prebidGlobal.js'; import { EVENTS } from 'src/constants.js'; import adapterManager, { gdprDataHandler, uspDataHandler } from 'src/adapterManager.js'; import parse from 'url-parse'; +import { EVENT_TYPE_VIEWABLE, TRACKER_METHOD_IMG } from 'src/eventTrackers.js'; const GPT_SLOT = { getAdUnitPath() { @@ -23,6 +24,12 @@ const EVENT_OBJ = { slot: GPT_SLOT } +const VIEWABILITY_PIXEL_URLS = [ + 'https://domain-1.com/end-point?a=1', + 'https://domain-2.com/end-point/', + 'https://domain-3.com/end-point?a=1' +]; + const PBJS_WINNING_BID = { 'adUnitCode': '/harshad/Jan/2021/', 'bidderCode': 'pubmatic', @@ -39,11 +46,7 @@ const PBJS_WINNING_BID = { 'creativeId': 'id', 'netRevenue': true, 'currency': 'USD', - 'vurls': [ - 'https://domain-1.com/end-point?a=1', - 'https://domain-2.com/end-point/', - 'https://domain-3.com/end-point?a=1' - ] + 'eventtrackers': VIEWABILITY_PIXEL_URLS.map(url => ({ event: EVENT_TYPE_VIEWABLE, method: TRACKER_METHOD_IMG, url })) }; describe('#bidViewability', function() { @@ -111,117 +114,6 @@ describe('#bidViewability', function() { }); }); - describe('fireViewabilityPixels', function() { - let sandbox; - let triggerPixelSpy; - - beforeEach(function() { - sandbox = sinon.createSandbox(); - triggerPixelSpy = sandbox.spy(utils, ['triggerPixel']); - }); - - afterEach(function() { - sandbox.restore(); - }); - - it('DO NOT fire pixels if NOT mentioned in module config', function() { - const moduleConfig = {}; - bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); - expect(triggerPixelSpy.callCount).to.equal(0); - }); - - it('fire pixels if mentioned in module config', function() { - const moduleConfig = { firePixels: true }; - bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); - PBJS_WINNING_BID.vurls.forEach((url, i) => { - const call = triggerPixelSpy.getCall(i); - expect(call.args[0]).to.equal(url); - }); - }); - - it('USP: should include the us_privacy key when USP Consent is available', function () { - const uspDataHandlerStub = sinon.stub(uspDataHandler, 'getConsentData'); - uspDataHandlerStub.returns('1YYY'); - const moduleConfig = { firePixels: true }; - bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); - PBJS_WINNING_BID.vurls.forEach((url, i) => { - const call = triggerPixelSpy.getCall(i); - expect(call.args[0].indexOf(url)).to.equal(0); - const testurl = parse(call.args[0]); - const queryObject = utils.parseQS(testurl.query); - expect(queryObject.us_privacy).to.equal('1YYY'); - }); - uspDataHandlerStub.restore(); - }); - - it('USP: should not include the us_privacy key when USP Consent is not available', function () { - const moduleConfig = { firePixels: true }; - bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); - PBJS_WINNING_BID.vurls.forEach((url, i) => { - const call = triggerPixelSpy.getCall(i); - expect(call.args[0].indexOf(url)).to.equal(0); - const testurl = parse(call.args[0]); - const queryObject = utils.parseQS(testurl.query); - expect(queryObject.us_privacy).to.equal(undefined); - }); - }); - - it('GDPR: should include the GDPR keys when GDPR Consent is available', function() { - const gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData'); - gdprDataHandlerStub.returns({ - gdprApplies: true, - consentString: 'consent', - addtlConsent: 'moreConsent' - }); - const moduleConfig = { firePixels: true }; - bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); - PBJS_WINNING_BID.vurls.forEach((url, i) => { - const call = triggerPixelSpy.getCall(i); - expect(call.args[0].indexOf(url)).to.equal(0); - const testurl = parse(call.args[0]); - const queryObject = utils.parseQS(testurl.query); - expect(queryObject.gdpr).to.equal('1'); - expect(queryObject.gdpr_consent).to.equal('consent'); - expect(queryObject.addtl_consent).to.equal('moreConsent'); - }); - gdprDataHandlerStub.restore(); - }); - - it('GDPR: should not include the GDPR keys when GDPR Consent is not available', function () { - const moduleConfig = { firePixels: true }; - bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); - PBJS_WINNING_BID.vurls.forEach((url, i) => { - const call = triggerPixelSpy.getCall(i); - expect(call.args[0].indexOf(url)).to.equal(0); - const testurl = parse(call.args[0]); - const queryObject = utils.parseQS(testurl.query); - expect(queryObject.gdpr).to.equal(undefined); - expect(queryObject.gdpr_consent).to.equal(undefined); - expect(queryObject.addtl_consent).to.equal(undefined); - }); - }); - - it('GDPR: should only include the GDPR keys for GDPR Consent fields with values', function () { - const gdprDataHandlerStub = sinon.stub(gdprDataHandler, 'getConsentData'); - gdprDataHandlerStub.returns({ - gdprApplies: true, - consentString: 'consent' - }); - const moduleConfig = { firePixels: true }; - bidViewability.fireViewabilityPixels(moduleConfig, PBJS_WINNING_BID); - PBJS_WINNING_BID.vurls.forEach((url, i) => { - const call = triggerPixelSpy.getCall(i); - expect(call.args[0].indexOf(url)).to.equal(0); - const testurl = parse(call.args[0]); - const queryObject = utils.parseQS(testurl.query); - expect(queryObject.gdpr).to.equal('1'); - expect(queryObject.gdpr_consent).to.equal('consent'); - expect(queryObject.addtl_consent).to.equal(undefined); - }); - gdprDataHandlerStub.restore(); - }) - }); - describe('impressionViewableHandler', function() { let sandbox; let triggerPixelSpy; @@ -268,7 +160,7 @@ describe('#bidViewability', function() { winningBidsArray.push(PBJS_WINNING_BID); bidViewability.impressionViewableHandler(moduleConfig, EVENT_OBJ); // fire pixels should be called - PBJS_WINNING_BID.vurls.forEach((url, i) => { + VIEWABILITY_PIXEL_URLS.forEach((url, i) => { const call = triggerPixelSpy.getCall(i); expect(call.args[0]).to.equal(url); }); diff --git a/test/spec/modules/sspBCBidAdapter_spec.js b/test/spec/modules/sspBCBidAdapter_spec.js index 5181f0ef02a..4a893aaedb9 100644 --- a/test/spec/modules/sspBCBidAdapter_spec.js +++ b/test/spec/modules/sspBCBidAdapter_spec.js @@ -690,14 +690,14 @@ describe('SSPBC adapter', function () { expect(result.length).to.equal(bids.length); expect(resultSingle.length).to.equal(1); - expect(resultSingle[0]).to.have.keys('ad', 'cpm', 'width', 'height', 'mediaType', 'meta', 'requestId', 'creativeId', 'currency', 'netRevenue', 'ttl', 'vurls'); + expect(resultSingle[0]).to.have.keys('ad', 'cpm', 'width', 'height', 'mediaType', 'meta', 'requestId', 'creativeId', 'currency', 'netRevenue', 'ttl', 'vurls', 'eventtrackers'); }); it('should create bid from OneCode (parameter-less) request, if response contains siteId', function () { const resultOneCode = spec.interpretResponse(serverResponseOneCode, requestOneCode); expect(resultOneCode.length).to.equal(1); - expect(resultOneCode[0]).to.have.keys('ad', 'cpm', 'width', 'height', 'mediaType', 'meta', 'requestId', 'creativeId', 'currency', 'netRevenue', 'ttl', 'vurls'); + expect(resultOneCode[0]).to.have.keys('ad', 'cpm', 'width', 'height', 'mediaType', 'meta', 'requestId', 'creativeId', 'currency', 'netRevenue', 'ttl', 'vurls', 'eventtrackers'); }); it('should not create bid from OneCode (parameter-less) request, if response does not contain siteId', function () { @@ -724,7 +724,7 @@ describe('SSPBC adapter', function () { expect(resultVideo.length).to.equal(1); const videoBid = resultVideo[0]; - expect(videoBid).to.have.keys('adType', 'cpm', 'creativeId', 'currency', 'width', 'height', 'meta', 'mediaType', 'netRevenue', 'requestId', 'ttl', 'vastContent', 'vastXml', 'vastUrl', 'vurls'); + expect(videoBid).to.have.keys('adType', 'cpm', 'creativeId', 'currency', 'width', 'height', 'meta', 'mediaType', 'netRevenue', 'requestId', 'ttl', 'vastContent', 'vastXml', 'vastUrl', 'vurls', 'eventtrackers'); expect(videoBid.adType).to.equal('instream'); expect(videoBid.mediaType).to.equal('video'); expect(videoBid.vastXml).to.match(/^<\?xml.*<\/VAST>$/); @@ -738,7 +738,7 @@ describe('SSPBC adapter', function () { expect(resultNative.length).to.equal(1); const nativeBid = resultNative[0]; - expect(nativeBid).to.have.keys('cpm', 'creativeId', 'currency', 'width', 'height', 'meta', 'mediaType', 'netRevenue', 'requestId', 'ttl', 'native', 'vurls'); + expect(nativeBid).to.have.keys('cpm', 'creativeId', 'currency', 'width', 'height', 'meta', 'mediaType', 'netRevenue', 'requestId', 'ttl', 'native', 'vurls', 'eventtrackers'); expect(nativeBid.native).to.have.keys('image', 'icon', 'title', 'sponsoredBy', 'body', 'clickUrl', 'impressionTrackers', 'javascriptTrackers', 'clickTrackers'); }); From 10d5ccd78ec30f8ee1175e641ee52c21880c7832 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 11 Mar 2026 07:13:59 -0700 Subject: [PATCH 33/48] Prebid 11: remove intersectionRtdProvider, use IntersectionObserver in percentInView (#14525) * Core: add elementSelector property of ad units * core: use getAdUnitElement * various adapters: use getAdUnitElement * various modules: use getAdUnitElement * various adapters: use getAdUnitElement * use .element, not .elementSelector * lint * fix secureCreatives tests * Update ixBidAdapter.js * Remove TODO note; update type * lint * pubmaticBidAdapter: use getAdUnitElement * placement position: use getAdUnitElement * percentInView: use IntersectionObserver * adlooxRtdProvider: do not depend on intersectionObserver * remove intersectionrtdprovider * check the right element has intersected * keep size override * handle missing intersection observer * Fix tests * DOMRect weirdness * remove unnecessary sort * More aggressive static fallback * Update percentInView.js * Update percentInView.js * whitespace --------- Co-authored-by: Patrick McCann --- libraries/percentInView/percentInView.js | 100 +++++++- modules/adlooxRtdProvider.js | 9 +- modules/intersectionRtdProvider.js | 118 ---------- test/spec/libraries/percentInView_spec.js | 221 +++++++++++++++++- .../modules/intersectionRtdProvider_spec.js | 164 ------------- 5 files changed, 322 insertions(+), 290 deletions(-) delete mode 100644 modules/intersectionRtdProvider.js delete mode 100644 test/spec/modules/intersectionRtdProvider_spec.js diff --git a/libraries/percentInView/percentInView.js b/libraries/percentInView/percentInView.js index 0de3a9c257d..53028d51cc8 100644 --- a/libraries/percentInView/percentInView.js +++ b/libraries/percentInView/percentInView.js @@ -1,5 +1,8 @@ import { getWinDimensions, inIframe } from '../../src/utils.js'; import { getBoundingClientRect } from '../boundingClientRect/boundingClientRect.js'; +import { defer, PbPromise } from '../../src/utils/promise.js'; +import { startAuction } from '../../src/prebid.js'; +import { getAdUnitElement } from '../../src/utils/adUnits.js'; /** * return the offset between the given window's viewport and the top window's. @@ -24,8 +27,8 @@ export function getViewportOffset(win = window) { return { x, y }; } -export function getBoundingBox(element, { w, h } = {}) { - let { width, height, left, top, right, bottom, x, y } = getBoundingClientRect(element); +function applySize(bbox, { w, h }) { + let { width, height, left, top, right, bottom, x, y } = bbox; if ((width === 0 || height === 0) && w && h) { width = w; @@ -37,6 +40,10 @@ export function getBoundingBox(element, { w, h } = {}) { return { width, height, left, top, right, bottom, x, y }; } +export function getBoundingBox(element, { w, h } = {}) { + return applySize(getBoundingClientRect(element), { w, h }); +} + function getIntersectionOfRects(rects) { const bbox = { left: rects[0].left, right: rects[0].right, top: rects[0].top, bottom: rects[0].bottom @@ -64,7 +71,7 @@ function getIntersectionOfRects(rects) { return bbox; } -export const percentInView = (element, { w, h } = {}) => { +const percentInViewStatic = (element, { w, h } = {}) => { const elementBoundingBox = getBoundingBox(element, { w, h }); // when in an iframe, the bounding box is relative to the iframe's viewport @@ -102,6 +109,93 @@ export const percentInView = (element, { w, h } = {}) => { return 0; } +/** + * A wrapper around an IntersectionObserver that keeps track of the latest IntersectionEntry that was observed + * for each observed element. + * + * @param mkObserver + */ +export function intersections(mkObserver) { + const intersections = new WeakMap(); + let next = defer(); + function observerCallback(entries) { + entries.forEach(entry => { + if ((intersections.get(entry.target)?.time ?? -1) < entry.time) { + intersections.set(entry.target, entry) + next.resolve(); + next = defer(); + } + }) + } + + let obs = null; + try { + obs = mkObserver(observerCallback); + } catch (e) { + // IntersectionObserver not supported + } + + async function waitFor(element) { + const intersection = getIntersection(element); + if (intersection != null) { + return intersection; + } else { + return next.promise.then(() => waitFor(element)); + } + } + /** + * Observe the given element; returns a promise to the first available intersection observed for it. + */ + async function observe(element) { + if (obs != null && !intersections.has(element)) { + obs.observe(element); + intersections.set(element, null); + return waitFor(element); + } else { + return PbPromise.resolve(getIntersection(element)); + } + } + + /** + * Return the latest intersection that was observed for the given element. + */ + function getIntersection(element) { + return intersections.get(element); + } + + return { + observe, + getIntersection, + } +} + +export const viewportIntersections = intersections((callback) => new IntersectionObserver(callback)); + +export function mkIntersectionHook(intersections = viewportIntersections) { + return function (next, request) { + PbPromise.allSettled((request.adUnits ?? []).map(adUnit => + intersections.observe(getAdUnitElement(adUnit)) + )).then(() => next.call(this, request)); + } +} + +startAuction.before(mkIntersectionHook()); + +export function percentInView(element, { w, h } = {}) { + const intersection = viewportIntersections.getIntersection(element); + if (intersection == null) { + viewportIntersections.observe(element); + return percentInViewStatic(element, { w, h }); + } else { + const adjusted = applySize(intersection.boundingClientRect, { w, h }); + if (adjusted.width !== intersection.boundingClientRect.width || adjusted.height !== intersection.boundingClientRect.height) { + // use w/h override + return percentInViewStatic(element, { w, h }); + } + return intersection.isIntersecting ? intersection.intersectionRatio * 100 : 0; + } +} + /** * Checks if viewability can be measured for an element * @param {HTMLElement} element - DOM element to check diff --git a/modules/adlooxRtdProvider.js b/modules/adlooxRtdProvider.js index c991d776976..2a4e61f9f79 100644 --- a/modules/adlooxRtdProvider.js +++ b/modules/adlooxRtdProvider.js @@ -36,6 +36,8 @@ import { safeJSONParse } from '../src/utils.js'; import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js'; +import { viewportIntersections } from '../libraries/percentInView/percentInView.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const MODULE_NAME = 'adloox'; const MODULE = `${MODULE_NAME}RtdProvider`; @@ -188,10 +190,9 @@ function getTargetingData(adUnitArray, config, userConsent, auction) { if (v) targeting[unit.code][`${ADSERVER_TARGETING_PREFIX}_${k}`] = v; }); - // ATF results shamelessly exfiltrated from intersectionRtdProvider - const bid = unit.bids.find(bid => !!bid.intersection); - if (bid) { - const v = val(config.params.thresholds.filter(t => t <= (bid.intersection.intersectionRatio * 100))); + const intersection = viewportIntersections.getIntersection(getAdUnitElement(unit)); + if (intersection) { + const v = val(config.params.thresholds.filter(t => t <= (intersection.intersectionRatio * 100))); if (v) targeting[unit.code][`${ADSERVER_TARGETING_PREFIX}_atf`] = v; } }); diff --git a/modules/intersectionRtdProvider.js b/modules/intersectionRtdProvider.js deleted file mode 100644 index b57fd919d16..00000000000 --- a/modules/intersectionRtdProvider.js +++ /dev/null @@ -1,118 +0,0 @@ -import { submodule } from '../src/hook.js'; -import { isFn, logError } from '../src/utils.js'; -import { config } from '../src/config.js'; -import { getGlobal } from '../src/prebidGlobal.js'; - -import '../src/adapterManager.js'; - -let observerAvailable = true; -function getIntersectionData(requestBidsObject, onDone, providerConfig, userConsent) { - const intersectionMap = {}; - const placeholdersMap = {}; - let done = false; - if (!observerAvailable) return complete(); - const observer = new IntersectionObserver(observerCallback, { threshold: 0.5 }); - const adUnitCodes = requestBidsObject.adUnitCodes || []; - const auctionDelay = config.getConfig('realTimeData.auctionDelay') || 0; - const waitForIt = providerConfig.waitForIt; - let adUnits = requestBidsObject.adUnits || getGlobal().adUnits || []; - if (adUnitCodes.length) { - adUnits = adUnits.filter(unit => adUnitCodes.includes(unit.code)); - } - let checkTimeoutId; - findAndObservePlaceholders(); - if (auctionDelay > 0) { - setTimeout(complete, auctionDelay); - } - function findAndObservePlaceholders() { - const observed = adUnits.filter((unit) => { - const code = unit.code; - if (placeholdersMap[code]) return true; - const ph = document.getElementById(code); - if (ph) { - placeholdersMap[code] = ph; - observer.observe(ph); - return true; - } - return false; - }); - if ( - observed.length === adUnits.length || - !waitForIt || - auctionDelay <= 0 - ) { - return; - } - checkTimeoutId = setTimeout(findAndObservePlaceholders); - } - function observerCallback(entries) { - let entry = entries.pop(); - while (entry) { - const target = entry.target; - const id = target.getAttribute('id'); - if (id) { - const intersection = intersectionMap[id]; - if (!intersection || intersection.time < entry.time) { - intersectionMap[id] = { - 'boundingClientRect': cloneRect(entry.boundingClientRect), - 'intersectionRect': cloneRect(entry.intersectionRect), - 'rootRect': cloneRect(entry.rootRect), - 'intersectionRatio': entry.intersectionRatio, - 'isIntersecting': entry.isIntersecting, - 'time': entry.time - }; - if (adUnits.every(unit => !!intersectionMap[unit.code])) { - complete(); - } - } - } - entry = entries.pop(); - } - } - function complete() { - if (done) return; - if (checkTimeoutId) clearTimeout(checkTimeoutId); - done = true; - checkTimeoutId = null; - observer && observer.disconnect(); - adUnits && adUnits.forEach((unit) => { - const intersection = intersectionMap[unit.code]; - if (intersection && unit.bids) { - unit.bids.forEach(bid => { - bid.intersection = intersection; - }); - } - }); - onDone(); - } -} -function init(moduleConfig) { - if (!isFn(window.IntersectionObserver)) { - logError('IntersectionObserver is not defined'); - observerAvailable = false; - } else { - observerAvailable = true; - } - return observerAvailable; -} -function cloneRect(rect) { - return rect ? { - 'left': rect.left, - 'top': rect.top, - 'right': rect.right, - 'bottom': rect.bottom, - 'width': rect.width, - 'height': rect.height, - 'x': rect.x, - 'y': rect.y, - } : rect; -} -export const intersectionSubmodule = { - name: 'intersection', - getBidRequestData: getIntersectionData, - init: init, -}; -function registerSubModule() { - submodule('realTimeData', intersectionSubmodule); -} -registerSubModule(); diff --git a/test/spec/libraries/percentInView_spec.js b/test/spec/libraries/percentInView_spec.js index 7405e95f95d..4dd54ff99d0 100644 --- a/test/spec/libraries/percentInView_spec.js +++ b/test/spec/libraries/percentInView_spec.js @@ -1,6 +1,23 @@ -import { getViewportOffset } from '../../../libraries/percentInView/percentInView.js'; +import { + getViewportOffset, + intersections, + mkIntersectionHook, + percentInView, + viewportIntersections, +} from '../../../libraries/percentInView/percentInView.js'; +import * as bbox from 'libraries/boundingClientRect/boundingClientRect'; + +import { defer } from 'src/utils/promise.js'; describe('percentInView', () => { + let sandbox; + beforeEach(() => { + sandbox = sinon.createSandbox(); + }); + afterEach(() => { + sandbox.restore(); + }); + describe('getViewportOffset', () => { function mockWindow(offsets = []) { let win, leaf, child; @@ -17,6 +34,7 @@ describe('percentInView', () => { } return leaf; } + it('returns 0, 0 for the top window', () => { expect(getViewportOffset(mockWindow())).to.eql({ x: 0, y: 0 }); }); @@ -37,4 +55,205 @@ describe('percentInView', () => { expect(getViewportOffset(win)).to.eql({ x: 0, y: 0 }); }); }); + + async function delay() { + await new Promise(resolve => setTimeout(resolve, 10)); + } + + describe('intersections', () => { + let callback, obs, nakedObs, mkObserver, el; + beforeEach(() => { + el = document.createElement('div'); + nakedObs = sinon.stub(); + nakedObs.observe = sinon.stub(); + mkObserver = sinon.stub().callsFake((cb) => { + callback = cb; + return nakedObs; + }); + obs = intersections(mkObserver); + }); + describe('when mkObserver throws', () => { + beforeEach(() => { + mkObserver = sinon.stub().callsFake(() => { + throw new Error(); + }); + obs = intersections(mkObserver); + }); + it('getIntersection should return undef', () => { + expect(obs.getIntersection({})).to.not.exist; + }); + + it('observe should resolve', async () => { + await obs.observe({}); + }); + }); + + it('observe should reject if the element cannot be observed', async () => { + let err = new Error(); + nakedObs.observe.throws(err); + try { + await obs.observe(null); + } catch (e) { + expect(e).to.eql(err); + return; + } + sinon.assert.fail('promise should reject'); + }); + it('does not observe the same element more than once', () => { + obs.observe(el); + obs.observe(el); + sinon.assert.calledOnce(nakedObs.observe); + }); + it('getIntersection should return undefined if the element is not observed', () => { + expect(obs.getIntersection(el)).to.not.exist; + }); + it('observe should resolve to latest intersection entry', () => { + let pm = obs.observe(el); + let entry = { + target: el, + time: 100 + }; + callback([entry, { + target: el, + time: 50 + }]); + return pm.then(result => { + expect(result).to.eql(entry); + }); + }); + it('observe should resolve immediately if an entry is available', () => { + const entry = { + target: el, + time: 10 + }; + callback([entry]); + const pm = obs.observe(el); + callback([{ + target: el, + time: 20 + }]); + return pm.then((result) => { + expect(result).to.eql(entry); + }); + }); + it('should ignore stale entries', async () => { + const entry = { + target: el, + time: 100 + }; + obs.observe(el); + callback([entry]); + callback([{ + target: el, + time: 10 + }]); + expect(obs.getIntersection(el)).to.eql(entry); + }); + + it('should not resolve until the targeted element has intersected', async () => { + const entry = { + target: el, + time: 100 + }; + const pm = obs.observe(el); + callback([{ + target: {}, + time: 20 + }]); + await delay(); + callback([entry]); + expect(await pm).to.eql(entry); + }); + }); + + describe('intersection hook', () => { + let intersections, hook, next, request; + beforeEach(() => { + next = sinon.stub(); + intersections = { + observe: sinon.stub() + }; + hook = mkIntersectionHook(intersections); + request = {}; + }); + + it('should observe elements for every ad unit', async () => { + request.adUnits = [{ + element: 'el1' + }, { + code: 'el2' + }]; + sandbox.stub(document, 'getElementById').returns('el2'); + hook(next, request); + sinon.assert.calledWith(intersections.observe, 'el1'); + sinon.assert.calledWith(intersections.observe, 'el2'); + await delay(); + sinon.assert.calledWith(next, request); + }); + + describe('promise resolution', () => { + let adUnits; + beforeEach(() => { + adUnits = { + el1: { + element: 'el1', + df: defer() + }, + el2: { + element: 'el2', + df: defer() + } + }; + request.adUnits = Object.values(adUnits); + intersections.observe.callsFake((element) => adUnits[element].df.promise); + }); + it('should wait for all promises to resolve', async () => { + hook(next, request); + sinon.assert.notCalled(next); + adUnits.el1.df.resolve(); + await delay(); + sinon.assert.notCalled(next); + adUnits.el2.df.resolve(); + await delay(); + sinon.assert.calledWith(next, request); + }); + + it('should still continue if some promises reject', async () => { + hook(next, request); + adUnits.el1.df.reject(); + await delay(); + sinon.assert.notCalled(next); + adUnits.el2.df.resolve(); + await delay(); + sinon.assert.calledWith(next, request); + }); + }); + }); + + describe('percentInView', () => { + let intersection; + beforeEach(() => { + sandbox.stub(viewportIntersections, 'getIntersection').callsFake(() => intersection); + sandbox.stub(viewportIntersections, 'observe'); + sandbox.stub(bbox, 'getBoundingClientRect'); + }); + + it('does not use intersection if w/h are relevant', () => { + bbox.getBoundingClientRect.returns({ + width: 0, + height: 0, + left: -50, + top: -100, + }); + intersection = { + boundingClientRect: { + width: 0, + height: 0, + }, + isIntersecting: true, + intersectionRatio: 1 + }; + expect(percentInView({}, { w: 100, h: 200 })).to.not.eql(100); + }); + }); }); diff --git a/test/spec/modules/intersectionRtdProvider_spec.js b/test/spec/modules/intersectionRtdProvider_spec.js deleted file mode 100644 index 9fa934fd4f3..00000000000 --- a/test/spec/modules/intersectionRtdProvider_spec.js +++ /dev/null @@ -1,164 +0,0 @@ -import { config as _config, config } from 'src/config.js'; -import { expect } from 'chai'; -import * as events from 'src/events.js'; -import * as prebidGlobal from 'src/prebidGlobal.js'; -import { intersectionSubmodule } from 'modules/intersectionRtdProvider.js'; -import * as utils from 'src/utils.js'; -import { getGlobal } from 'src/prebidGlobal.js'; -import 'src/prebid.js'; - -describe('Intersection RTD Provider', function () { - let sandbox; - let placeholder; - const pbjs = getGlobal(); - const adUnit = { - code: 'ad-slot-1', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - }, - bids: [ - { - bidder: 'fake' - } - ] - }; - const providerConfig = { name: 'intersection', waitForIt: true }; - const rtdConfig = { realTimeData: { auctionDelay: 200, dataProviders: [providerConfig] } } - describe('IntersectionObserver not supported', function() { - beforeEach(function() { - sandbox = sinon.createSandbox(); - }); - afterEach(function() { - sandbox.restore(); - sandbox = undefined; - }); - it('init should return false', function () { - sandbox.stub(window, 'IntersectionObserver').value(undefined); - expect(intersectionSubmodule.init({})).is.false; - }); - }); - describe('IntersectionObserver supported', function() { - beforeEach(function() { - sandbox = sinon.createSandbox(); - placeholder = createDiv(); - append(); - const __config = {}; - sandbox.stub(_config, 'getConfig').callsFake(function (path) { - return utils.deepAccess(__config, path); - }); - sandbox.stub(_config, 'setConfig').callsFake(function (obj) { - utils.mergeDeep(__config, obj); - }); - sandbox.stub(window, 'IntersectionObserver').callsFake(function (cb) { - return { - observe(el) { - cb([ - { - target: el, - intersectionRatio: 1, - isIntersecting: true, - time: Date.now(), - boundingClientRect: { left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0, x: 0, y: 0 }, - intersectionRect: { left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0, x: 0, y: 0 }, - rootRect: { left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0, x: 0, y: 0 } - } - ]); - }, - unobserve() {}, - disconnect() {} - }; - }); - }); - afterEach(function() { - sandbox.restore(); - remove(); - sandbox = undefined; - placeholder = undefined; - pbjs.removeAdUnit(); - }); - it('init should return true', function () { - expect(intersectionSubmodule.init({})).is.true; - }); - it('should set intersection. (request with "adUnitCodes")', function(done) { - pbjs.addAdUnits([utils.deepClone(adUnit)]); - config.setConfig(rtdConfig); - const onDone = sandbox.stub(); - const requestBidObject = { adUnitCodes: [adUnit.code] }; - intersectionSubmodule.init({}); - intersectionSubmodule.getBidRequestData( - requestBidObject, - onDone, - providerConfig - ); - setTimeout(function() { - expect(pbjs.adUnits[0].bids[0]).to.have.property('intersection'); - done(); - }, 200); - }); - it('should set intersection. (request with "adUnits")', function(done) { - config.setConfig(rtdConfig); - const onDone = sandbox.stub(); - const requestBidObject = { adUnits: [utils.deepClone(adUnit)] }; - intersectionSubmodule.init(); - intersectionSubmodule.getBidRequestData( - requestBidObject, - onDone, - providerConfig - ); - setTimeout(function() { - expect(requestBidObject.adUnits[0].bids[0]).to.have.property('intersection'); - done(); - }, 200); - }); - it('should set intersection. (request all)', function(done) { - pbjs.addAdUnits([utils.deepClone(adUnit)]); - config.setConfig(rtdConfig); - const onDone = sandbox.stub(); - const requestBidObject = {}; - intersectionSubmodule.init({}); - intersectionSubmodule.getBidRequestData( - requestBidObject, - onDone, - providerConfig - ); - setTimeout(function() { - expect(pbjs.adUnits[0].bids[0]).to.have.property('intersection'); - done(); - }, 200); - }); - it('should call done due timeout', function(done) { - config.setConfig(rtdConfig); - remove(); - const onDone = sandbox.stub(); - const requestBidObject = { adUnits: [utils.deepClone(adUnit)] }; - intersectionSubmodule.init({}); - intersectionSubmodule.getBidRequestData( - requestBidObject, - onDone, - { ...providerConfig, test: 1 } - ); - setTimeout(function() { - sinon.assert.calledOnce(onDone); - expect(requestBidObject.adUnits[0].bids[0]).to.not.have.property('intersection'); - done(); - }, 300); - }); - }); - function createDiv() { - const div = document.createElement('div'); - div.id = adUnit.code; - return div; - } - function append() { - if (placeholder) { - document.body.appendChild(placeholder); - } - } - function remove() { - if (placeholder && placeholder.parentElement) { - placeholder.parentElement.removeChild(placeholder); - } - } -}); From dfb3bc14a69e1f99a4d85f8e952151f4357932db Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 11 Mar 2026 10:38:32 -0400 Subject: [PATCH 34/48] Prebid 11: toss mediatype mismatch bids; avoid mediaType mismatch rejects when adapter omits mediaType (#14496) * Core: preserve omitted mediaType behavior in bid validation * Update bidderFactory to retain mediaType Retain mediaType information from adapter response. * tests fixing * lint * Core: split unknown vs invalid mediaType rejection flags (#14569) --------- Co-authored-by: mkomorski --- src/adapters/bidderFactory.ts | 26 +++++- src/auction.ts | 12 +++ src/config.ts | 2 +- test/spec/auctionmanager_spec.js | 6 +- test/spec/unit/core/bidderFactory_spec.js | 108 ++++++++++++++++++++++ 5 files changed, 148 insertions(+), 6 deletions(-) diff --git a/src/adapters/bidderFactory.ts b/src/adapters/bidderFactory.ts index bacd954f641..737c26117e1 100644 --- a/src/adapters/bidderFactory.ts +++ b/src/adapters/bidderFactory.ts @@ -279,11 +279,11 @@ export function newBidder(spec: BidderSpec) { const tidGuard = guardTids(bidderRequest); const adUnitCodesHandled = {}; - function addBidWithCode(adUnitCode: string, bid: Bid) { + function addBidWithCode(adUnitCode: string, bid: Bid, responseMediaType = null) { const metrics = useMetrics(bid.metrics); metrics.checkpoint('addBidResponse'); adUnitCodesHandled[adUnitCode] = true; - if (metrics.measureTime('addBidResponse.validate', () => isValid(adUnitCode, bid))) { + if (metrics.measureTime('addBidResponse.validate', () => isValid(adUnitCode, bid, { responseMediaType }))) { addBidResponse(adUnitCode, bid); } else { addBidResponse.reject(adUnitCode, bid, REJECTION_REASON.INVALID) @@ -345,7 +345,10 @@ export function newBidder(spec: BidderSpec) { bid.deferBilling = bidRequest.deferBilling; bid.deferRendering = bid.deferBilling && (bidResponse.deferRendering ?? typeof spec.onBidBillable !== 'function'); const prebidBid: Bid = Object.assign(createBid(bidRequest), bid, pick(bidRequest, Object.keys(TIDS))); - addBidWithCode(bidRequest.adUnitCode, prebidBid); + const responseMediaType = Object.prototype.hasOwnProperty.call(bidResponse, 'mediaType') + ? bidResponse.mediaType + : null; + addBidWithCode(bidRequest.adUnitCode, prebidBid, responseMediaType); } else { logWarn(`Bidder ${spec.code} made bid for unknown request ID: ${bidResponse.requestId}. Ignoring.`); addBidResponse.reject(null, bidResponse, REJECTION_REASON.INVALID_REQUEST_ID); @@ -647,7 +650,7 @@ function validBidSize(adUnitCode, bid: BannerBid, { index = auctionManager.index } // Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored. -export function isValid(adUnitCode: string, bid: Bid, { index = auctionManager.index } = {}) { +export function isValid(adUnitCode: string, bid: Bid, { index = auctionManager.index, responseMediaType = bid.mediaType } = {}) { function hasValidKeys() { const bidKeys = Object.keys(bid); return COMMON_BID_RESPONSE_KEYS.every(key => bidKeys.includes(key) && ![undefined, null].includes(bid[key])); @@ -672,6 +675,21 @@ export function isValid(adUnitCode: string, bid: Bid, { index = auctionManager.i return false; } + const auctionOptions = config.getConfig('auctionOptions') || {}; + const rejectUnknownMediaTypes = auctionOptions.rejectUnknownMediaTypes === true; + const rejectInvalidMediaTypes = auctionOptions.rejectInvalidMediaTypes !== false; + const mediaTypes = index.getMediaTypes(bid); + if (mediaTypes && Object.keys(mediaTypes).length > 0) { + if (responseMediaType == null && rejectUnknownMediaTypes) { + logError(errorMessage(`Bid mediaType is required. Allowed: ${Object.keys(mediaTypes).join(', ')}`)); + return false; + } + if (responseMediaType != null && rejectInvalidMediaTypes && !mediaTypes.hasOwnProperty(responseMediaType)) { + logError(errorMessage(`Bid mediaType '${responseMediaType}' is not supported by the ad unit. Allowed: ${Object.keys(mediaTypes).join(', ')}`)); + return false; + } + } + if (FEATURES.NATIVE && bid.mediaType === 'native' && !nativeBidIsValid(bid, { index })) { logError(errorMessage('Native bid missing some required properties.')); return false; diff --git a/src/auction.ts b/src/auction.ts index 4f805603c55..6a7a9643938 100644 --- a/src/auction.ts +++ b/src/auction.ts @@ -143,6 +143,18 @@ export interface AuctionOptionsConfig { * to pre-10.12 rendering logic. */ legacyRender?: boolean; + + /** + * When true, reject bids without a response `mediaType` when the ad unit has an explicit mediaTypes list. + * Default is false to preserve legacy behavior for responses that omit mediaType. + */ + rejectUnknownMediaTypes?: boolean; + + /** + * When true, reject bids with a response `mediaType` that does not match the ad unit's explicit mediaTypes list. + * Default is true; set to false to keep mismatched mediaType responses. + */ + rejectInvalidMediaTypes?: boolean; } export interface PriceBucketConfig { diff --git a/src/config.ts b/src/config.ts index 827856df0f0..665ce89778d 100644 --- a/src/config.ts +++ b/src/config.ts @@ -63,7 +63,7 @@ function attachProperties(config, useDefaultValues = true) { } : {} const validateauctionOptions = (() => { - const boolKeys = ['secondaryBidders', 'suppressStaleRender', 'suppressExpiredRender', 'legacyRender']; + const boolKeys = ['suppressStaleRender', 'suppressExpiredRender', 'legacyRender', 'rejectUnknownMediaTypes', 'rejectInvalidMediaTypes']; const arrKeys = ['secondaryBidders'] const allKeys = [].concat(boolKeys).concat(arrKeys); diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js index 90bdc857e98..58151526325 100644 --- a/test/spec/auctionmanager_spec.js +++ b/test/spec/auctionmanager_spec.js @@ -105,6 +105,10 @@ function mockBidRequest(bid, opts) { const defaultMediaType = { banner: { sizes: [[300, 250], [300, 600]] + }, + video: { + context: 'outstream', + renderer: {} } } const mediaType = (opts && opts.mediaType) ? opts.mediaType : defaultMediaType; @@ -1159,7 +1163,7 @@ describe('auctionmanager.js', function () { bids[0], { bidderCode: BIDDER_CODE, - mediaType: 'video-outstream', + mediaType: 'video', } ); spec.interpretResponse.returns(bids1); diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 153bccab5ca..383d7441a62 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -1691,6 +1691,114 @@ describe('bidderFactory', () => { }); }); }) + + describe('media type validation', () => { + let req; + + function mkResponse(props) { + return Object.assign({ + requestId: req.bidId, + cpm: 1, + ttl: 60, + creativeId: '123', + netRevenue: true, + currency: 'USD', + width: 1, + height: 2, + mediaType: 'banner', + }, props); + } + + function checkValid(bid, opts = {}) { + return isValid('au', bid, { + index: stubAuctionIndex({ bidRequests: [req] }), + ...opts, + }); + } + + beforeEach(() => { + req = { + ...MOCK_BIDS_REQUEST.bids[0], + mediaTypes: { + banner: { + sizes: [[1, 2]] + } + } + }; + }); + + it('should reject video bid when ad unit only has banner', () => { + expect(checkValid(mkResponse({ mediaType: 'video' }))).to.be.false; + }); + + it('should accept video bid when ad unit has both banner and video', () => { + req.mediaTypes = { + banner: { sizes: [[1, 2]] }, + video: { context: 'instream' } + }; + expect(checkValid(mkResponse({ mediaType: 'video', vastUrl: 'http://vast.xml' }))).to.be.true; + }); + + it('should skip media type check when adapter omits mediaType', () => { + req.mediaTypes = { + video: { context: 'instream' } + }; + + expect(checkValid(mkResponse({ mediaType: 'banner' }), { responseMediaType: null })).to.be.true; + }); + + it('should reject unknown media type when configured and adapter omits mediaType', () => { + req.mediaTypes = { + video: { context: 'instream' } + }; + config.setConfig({ + auctionOptions: { + rejectUnknownMediaTypes: true + } + }); + + expect(checkValid(mkResponse({ mediaType: 'banner' }), { responseMediaType: null })).to.be.false; + }); + + it('should keep legacy behavior when rejectUnknownMediaTypes is disabled', () => { + req.mediaTypes = { + video: { context: 'instream' } + }; + config.setConfig({ + auctionOptions: { + rejectUnknownMediaTypes: false + } + }); + + expect(checkValid(mkResponse({ mediaType: 'banner' }), { responseMediaType: null })).to.be.true; + }); + + it('should allow mismatched media type when rejectInvalidMediaTypes is disabled', () => { + req.mediaTypes = { + banner: { sizes: [[1, 2]] } + }; + config.setConfig({ + auctionOptions: { + rejectInvalidMediaTypes: false + } + }); + + expect(checkValid(mkResponse({ mediaType: 'video' }))).to.be.true; + }); + + it('should reject mismatched media type when rejectInvalidMediaTypes is enabled', () => { + req.mediaTypes = { + banner: { sizes: [[1, 2]] } + }; + config.setConfig({ + auctionOptions: { + rejectInvalidMediaTypes: true + } + }); + + expect(checkValid(mkResponse({ mediaType: 'video' }))).to.be.false; + }); + }); }); describe('gzip compression', () => { From a669a8afdc66b0a46adf3d9553bfdd3922369a17 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 11 Mar 2026 09:40:46 -0700 Subject: [PATCH 35/48] adloox analytics: do not disable if not enabled --- modules/adlooxAnalyticsAdapter.js | 5 +++-- test/spec/modules/adlooxAnalyticsAdapter_spec.js | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/adlooxAnalyticsAdapter.js b/modules/adlooxAnalyticsAdapter.js index 444e9ecf3c4..4b1461c79a5 100644 --- a/modules/adlooxAnalyticsAdapter.js +++ b/modules/adlooxAnalyticsAdapter.js @@ -172,8 +172,9 @@ analyticsAdapter.enableAnalytics = function(config) { analyticsAdapter.originDisableAnalytics = analyticsAdapter.disableAnalytics; analyticsAdapter.disableAnalytics = function() { analyticsAdapter.context = null; - - analyticsAdapter.originDisableAnalytics(); + if (this.enabled) { + analyticsAdapter.originDisableAnalytics(); + } } analyticsAdapter.url = function(url, args, bid) { diff --git a/test/spec/modules/adlooxAnalyticsAdapter_spec.js b/test/spec/modules/adlooxAnalyticsAdapter_spec.js index 30404fc9dc6..692349a31d6 100644 --- a/test/spec/modules/adlooxAnalyticsAdapter_spec.js +++ b/test/spec/modules/adlooxAnalyticsAdapter_spec.js @@ -40,10 +40,6 @@ describe('Adloox Analytics Adapter', function () { } }; - adapterManager.registerAnalyticsAdapter({ - code: analyticsAdapterName, - adapter: analyticsAdapter - }); describe('enableAnalytics', function () { afterEach(function () { analyticsAdapter.disableAnalytics(); From 24521a2349258ac2db823f590c8fe766841f93a5 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 11 Mar 2026 11:24:21 -0700 Subject: [PATCH 36/48] connatixBidAdapter: fix tests --- test/spec/modules/connatixBidAdapter_spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js index ba732913815..1c94e76a8d8 100644 --- a/test/spec/modules/connatixBidAdapter_spec.js +++ b/test/spec/modules/connatixBidAdapter_spec.js @@ -172,6 +172,7 @@ describe('connatixBidAdapter', function () { height: 250 }); + const getElementByIdStub = sinon.stub(document, 'getElementById'); getElementByIdStub.withArgs('validElement').returns(element); const result = connatixDetectViewability(bid); From 5bb2075a21860ac433faa2948b27393200a52462 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 11 Mar 2026 11:36:45 -0700 Subject: [PATCH 37/48] connatixBidAdapter: fix the fix to the test --- test/spec/modules/connatixBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js index 1c94e76a8d8..82479617769 100644 --- a/test/spec/modules/connatixBidAdapter_spec.js +++ b/test/spec/modules/connatixBidAdapter_spec.js @@ -172,7 +172,7 @@ describe('connatixBidAdapter', function () { height: 250 }); - const getElementByIdStub = sinon.stub(document, 'getElementById'); + const getElementByIdStub = sandbox.stub(document, 'getElementById'); getElementByIdStub.withArgs('validElement').returns(element); const result = connatixDetectViewability(bid); From 7216f22761df7634654ee7f5f4c850f01fe1e8fc Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 11 Mar 2026 11:52:44 -0700 Subject: [PATCH 38/48] percentInView: add timeout, adjust intersection thresholds (#14579) --- libraries/percentInView/percentInView.js | 20 +++++++++++++++----- test/spec/libraries/percentInView_spec.js | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/libraries/percentInView/percentInView.js b/libraries/percentInView/percentInView.js index 53028d51cc8..21605c194a2 100644 --- a/libraries/percentInView/percentInView.js +++ b/libraries/percentInView/percentInView.js @@ -1,6 +1,6 @@ import { getWinDimensions, inIframe } from '../../src/utils.js'; import { getBoundingClientRect } from '../boundingClientRect/boundingClientRect.js'; -import { defer, PbPromise } from '../../src/utils/promise.js'; +import { defer, PbPromise, delay } from '../../src/utils/promise.js'; import { startAuction } from '../../src/prebid.js'; import { getAdUnitElement } from '../../src/utils/adUnits.js'; @@ -169,13 +169,23 @@ export function intersections(mkObserver) { } } -export const viewportIntersections = intersections((callback) => new IntersectionObserver(callback)); +export const viewportIntersections = intersections((callback) => new IntersectionObserver(callback, { + // update percentInView when visibility varies by 1% + threshold: Array.from({ length: 101 }, (e, i) => i / 100) +})); export function mkIntersectionHook(intersections = viewportIntersections) { return function (next, request) { - PbPromise.allSettled((request.adUnits ?? []).map(adUnit => - intersections.observe(getAdUnitElement(adUnit)) - )).then(() => next.call(this, request)); + PbPromise.race([ + PbPromise.allSettled((request.adUnits ?? []).map(adUnit => + intersections.observe(getAdUnitElement(adUnit)) + )), + // according to MDN, with threshold 0 "the callback will be run as soon as the target element intersects or touches the boundary of the root, even if no pixels are yet visible" + // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API + // However, browsers appear to run it even when the element is outside the DOM + // just to be sure, cap the amount of time we wait for intersections + delay(20) + ]).then(() => next.call(this, request)); } } diff --git a/test/spec/libraries/percentInView_spec.js b/test/spec/libraries/percentInView_spec.js index 4dd54ff99d0..fd3f9b5ea20 100644 --- a/test/spec/libraries/percentInView_spec.js +++ b/test/spec/libraries/percentInView_spec.js @@ -56,8 +56,8 @@ describe('percentInView', () => { }); }); - async function delay() { - await new Promise(resolve => setTimeout(resolve, 10)); + async function delay(ms = 10) { + await new Promise(resolve => setTimeout(resolve, ms)); } describe('intersections', () => { @@ -227,6 +227,19 @@ describe('percentInView', () => { await delay(); sinon.assert.calledWith(next, request); }); + + it('should continue if promises never resolve', async () => { + hook(next, request); + await delay(100); + sinon.assert.called(next); + }); + + it('should not delay if there are no elements to observe', async () => { + request.adUnits = []; + hook(next, request); + await delay(); + sinon.assert.called(next); + }) }); }); From 2fa14f2a2596763bc60c19b1407fdc2e92e45232 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 11 Mar 2026 17:02:34 -0700 Subject: [PATCH 39/48] remove debugger statement --- test/spec/modules/msftBidAdapter_spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/spec/modules/msftBidAdapter_spec.js b/test/spec/modules/msftBidAdapter_spec.js index 9f7d757d897..2f5f1014594 100644 --- a/test/spec/modules/msftBidAdapter_spec.js +++ b/test/spec/modules/msftBidAdapter_spec.js @@ -210,7 +210,6 @@ describe('msftBidAdapter', function () { const bidderRequest = Object.assign({}, testBidderRequest, { bids: bidRequests }); - debugger;// eslint-disable-line no-debugger const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.method).to.equal('POST'); const data = request.data; From 85860a8278f8cf1cea5c4809c5e36eadff3f0d0e Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 11 Mar 2026 17:27:51 -0700 Subject: [PATCH 40/48] mediaFuse: fix test failing on safari (regex lookbehind not supported) --- test/spec/modules/mediafuseBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/mediafuseBidAdapter_spec.js b/test/spec/modules/mediafuseBidAdapter_spec.js index b6cd8e7d810..70a2dc43886 100644 --- a/test/spec/modules/mediafuseBidAdapter_spec.js +++ b/test/spec/modules/mediafuseBidAdapter_spec.js @@ -614,7 +614,7 @@ describe('mediafuseBidAdapter', function () { const trkTracker = trackers.find(t => t.includes('trk.js')); expect(trkTracker).to.include('data-src='); // Verify the original 'src=1' param is now 'data-src=1' (not a bare 'src=') - expect(trkTracker).to.not.match(/(? Date: Wed, 11 Mar 2026 17:46:52 -0700 Subject: [PATCH 41/48] Revert "mediaFuse: fix test failing on safari (regex lookbehind not supported)" This reverts commit 85860a8278f8cf1cea5c4809c5e36eadff3f0d0e. --- test/spec/modules/mediafuseBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/mediafuseBidAdapter_spec.js b/test/spec/modules/mediafuseBidAdapter_spec.js index 70a2dc43886..b6cd8e7d810 100644 --- a/test/spec/modules/mediafuseBidAdapter_spec.js +++ b/test/spec/modules/mediafuseBidAdapter_spec.js @@ -614,7 +614,7 @@ describe('mediafuseBidAdapter', function () { const trkTracker = trackers.find(t => t.includes('trk.js')); expect(trkTracker).to.include('data-src='); // Verify the original 'src=1' param is now 'data-src=1' (not a bare 'src=') - expect(trkTracker).to.not.match(/[^-]src=1/); + expect(trkTracker).to.not.match(/(? Date: Wed, 11 Mar 2026 17:59:47 -0700 Subject: [PATCH 42/48] mediafuse: reapply adpod changes --- modules/mediafuseBidAdapter.js | 92 +----- test/spec/modules/mediafuseBidAdapter_spec.js | 261 ------------------ 2 files changed, 3 insertions(+), 350 deletions(-) diff --git a/modules/mediafuseBidAdapter.js b/modules/mediafuseBidAdapter.js index da98d88fa81..b308a713d6e 100644 --- a/modules/mediafuseBidAdapter.js +++ b/modules/mediafuseBidAdapter.js @@ -19,13 +19,12 @@ import { import { Renderer } from '../src/Renderer.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { ADPOD, BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { INSTREAM, OUTSTREAM } from '../src/video.js'; import { getStorageManager } from '../src/storageManager.js'; import { bidderSettings } from '../src/bidderSettings.js'; import { hasPurpose1Consent } from '../src/utils/gdpr.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; -import { APPNEXUS_CATEGORY_MAPPING } from '../libraries/categoryTranslationMapping/index.js'; import { getANKewyordParamFromMaps, getANKeywordParam @@ -222,10 +221,6 @@ export const spec = { const mfKeywords = config.getConfig('mediafuseAuctionKeywords'); payload.keywords = getANKeywordParam(bidderRequest?.ortb2, mfKeywords); - if (config.getConfig('adpod.brandCategoryExclusion')) { - payload.brand_category_uniqueness = true; - } - if (debugObjParams.enabled) { payload.debug = debugObjParams; logInfo('MediaFuse Debug Auction Settings:\n\n' + JSON.stringify(debugObjParams, null, 4)); @@ -261,16 +256,6 @@ export const spec = { payload.referrer_detection = refererinfo; } - const hasAdPodBid = ((bidRequests) || []).find(hasAdPod); - if (hasAdPodBid) { - bidRequests.filter(hasAdPod).forEach(adPodBid => { - const adPodTags = createAdPodRequest(tags, adPodBid); - // don't need the original adpod placement because it's in adPodTags - const nonPodTags = payload.tags.filter(tag => tag.uuid !== adPodBid.bidId); - payload.tags = [...nonPodTags, ...adPodTags]; - }); - } - if (bidRequests[0].userIdAsEids?.length > 0) { const eids = []; bidRequests[0].userIdAsEids.forEach(eid => { @@ -579,7 +564,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { } if (rtbBid.rtb.video) { - // shared video properties used for all 3 contexts + // shared video properties used for both stream contexts Object.assign(bid, { width: rtbBid.rtb.video.player_width, height: rtbBid.rtb.video.player_height, @@ -589,17 +574,6 @@ function newBid(serverBid, rtbBid, bidderRequest) { const videoContext = deepAccess(bidRequest, 'mediaTypes.video.context'); switch (videoContext) { - case ADPOD: - const primaryCatId = (APPNEXUS_CATEGORY_MAPPING[rtbBid.brand_category_id]) ? APPNEXUS_CATEGORY_MAPPING[rtbBid.brand_category_id] : null; - bid.meta = Object.assign({}, bid.meta, { primaryCatId }); - const dealTier = rtbBid.deal_priority; - bid.video = { - context: ADPOD, - durationSeconds: Math.floor(rtbBid.rtb.video.duration_ms / 1000), - dealTier - }; - bid.vastUrl = rtbBid.rtb.video.asset_url; - break; case OUTSTREAM: bid.adResponse = serverBid; bid.adResponse.ad = bid.adResponse.ads[0]; @@ -756,11 +730,7 @@ function bidToTag(bid) { const videoMediaType = deepAccess(bid, `mediaTypes.${VIDEO}`); const context = deepAccess(bid, 'mediaTypes.video.context'); - if (videoMediaType && context === 'adpod') { - tag.hb_source = 7; - } else { - tag.hb_source = 1; - } + tag.hb_source = 1; if (bid.mediaType === VIDEO || videoMediaType) { tag.ad_types.push(VIDEO); } @@ -909,14 +879,6 @@ function hasDebug(bid) { return !!bid.debug } -function hasAdPod(bid) { - return ( - bid.mediaTypes && - bid.mediaTypes.video && - bid.mediaTypes.video.context === ADPOD - ); -} - function hasOmidSupport(bid) { let hasOmid = false; const bidderParams = bid.params; @@ -930,54 +892,6 @@ function hasOmidSupport(bid) { return hasOmid; } -/** - * Expand an adpod placement into a set of request objects according to the - * total adpod duration and the range of duration seconds. Sets minduration/ - * maxduration video property according to requireExactDuration configuration - */ -function createAdPodRequest(tags, adPodBid) { - const { durationRangeSec, requireExactDuration } = adPodBid.mediaTypes.video; - - const numberOfPlacements = getAdPodPlacementNumber(adPodBid.mediaTypes.video); - const maxDuration = Math.max(...durationRangeSec); - - const tagToDuplicate = tags.filter(tag => tag.uuid === adPodBid.bidId); - const request = fill(...tagToDuplicate, numberOfPlacements); - - if (requireExactDuration) { - const divider = Math.ceil(numberOfPlacements / durationRangeSec.length); - const chunked = chunk(request, divider); - - // each configured duration is set as min/maxduration for a subset of requests - durationRangeSec.forEach((duration, index) => { - chunked[index].forEach(tag => { - setVideoProperty(tag, 'minduration', duration); - setVideoProperty(tag, 'maxduration', duration); - }); - }); - } else { - // all maxdurations should be the same - request.forEach(tag => setVideoProperty(tag, 'maxduration', maxDuration)); - } - - return request; -} - -function getAdPodPlacementNumber(videoParams) { - const { adPodDurationSec, durationRangeSec, requireExactDuration } = videoParams; - const minAllowedDuration = Math.min(...durationRangeSec); - const numberOfPlacements = Math.floor(adPodDurationSec / minAllowedDuration); - - return requireExactDuration - ? Math.max(numberOfPlacements, durationRangeSec.length) - : numberOfPlacements; -} - -function setVideoProperty(tag, key, value) { - if (isEmpty(tag.video)) { tag.video = {}; } - tag.video[key] = value; -} - function getRtbBid(tag) { return tag && tag.ads && tag.ads.length && ((tag.ads) || []).find(ad => ad.rtb); } diff --git a/test/spec/modules/mediafuseBidAdapter_spec.js b/test/spec/modules/mediafuseBidAdapter_spec.js index e446a1c1138..c1ca2e918f7 100644 --- a/test/spec/modules/mediafuseBidAdapter_spec.js +++ b/test/spec/modules/mediafuseBidAdapter_spec.js @@ -347,185 +347,6 @@ describe('MediaFuseAdapter', function () { expect(payload.tags[0].reserve).to.exist.and.to.equal(3); }); - it('should duplicate adpod placements into batches and set correct maxduration', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - - // 300 / 15 = 20 total - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(5); - - expect(payload1.tags[0]).to.deep.equal(payload1.tags[1]); - expect(payload1.tags[0].video.maxduration).to.equal(30); - - expect(payload2.tags[0]).to.deep.equal(payload1.tags[1]); - expect(payload2.tags[0].video.maxduration).to.equal(30); - }); - - it('should round down adpod placements when numbers are uneven', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 123, - durationRangeSec: [45], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags.length).to.equal(2); - }); - - it('should duplicate adpod placements when requireExactDuration is set', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - requireExactDuration: true, - } - } - } - ); - - // 20 total placements with 15 max impressions = 2 requests - const request = spec.buildRequests([bidRequest]); - expect(request.length).to.equal(2); - - // 20 spread over 2 requests = 15 in first request, 5 in second - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(5); - - // 10 placements should have max/min at 15 - // 10 placemenst should have max/min at 30 - const payload1tagsWith15 = payload1.tags.filter(tag => tag.video.maxduration === 15); - const payload1tagsWith30 = payload1.tags.filter(tag => tag.video.maxduration === 30); - expect(payload1tagsWith15.length).to.equal(10); - expect(payload1tagsWith30.length).to.equal(5); - - // 5 placemenst with min/max at 30 were in the first request - // so 5 remaining should be in the second - const payload2tagsWith30 = payload2.tags.filter(tag => tag.video.maxduration === 30); - expect(payload2tagsWith30.length).to.equal(5); - }); - - it('should set durations for placements when requireExactDuration is set and numbers are uneven', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 105, - durationRangeSec: [15, 30, 60], - requireExactDuration: true, - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags.length).to.equal(7); - - const tagsWith15 = payload.tags.filter(tag => tag.video.maxduration === 15); - const tagsWith30 = payload.tags.filter(tag => tag.video.maxduration === 30); - const tagsWith60 = payload.tags.filter(tag => tag.video.maxduration === 60); - expect(tagsWith15.length).to.equal(3); - expect(tagsWith30.length).to.equal(3); - expect(tagsWith60.length).to.equal(1); - }); - - it('should break adpod request into batches', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 225, - durationRangeSec: [5], - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload1 = JSON.parse(request[0].data); - const payload2 = JSON.parse(request[1].data); - const payload3 = JSON.parse(request[2].data); - - expect(payload1.tags.length).to.equal(15); - expect(payload2.tags.length).to.equal(15); - expect(payload3.tags.length).to.equal(15); - }); - - it('should contain hb_source value for adpod', function() { - const bidRequest = Object.assign({}, - bidRequests[0], - { - params: { placementId: '14542875' } - }, - { - mediaTypes: { - video: { - context: 'adpod', - playerSize: [640, 480], - adPodDurationSec: 300, - durationRangeSec: [15, 30], - } - } - } - ); - const request = spec.buildRequests([bidRequest])[0]; - const payload = JSON.parse(request.data); - expect(payload.tags[0].hb_source).to.deep.equal(7); - }); - it('should contain hb_source value for other media', function() { const bidRequest = Object.assign({}, bidRequests[0], @@ -542,21 +363,6 @@ describe('MediaFuseAdapter', function () { expect(payload.tags[0].hb_source).to.deep.equal(1); }); - it('adds brand_category_exclusion to request when set', function() { - const bidRequest = Object.assign({}, bidRequests[0]); - sinon - .stub(config, 'getConfig') - .withArgs('adpod.brandCategoryExclusion') - .returns(true); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.brand_category_uniqueness).to.equal(true); - - config.getConfig.restore(); - }); - it('adds auction level keywords to request when set', function() { const bidRequest = Object.assign({}, bidRequests[0]); sinon @@ -1261,46 +1067,6 @@ describe('MediaFuseAdapter', function () { expect(result[0]).to.have.property('mediaType', 'video'); }); - it('handles adpod responses', function () { - const response = { - 'tags': [{ - 'uuid': '84ab500420319d', - 'ads': [{ - 'ad_type': 'video', - 'brand_category_id': 10, - 'cpm': 0.500000, - 'notify_url': 'imptracker.com', - 'rtb': { - 'video': { - 'asset_url': 'https://sample.vastURL.com/here/adpod', - 'duration_ms': 30000, - } - }, - 'viewability': { - 'config': '' - } - }] - }] - }; - - const bidderRequest = { - bids: [{ - bidId: '84ab500420319d', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'adpod' - } - } - }] - }; - - const result = spec.interpretResponse({ body: response }, { bidderRequest }); - expect(result[0]).to.have.property('vastUrl'); - expect(result[0].video.context).to.equal('adpod'); - expect(result[0].video.durationSeconds).to.equal(30); - }); - it('handles native responses', function () { const response1 = deepClone(response); response1.tags[0].ads[0].ad_type = 'native'; @@ -1378,33 +1144,6 @@ describe('MediaFuseAdapter', function () { ); }); - it('should add deal_priority and deal_code', function() { - const responseWithDeal = deepClone(response); - responseWithDeal.tags[0].ads[0].ad_type = 'video'; - responseWithDeal.tags[0].ads[0].deal_priority = 5; - responseWithDeal.tags[0].ads[0].deal_code = '123'; - responseWithDeal.tags[0].ads[0].rtb.video = { - duration_ms: 1500, - player_width: 640, - player_height: 340, - }; - - const bidderRequest = { - bids: [{ - bidId: '3db3773286ee59', - adUnitCode: 'code', - mediaTypes: { - video: { - context: 'adpod' - } - } - }] - } - const result = spec.interpretResponse({ body: responseWithDeal }, { bidderRequest }); - expect(Object.keys(result[0].mediafuse)).to.include.members(['buyerMemberId', 'dealPriority', 'dealCode']); - expect(result[0].video.dealTier).to.equal(5); - }); - it('should add advertiser id', function() { const responseAdvertiserId = deepClone(response); responseAdvertiserId.tags[0].ads[0].advertiser_id = '123'; From 21978c60ba6c077dba453f3c0977e5ea27fb4a5f Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Wed, 11 Mar 2026 18:08:06 -0700 Subject: [PATCH 43/48] mediafuse: fix lint --- modules/mediafuseBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/mediafuseBidAdapter.js b/modules/mediafuseBidAdapter.js index b308a713d6e..5b4b5159dbc 100644 --- a/modules/mediafuseBidAdapter.js +++ b/modules/mediafuseBidAdapter.js @@ -29,7 +29,7 @@ import { getANKewyordParamFromMaps, getANKeywordParam } from '../libraries/appnexusUtils/anKeywords.js'; -import { convertCamelToUnderscore, fill } from '../libraries/appnexusUtils/anUtils.js'; +import { convertCamelToUnderscore } from '../libraries/appnexusUtils/anUtils.js'; import { chunk } from '../libraries/chunk/chunk.js'; /** From 01b51eb7f55c0125d817d92c55296e2c01fbbe20 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Thu, 12 Mar 2026 07:25:04 -0700 Subject: [PATCH 44/48] mediafuse: use getAdUnitElement --- modules/mediafuseBidAdapter.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/modules/mediafuseBidAdapter.js b/modules/mediafuseBidAdapter.js index 5845acb72da..7fe6538c7ad 100644 --- a/modules/mediafuseBidAdapter.js +++ b/modules/mediafuseBidAdapter.js @@ -28,6 +28,7 @@ import { } from '../libraries/appnexusUtils/anKeywords.js'; import { convertCamelToUnderscore } from '../libraries/appnexusUtils/anUtils.js'; import { chunk } from '../libraries/chunk/chunk.js'; +import { getAdUnitElement } from '../src/utils/adUnits.js'; const BIDDER_CODE = 'mediafuse'; const GVLID = 32; @@ -492,7 +493,7 @@ const converter = ortbConverter({ tag_id: extANData.tag_id, uuid: bidResponse.requestId }; - bidResponse.renderer = newRenderer(bidRequest.adUnitCode, { + bidResponse.renderer = newRenderer(bidRequest, { renderer_url: extANData.renderer_url, renderer_id: extANData.renderer_id, }, rendererOptions); @@ -677,13 +678,13 @@ function getBidFloor(bid) { return null; } -function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { +function newRenderer(bidRequest, rtbBid, rendererOptions = {}) { const renderer = Renderer.install({ id: rtbBid.renderer_id, url: rtbBid.renderer_url, config: rendererOptions, loaded: false, - adUnitCode, + adUnitCode: bidRequest.adUnitCode, }); try { @@ -697,7 +698,7 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { loaded: () => logMessage('Mediafuse outstream video loaded event'), ended: () => { logMessage('Mediafuse outstream renderer video event'); - const el = document.getElementById(adUnitCode); + const el = getAdUnitElement(bidRequest); if (el) { el.style.display = 'none'; } @@ -706,9 +707,9 @@ function newRenderer(adUnitCode, rtbBid, rendererOptions = {}) { return renderer; } -function hidedfpContainer(elementId) { +function hidedfpContainer(container) { try { - const el = document.getElementById(elementId).querySelectorAll("div[id^='google_ads']"); + const el = container.querySelectorAll("div[id^='google_ads']"); if (el[0]) { el[0].style.setProperty('display', 'none'); } @@ -717,9 +718,9 @@ function hidedfpContainer(elementId) { } } -function hideSASIframe(elementId) { +function hideSASIframe(container) { try { - const el = document.getElementById(elementId).querySelectorAll("script[id^='sas_script']"); + const el = container.querySelectorAll("script[id^='sas_script']"); if (el[0]?.nextSibling?.localName === 'iframe') { el[0].nextSibling.style.setProperty('display', 'none'); } @@ -740,8 +741,9 @@ function handleOutstreamRendererEvents(bid, id, eventName) { } function outstreamRender(bid, doc) { - hidedfpContainer(bid.adUnitCode); - hideSASIframe(bid.adUnitCode); + const container = getAdUnitElement(bid); + hidedfpContainer(container); + hideSASIframe(container); bid.renderer.push(() => { const win = doc?.defaultView || window; if (win.ANOutstreamVideo) { From 76a187f43eec5cb0ca790becd6ef41ccbffd9cbe Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Thu, 12 Mar 2026 08:42:16 -0700 Subject: [PATCH 45/48] magnite utils: use getAdUnitElement --- libraries/magniteUtils/outstream.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/magniteUtils/outstream.js b/libraries/magniteUtils/outstream.js index ab6f16cf89d..59daeacae0c 100644 --- a/libraries/magniteUtils/outstream.js +++ b/libraries/magniteUtils/outstream.js @@ -1,5 +1,6 @@ import { Renderer } from '../../src/Renderer.js'; import { logWarn } from '../../src/utils.js'; +import { getAdUnitElement } from '../../src/utils/adUnits.js'; export const DEFAULT_RENDERER_URL = 'https://video-outstream.rubiconproject.com/apex-2.3.7.js'; @@ -26,7 +27,7 @@ export function hideSmartAdServerIframe(adUnit) { export function renderBid(bid) { // hide existing ad units - let adUnitElement = document.getElementById(bid.adUnitCode); + let adUnitElement = getAdUnitElement(bid); if (!adUnitElement) { logWarn(`Magnite: unable to find ad unit element with id "${bid.adUnitCode}" for rendering.`); return; From 87c93112f3a28849b740fc7d65a9ad83fa292160 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Thu, 12 Mar 2026 13:59:42 -0700 Subject: [PATCH 46/48] Prebid 11: normalize onBidViewable behavior (#14586) * Prebid 11: normalize onBidViewable behavior * lint --- libraries/bidViewabilityPixels/index.js | 13 +++++++++++++ modules/bidViewability.js | 16 ++-------------- modules/bidViewabilityIO.js | 5 ++--- test/spec/modules/bidViewabilityIO_spec.js | 22 ++++++++++++++++++++++ 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/libraries/bidViewabilityPixels/index.js b/libraries/bidViewabilityPixels/index.js index 1114e608548..63417940d53 100644 --- a/libraries/bidViewabilityPixels/index.js +++ b/libraries/bidViewabilityPixels/index.js @@ -1,6 +1,9 @@ import { EVENT_TYPE_VIEWABLE, parseEventTrackers, TRACKER_METHOD_IMG, TRACKER_METHOD_JS } from '../../src/eventTrackers.js'; import { filterEventTrackers, legacyPropertiesToOrtbNative } from '../../src/native.js'; import { triggerPixel, insertHtmlIntoIframe } from '../../src/utils.js'; +import * as events from '../../src/events.js'; +import { EVENTS } from '../../src/constants.js'; +import adapterManager from '../../src/adapterManager.js'; /** * Collects viewable tracking URLs from bid.eventtrackers for EVENT_TYPE_VIEWABLE (IMG and JS methods). @@ -45,3 +48,13 @@ export function fireViewabilityPixels(bid) { insertHtmlIntoIframe(markup); } } + +export function triggerBidViewable(bid) { + fireViewabilityPixels(bid); + // trigger respective bidder's onBidViewable handler + adapterManager.callBidViewableBidder(bid.adapterCode || bid.bidder, bid); + if (bid.deferBilling) { + adapterManager.triggerBilling(bid); + } + events.emit(EVENTS.BID_VIEWABLE, bid); +} diff --git a/modules/bidViewability.js b/modules/bidViewability.js index 0b367b6d149..191df92f8f6 100644 --- a/modules/bidViewability.js +++ b/modules/bidViewability.js @@ -3,12 +3,9 @@ // Does not work with other than GPT integration import { config } from '../src/config.js'; -import * as events from '../src/events.js'; -import { EVENTS } from '../src/constants.js'; import { isAdUnitCodeMatchingSlot, logWarn } from '../src/utils.js'; import { getGlobal } from '../src/prebidGlobal.js'; -import adapterManager from '../src/adapterManager.js'; -import { fireViewabilityPixels } from '../libraries/bidViewabilityPixels/index.js'; +import { triggerBidViewable } from '../libraries/bidViewabilityPixels/index.js'; const MODULE_NAME = 'bidViewability'; const CONFIG_ENABLED = 'enabled'; @@ -33,16 +30,7 @@ export const impressionViewableHandler = (globalModuleConfig, event) => { if (respectiveBid === null) { logWinningBidNotFound(slot); } else { - fireViewabilityPixels(respectiveBid); - // trigger respective bidder's onBidViewable handler - adapterManager.callBidViewableBidder(respectiveBid.adapterCode || respectiveBid.bidder, respectiveBid); - - if (respectiveBid.deferBilling) { - adapterManager.triggerBilling(respectiveBid); - } - - // emit the BID_VIEWABLE event with bid details, this event can be consumed by bidders and analytics pixels - events.emit(EVENTS.BID_VIEWABLE, respectiveBid); + triggerBidViewable(respectiveBid); } }; diff --git a/modules/bidViewabilityIO.js b/modules/bidViewabilityIO.js index 5e7480654d6..34dc03c168f 100644 --- a/modules/bidViewabilityIO.js +++ b/modules/bidViewabilityIO.js @@ -2,7 +2,7 @@ import { logMessage } from '../src/utils.js'; import { config } from '../src/config.js'; import * as events from '../src/events.js'; import { EVENTS } from '../src/constants.js'; -import { fireViewabilityPixels } from '../libraries/bidViewabilityPixels/index.js'; +import { triggerBidViewable } from '../libraries/bidViewabilityPixels/index.js'; import { getAdUnitElement } from '../src/utils/adUnits.js'; const MODULE_NAME = 'bidViewabilityIO'; @@ -44,8 +44,7 @@ export const getViewableOptions = (bid) => { export const markViewed = (bid, entry, observer) => { return () => { observer.unobserve(entry.target); - fireViewabilityPixels(bid); - events.emit(EVENTS.BID_VIEWABLE, bid); + triggerBidViewable(bid); _logMessage(`id: ${entry.target.getAttribute('id')} code: ${bid.adUnitCode} was viewed`); } } diff --git a/test/spec/modules/bidViewabilityIO_spec.js b/test/spec/modules/bidViewabilityIO_spec.js index e23e886c3d8..f76a0c6230b 100644 --- a/test/spec/modules/bidViewabilityIO_spec.js +++ b/test/spec/modules/bidViewabilityIO_spec.js @@ -5,6 +5,8 @@ import * as sinon from 'sinon'; import { expect } from 'chai'; import { EVENTS } from 'src/constants.js'; import { EVENT_TYPE_VIEWABLE, TRACKER_METHOD_IMG } from 'src/eventTrackers.js'; +import * as bidViewability from '../../../modules/bidViewability.js'; +import adapterManager from '../../../src/adapterManager.js'; describe('#bidViewabilityIO', function() { const makeElement = (id) => { @@ -145,6 +147,26 @@ describe('#bidViewabilityIO', function() { func(); expect(triggerPixelSpy.callCount).to.equal(0); }); + + it('should call onBidViewable', () => { + sandbox.stub(adapterManager, 'callBidViewableBidder'); + const bid = { + bidder: 'mockBidder', + ...banner_bid + } + bidViewabilityIO.markViewed(bid, mockEntry, mockObserver)(); + sinon.assert.calledWith(adapterManager.callBidViewableBidder, 'mockBidder', bid); + }); + + it('should call the triggerBilling function if the viewable bid has deferBilling set to true', function() { + sandbox.stub(adapterManager, 'triggerBilling'); + const bid = { + ...banner_bid, + deferBilling: true + } + bidViewabilityIO.markViewed(bid, mockEntry, mockObserver)(); + sinon.assert.called(adapterManager.triggerBilling); + }); }) describe('viewCallbackFactory tests', function() { From 4444f4eafea3cc49fcdade49b1342f3d07ab662b Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Thu, 12 Mar 2026 17:04:03 -0400 Subject: [PATCH 47/48] Delete scope3_segtax_pr.md --- scope3_segtax_pr.md | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 scope3_segtax_pr.md diff --git a/scope3_segtax_pr.md b/scope3_segtax_pr.md deleted file mode 100644 index 7589507f8a4..00000000000 --- a/scope3_segtax_pr.md +++ /dev/null @@ -1,35 +0,0 @@ -# Proposed Addition to segtax.md - -Add this line to the "Vendor-specific Taxonomies" section (in numerical order): - -``` -604: Scope3 Agentic Execution Engine (AEE) Targeting Signals -``` - -## PR Description Template: - -**Title:** Add Scope3 AEE Targeting Signals Taxonomy (segtax ID 604) - -**Description:** - -This PR registers Scope3's Agentic Execution Engine (AEE) targeting signal taxonomy for use in OpenRTB segment data. - -**Details:** -- **Taxonomy ID:** 604 -- **Name:** Scope3 Agentic Execution Engine (AEE) Targeting Signals -- **Purpose:** Identifies proprietary targeting signals generated by Scope3's AEE for real-time programmatic optimization -- **Usage:** These are opaque targeting codes (e.g., "x82s", "a91k") used for line item targeting decisions, not traditional audience segments - -**Contact:** [Your email] - -cc: @bretg @slimkrazy (as listed approvers in the document) - -## Alternative Higher ID: - -If you want to avoid any potential conflicts with IDs in the 600s range, you could use: - -``` -1001: Scope3 Agentic Execution Engine (AEE) Targeting Signals -``` - -This would put you well clear of any existing entries while still in the vendor-specific range. \ No newline at end of file From 55bc05552aa9332632069a12dd9882352ac6b5e3 Mon Sep 17 00:00:00 2001 From: Demetrio Girardi Date: Thu, 12 Mar 2026 15:28:31 -0700 Subject: [PATCH 48/48] taboola: fix missing import --- modules/taboolaBidAdapter.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/taboolaBidAdapter.js b/modules/taboolaBidAdapter.js index 9780961c17b..b4b04d4123a 100644 --- a/modules/taboolaBidAdapter.js +++ b/modules/taboolaBidAdapter.js @@ -3,7 +3,14 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, NATIVE } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; -import { deepSetValue, getWinDimensions, getWindowSelf, isPlainObject, replaceAuctionPrice } from '../src/utils.js'; +import { + deepSetValue, + getWinDimensions, + getWindowSelf, + isPlainObject, + replaceAuctionPrice, + safeJSONParse +} from '../src/utils.js'; import { getStorageManager } from '../src/storageManager.js'; import { ajax } from '../src/ajax.js'; import { ortbConverter } from '../libraries/ortbConverter/converter.js';