From 0ea3566039d10562af6e250ea3a2fd9f1fa84a65 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Tue, 30 Jul 2024 15:06:44 +0300 Subject: [PATCH 01/17] added consts for values --- modules/mgidBidAdapter.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index 5cfef325d2f..212a1682da4 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -56,6 +56,8 @@ const DEFAULT_IMAGE_HEIGHT = 328; const DEFAULT_ICON_WIDTH = 50; const DEFAULT_ICON_HEIGHT = 50; const DEFAULT_TITLE_LENGTH = 80; +const PIXEL_SYNC_URL = 'https://cm.mgid.com/i.gif'; +const IFRAME_SYNC_URL = 'https://cm.mgid.com/i.html'; let isInvalidNativeRequest = false; @@ -370,7 +372,7 @@ export const spec = { getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => { logInfo(LOG_INFO_PREFIX + `getUserSyncs`); const spb = isPlainObject(config.getConfig('userSync')) && - isNumber(config.getConfig('userSync').syncsPerBidder) + isNumber(config.getConfig('userSync').syncsPerBidder) ? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder; if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) { @@ -407,14 +409,14 @@ export const spec = { if (syncOptions.iframeEnabled) { syncs.push({ type: 'iframe', - url: 'https://cm.mgid.com/i.html?' + q.replace('{cbuster}', Math.round(new Date().getTime())) + url: IFRAME_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) }); } else if (syncOptions.pixelEnabled) { if (pixels.length === 0) { for (let i = 0; i < spb; i++) { syncs.push({ type: 'image', - url: 'https://cm.mgid.com/i.gif?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required + url: PIXEL_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required }); } } else { @@ -531,7 +533,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] }); } } } @@ -776,5 +778,5 @@ function getBidFloor(bid, cur) { if (reqCur === cur) { cur = '' } - return {floor: bidFloor, cur: cur} + return { floor: bidFloor, cur: cur } } From 26c051fe03e33ede44cb9205b46ccf7dbbb9b523 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Tue, 30 Jul 2024 15:35:52 +0300 Subject: [PATCH 02/17] added copy method --- modules/mgidBidAdapter.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index 212a1682da4..ba8db621467 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -14,12 +14,12 @@ import { isBoolean, isInteger, deepSetValue, getBidIdParameter, setOnAny } 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 {USERSYNC_DEFAULT_CONFIG} from '../src/userSync.js'; +import { USERSYNC_DEFAULT_CONFIG } from '../src/userSync.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -30,7 +30,7 @@ import {USERSYNC_DEFAULT_CONFIG} from '../src/userSync.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]: '; @@ -207,7 +207,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, @@ -692,18 +692,10 @@ function parseNativeResponse(bid, newBid) { newBid.native.title = adm.native.assets[i].title && adm.native.assets[i].title.text; break; case NATIVE_ASSETS.IMAGE.ID: - newBid.native.image = { - url: adm.native.assets[i].img && adm.native.assets[i].img.url, - height: adm.native.assets[i].img && adm.native.assets[i].img.h, - width: adm.native.assets[i].img && adm.native.assets[i].img.w, - }; + newBid.native.image = copyFromAdmAsset(adm.native.assets[i]); break; case NATIVE_ASSETS.ICON.ID: - newBid.native.icon = { - url: adm.native.assets[i].img && adm.native.assets[i].img.url, - height: adm.native.assets[i].img && adm.native.assets[i].img.h, - width: adm.native.assets[i].img && adm.native.assets[i].img.w, - }; + newBid.native.icon = copyFromAdmAsset(adm.native.assets[i]); break; case NATIVE_ASSETS.SPONSOREDBY.ID: case NATIVE_ASSETS.SPONSORED.ID: @@ -780,3 +772,11 @@ function getBidFloor(bid, cur) { } return { floor: bidFloor, cur: cur } } + +function copyFromAdmAsset(asset) { + return { + url: asset.img && asset.img.url, + height: asset.img && asset.img.h, + width: asset.img && asset.img.w, + } +} From 2b35da46392deafa8b40bc600e41843a7be93866 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Tue, 30 Jul 2024 15:41:32 +0300 Subject: [PATCH 03/17] moved extractDomainFromHost --- modules/mgidBidAdapter.js | 21 +++----------- modules/undertoneBidAdapter.js | 40 ++++++++------------------- src/utils.js | 50 +++++++++++++++++++++++----------- 3 files changed, 49 insertions(+), 62 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index ba8db621467..4089ad0d17d 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -12,6 +12,7 @@ import { isFn, isNumber, isBoolean, + extractDomainFromHost, isInteger, deepSetValue, getBidIdParameter, setOnAny } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; @@ -233,7 +234,7 @@ export const spec = { const page = deepAccess(bidderRequest, 'refererInfo.page') || info.location if (!isStr(deepAccess(request.site, 'domain'))) { const hostname = parseUrl(page).hostname; - request.site.domain = extractDomainFromHost(hostname) || hostname + request.site.domain = extractDomainFromHostExceptLocalhost(hostname) || hostname } if (!isStr(deepAccess(request.site, 'page'))) { request.site.page = page @@ -481,25 +482,11 @@ function setMediaType(bid, newBid) { } } -function extractDomainFromHost(pageHost) { +function extractDomainFromHostExceptLocalhost(pageHost) { if (pageHost === 'localhost') { return 'localhost' } - let domain = null; - try { - let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost); - if (domains != null && domains.length > 0) { - domain = domains[0]; - for (let i = 1; i < domains.length; i++) { - if (domains[i].length > domain.length) { - domain = domains[i]; - } - } - } - } catch (e) { - domain = null; - } - return domain; + return extractDomainFromHost(pageHost) } function getLanguage() { diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index c7e8102ffc9..9ade36b6e9c 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -2,9 +2,9 @@ * Adapter to send bids to Undertone */ -import {deepAccess, parseUrl} from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import { deepAccess, parseUrl, extractDomainFromHost } from '../src/utils.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; const BIDDER_CODE = 'undertone'; const URL = 'https://hb.undertone.com/hb'; @@ -26,24 +26,6 @@ function getBidFloor(bidRequest, mediaType) { return (floor && floor.currency === 'USD' && floor.floor) || 0; } -function extractDomainFromHost(pageHost) { - let domain = null; - try { - let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost); - if (domains != null && domains.length > 0) { - domain = domains[0]; - for (let i = 1; i < domains.length; i++) { - if (domains[i].length > domain.length) { - domain = domains[i]; - } - } - } - } catch (e) { - domain = null; - } - return domain; -} - function getGdprQueryParams(gdprConsent) { if (!gdprConsent) { return null; @@ -78,13 +60,13 @@ export const spec = { code: BIDDER_CODE, gvlid: 677, supportedMediaTypes: [BANNER, VIDEO], - isBidRequestValid: function(bid) { + isBidRequestValid: function (bid) { if (bid && bid.params && bid.params.publisherId) { bid.params.publisherId = parseInt(bid.params.publisherId); return true; } }, - buildRequests: function(validBidRequests, bidderRequest) { + buildRequests: function (validBidRequests, bidderRequest) { const vw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); const vh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); const pageSizeArray = vw == 0 || vh == 0 ? null : [vw, vh]; @@ -168,7 +150,7 @@ export const spec = { data: JSON.stringify(payload) }; }, - interpretResponse: function(serverResponse, request) { + interpretResponse: function (serverResponse, request) { const bids = []; const body = serverResponse.body; @@ -198,7 +180,7 @@ export const spec = { } return bids; }, - getUserSyncs: function(syncOptions, serverResponses, gdprConsent, usPrivacy) { + getUserSyncs: function (syncOptions, serverResponses, gdprConsent, usPrivacy) { const syncs = []; let gdprParams = getGdprQueryParams(gdprConsent); @@ -230,10 +212,10 @@ export const spec = { type: 'image', url: PIXEL_USER_SYNC_1 + pixelPrivacyParams }, - { - type: 'image', - url: PIXEL_USER_SYNC_2 + pixelPrivacyParams - }); + { + type: 'image', + url: PIXEL_USER_SYNC_2 + pixelPrivacyParams + }); } return syncs; } diff --git a/src/utils.js b/src/utils.js index ec227c6d74b..0d4dc801695 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,9 +1,9 @@ -import {config} from './config.js'; -import {klona} from 'klona/json'; -import {includes} from './polyfill.js'; +import { config } from './config.js'; +import { klona } from 'klona/json'; +import { includes } from './polyfill.js'; import { EVENTS, S2S } from './constants.js'; -import {GreedyPromise} from './utils/promise.js'; -import {getGlobal} from './prebidGlobal.js'; +import { GreedyPromise } from './utils/promise.js'; +import { getGlobal } from './prebidGlobal.js'; import { default as deepAccess } from 'dlv/index.js'; export { deepAccess }; @@ -172,7 +172,7 @@ export function parseGPTSingleSizeArray(singleSize) { } export function sizeTupleToRtbSize(size) { - return {w: size[0], h: size[1]}; + return { w: size[0], h: size[1] }; } // Parse a GPT style single size array, (i.e [300, 250]) @@ -430,7 +430,7 @@ export function insertElement(elm, doc, target, asLastChildChild) { let insertBeforeEl = asLastChildChild ? null : parentEl.firstChild; return parentEl.insertBefore(elm, insertBeforeEl); } - } catch (e) {} + } catch (e) { } } /** @@ -444,7 +444,7 @@ export function insertElement(elm, doc, target, asLastChildChild) { export function waitForElementToLoad(element, timeout) { let timer = null; return new GreedyPromise((resolve) => { - const onLoad = function() { + const onLoad = function () { element.removeEventListener('load', onLoad); element.removeEventListener('error', onLoad); if (timer != null) { @@ -689,7 +689,7 @@ export function replaceMacros(str, subs) { } export function replaceAuctionPrice(str, cpm) { - return replaceMacros(str, {AUCTION_PRICE: cpm}) + return replaceMacros(str, { AUCTION_PRICE: cpm }) } export function replaceClickThrough(str, clicktag) { @@ -786,7 +786,7 @@ export function delayExecution(func, numRequiredCalls) { * @returns {Object} {${key_value}: ${groupByArray}, key_value: {groupByArray}} */ export function groupBy(xs, key) { - return xs.reduce(function(rv, x) { + return xs.reduce(function (rv, x) { (rv[x[key]] = rv[x[key]] || []).push(x); return rv; }, {}); @@ -874,7 +874,7 @@ export function isAdUnitCodeMatchingSlot(slot) { * @return {string} warning message to display when condition is met */ export function unsupportedBidderMessage(adUnit, bidder) { - const mediaType = Object.keys(adUnit.mediaTypes || {'banner': 'banner'}).join(', '); + const mediaType = Object.keys(adUnit.mediaTypes || { 'banner': 'banner' }).join(', '); return ` ${adUnit.code} is a ${mediaType} ad unit @@ -1000,7 +1000,7 @@ export function buildUrl(obj) { * @param {boolean} [options.checkTypes=false] - If set, two objects with identical properties but different constructors will *not* be considered equivalent. * @returns {boolean} - Returns `true` if the objects are equivalent, `false` otherwise. */ -export function deepEqual(obj1, obj2, {checkTypes = false} = {}) { +export function deepEqual(obj1, obj2, { checkTypes = false } = {}) { if (obj1 === obj2) return true; else if ( (typeof obj1 === 'object' && obj1 !== null) && @@ -1011,7 +1011,7 @@ export function deepEqual(obj1, obj2, {checkTypes = false} = {}) { if (props1.length !== Object.keys(obj2).length) return false; for (let prop of props1) { if (obj2.hasOwnProperty(prop)) { - if (!deepEqual(obj1[prop], obj2[prop], {checkTypes})) { + if (!deepEqual(obj1[prop], obj2[prop], { checkTypes })) { return false; } } else { @@ -1069,7 +1069,7 @@ export function mergeDeep(target, ...sources) { export function cyrb53Hash(str, seed = 0) { // IE doesn't support imul // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul#Polyfill - let imul = function(opA, opB) { + let imul = function (opA, opB) { if (isFn(Math.imul)) { return Math.imul(opA, opB); } else { @@ -1107,7 +1107,7 @@ export function cyrb53Hash(str, seed = 0) { export function safeJSONParse(data) { try { return JSON.parse(data); - } catch (e) {} + } catch (e) { } } export function safeJSONEncode(data) { @@ -1162,7 +1162,7 @@ export function getUnixTimestampFromNow(timeValue = 0, timeUnit = 'd') { */ export function convertObjectToArray(obj) { return Object.keys(obj).map(key => { - return {[key]: obj[key]}; + return { [key]: obj[key] }; }); } @@ -1258,3 +1258,21 @@ export function setOnAny(collection, key) { } return undefined; } + +export function extractDomainFromHost(pageHost) { + let domain = null; + try { + let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost); + if (domains != null && domains.length > 0) { + domain = domains[0]; + for (let i = 1; i < domains.length; i++) { + if (domains[i].length > domain.length) { + domain = domains[i]; + } + } + } + } catch (e) { + domain = null; + } + return domain; +} From 4bf6bc458f5f851a03b965020d28bb4822f2fd2f Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Tue, 30 Jul 2024 16:09:35 +0300 Subject: [PATCH 04/17] added method triggerNurlWithCpm --- modules/mgidBidAdapter.js | 11 ++++------- modules/redtramBidAdapter.js | 7 ++----- src/utils.js | 10 ++++++++++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index 4089ad0d17d..8202c04b617 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -8,6 +8,7 @@ import { parseUrl, isEmpty, triggerPixel, + triggerNurlWithCpm, logWarn, isFn, isNumber, @@ -347,13 +348,9 @@ export const spec = { }, onBidWon: (bid) => { const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || ''; - if (isStr(bid.nurl) && bid.nurl !== '') { - bid.nurl = bid.nurl.replace( - /\${AUCTION_PRICE}/, - cpm - ); - triggerPixel(bid.nurl); - } + + triggerNurlWithCpm(bid, cpm) + if (bid.isBurl) { if (bid.mediaType === BANNER) { bid.ad = bid.ad.replace( diff --git a/modules/redtramBidAdapter.js b/modules/redtramBidAdapter.js index e1dc0e2a148..d544e08cf2a 100644 --- a/modules/redtramBidAdapter.js +++ b/modules/redtramBidAdapter.js @@ -3,7 +3,7 @@ import { isStr, deepAccess, getWindowTop, - triggerPixel + triggerNurlWithCpm } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; @@ -145,10 +145,7 @@ export const spec = { onBidWon: (bid) => { const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || ''; - if (isStr(bid.nurl) && bid.nurl !== '') { - bid.nurl = bid.nurl.replace(/\${AUCTION_PRICE}/, cpm); - triggerPixel(bid.nurl); - } + triggerNurlWithCpm(bid, cpm) } }; diff --git a/src/utils.js b/src/utils.js index 0d4dc801695..5caa9e34540 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1276,3 +1276,13 @@ export function extractDomainFromHost(pageHost) { } return domain; } + +export function triggerNurlWithCpm(bid, cpm) { + if (isStr(bid.nurl) && bid.nurl !== '') { + bid.nurl = bid.nurl.replace( + /\${AUCTION_PRICE}/, + cpm + ); + triggerPixel(bid.nurl); + } +} From 9354d05355db77b16a023a40b1db025c74aa48c7 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Tue, 30 Jul 2024 16:54:42 +0300 Subject: [PATCH 05/17] added getUserSyncs --- modules/mgidBidAdapter.js | 125 +++++++++++++++++++------------------ modules/mgidXBidAdapter.js | 63 +------------------ 2 files changed, 65 insertions(+), 123 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index 8202c04b617..9cf2ffc5ef9 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -367,68 +367,7 @@ export const spec = { } logInfo(LOG_INFO_PREFIX + `onBidWon`); }, - getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => { - logInfo(LOG_INFO_PREFIX + `getUserSyncs`); - const spb = isPlainObject(config.getConfig('userSync')) && - isNumber(config.getConfig('userSync').syncsPerBidder) - ? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder; - - if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) { - let pixels = []; - if (serverResponses && - isArray(serverResponses) && - serverResponses.length > 0 && - isPlainObject(serverResponses[0].body) && - isPlainObject(serverResponses[0].body.ext) && - isArray(serverResponses[0].body.ext.cm) && - serverResponses[0].body.ext.cm.length > 0) { - pixels = serverResponses[0].body.ext.cm; - } - - const syncs = []; - const query = []; - query.push('cbuster={cbuster}'); - query.push('gdpr_consent=' + encodeURIComponent(isPlainObject(gdprConsent) && isStr(gdprConsent?.consentString) ? gdprConsent.consentString : '')); - if (isPlainObject(gdprConsent) && typeof gdprConsent?.gdprApplies === 'boolean' && gdprConsent.gdprApplies) { - query.push('gdpr=1'); - } else { - query.push('gdpr=0'); - } - if (isPlainObject(uspConsent) && uspConsent?.consentString) { - query.push(`us_privacy=${encodeURIComponent(uspConsent?.consentString)}`); - } - if (isPlainObject(gppConsent) && gppConsent?.gppString) { - query.push(`gppString=${encodeURIComponent(gppConsent?.gppString)}`); - } - if (config.getConfig('coppa')) { - query.push('coppa=1') - } - const q = query.join('&') - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: IFRAME_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) - }); - } else if (syncOptions.pixelEnabled) { - if (pixels.length === 0) { - for (let i = 0; i < spb; i++) { - syncs.push({ - type: 'image', - url: PIXEL_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required - }); - } - } else { - for (let i = 0; i < spb && i < pixels.length; i++) { - syncs.push({ - type: 'image', - url: pixels[i] + (pixels[i].indexOf('?') > 0 ? '&' : '?') + q.replace('{cbuster}', Math.round(new Date().getTime())) - }); - } - } - } - return syncs; - } - } + getUserSyncs: getUserSyncs, }; registerBidder(spec); @@ -764,3 +703,65 @@ function copyFromAdmAsset(asset) { width: asset.img && asset.img.w, } } + +export function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) { + const spb = isPlainObject(config.getConfig('userSync')) && + isNumber(config.getConfig('userSync').syncsPerBidder) + ? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder; + + if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) { + let pixels = []; + if (serverResponses && + isArray(serverResponses) && + serverResponses.length > 0 && + isPlainObject(serverResponses[0].body) && + isPlainObject(serverResponses[0].body.ext) && + isArray(serverResponses[0].body.ext.cm) && + serverResponses[0].body.ext.cm.length > 0) { + pixels = serverResponses[0].body.ext.cm; + } + + const syncs = []; + const query = []; + query.push('cbuster={cbuster}'); + query.push('gdpr_consent=' + encodeURIComponent(isPlainObject(gdprConsent) && isStr(gdprConsent?.consentString) ? gdprConsent.consentString : '')); + if (isPlainObject(gdprConsent) && typeof gdprConsent?.gdprApplies === 'boolean' && gdprConsent.gdprApplies) { + query.push('gdpr=1'); + } else { + query.push('gdpr=0'); + } + if (isPlainObject(uspConsent) && uspConsent?.consentString) { + query.push(`us_privacy=${encodeURIComponent(uspConsent?.consentString)}`); + } + if (isPlainObject(gppConsent) && gppConsent?.gppString) { + query.push(`gppString=${encodeURIComponent(gppConsent?.gppString)}`); + } + if (config.getConfig('coppa')) { + query.push('coppa=1') + } + const q = query.join('&') + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: IFRAME_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) + }); + } else if (syncOptions.pixelEnabled) { + if (pixels.length === 0) { + for (let i = 0; i < spb; i++) { + syncs.push({ + type: 'image', + url: PIXEL_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required + }); + } + } else { + for (let i = 0; i < spb && i < pixels.length; i++) { + syncs.push({ + type: 'image', + url: pixels[i] + (pixels[i].indexOf('?') > 0 ? '&' : '?') + q.replace('{cbuster}', Math.round(new Date().getTime())) + }); + } + } + } + return syncs; + } +} diff --git a/modules/mgidXBidAdapter.js b/modules/mgidXBidAdapter.js index 471e8fb2754..11dda9b9105 100644 --- a/modules/mgidXBidAdapter.js +++ b/modules/mgidXBidAdapter.js @@ -4,6 +4,7 @@ import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { USERSYNC_DEFAULT_CONFIG } from '../src/userSync.js'; import { isBidRequestValid, buildRequestsBase, interpretResponse } from '../libraries/teqblazeUtils/bidderUtils.js'; +import { getUserSyncs } from './mgidBidAdapter.js' const BIDDER_CODE = 'mgidX'; const GVLID = 358; @@ -33,67 +34,7 @@ export const spec = { buildRequests, interpretResponse, - getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => { - const spb = isPlainObject(config.getConfig('userSync')) && - isNumber(config.getConfig('userSync').syncsPerBidder) - ? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder; - - if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) { - let pixels = []; - if (serverResponses && - isArray(serverResponses) && - serverResponses.length > 0 && - isPlainObject(serverResponses[0].body) && - isPlainObject(serverResponses[0].body.ext) && - isArray(serverResponses[0].body.ext.cm) && - serverResponses[0].body.ext.cm.length > 0) { - pixels = serverResponses[0].body.ext.cm; - } - - const syncs = []; - const query = []; - query.push('cbuster={cbuster}'); - query.push('gdpr_consent=' + encodeURIComponent(isPlainObject(gdprConsent) && isStr(gdprConsent?.consentString) ? gdprConsent.consentString : '')); - if (isPlainObject(gdprConsent) && typeof gdprConsent?.gdprApplies === 'boolean' && gdprConsent.gdprApplies) { - query.push('gdpr=1'); - } else { - query.push('gdpr=0'); - } - if (isPlainObject(uspConsent) && uspConsent?.consentString) { - query.push(`us_privacy=${encodeURIComponent(uspConsent?.consentString)}`); - } - if (isPlainObject(gppConsent) && gppConsent?.gppString) { - query.push(`gppString=${encodeURIComponent(gppConsent?.gppString)}`); - } - if (config.getConfig('coppa')) { - query.push('coppa=1') - } - const q = query.join('&') - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: IFRAME_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) - }); - } else if (syncOptions.pixelEnabled) { - if (pixels.length === 0) { - for (let i = 0; i < spb; i++) { - syncs.push({ - type: 'image', - url: PIXEL_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required - }); - } - } else { - for (let i = 0; i < spb && i < pixels.length; i++) { - syncs.push({ - type: 'image', - url: pixels[i] + (pixels[i].indexOf('?') > 0 ? '&' : '?') + q.replace('{cbuster}', Math.round(new Date().getTime())) - }); - } - } - } - return syncs; - } - } + getUserSyncs: getUserSyncs, }; registerBidder(spec); From 4a4e5957f9f5ac5d9c845606f0ecca004058db21 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Tue, 30 Jul 2024 17:18:46 +0300 Subject: [PATCH 06/17] less formatting mgidBid --- modules/mgidBidAdapter.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index 9cf2ffc5ef9..b8dc5434510 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -16,12 +16,12 @@ import { extractDomainFromHost, isInteger, deepSetValue, getBidIdParameter, setOnAny } 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 { USERSYNC_DEFAULT_CONFIG } from '../src/userSync.js'; +import {USERSYNC_DEFAULT_CONFIG} from '../src/userSync.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -209,7 +209,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, @@ -456,7 +456,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]}); } } } @@ -693,7 +693,7 @@ function getBidFloor(bid, cur) { if (reqCur === cur) { cur = '' } - return { floor: bidFloor, cur: cur } + return {floor: bidFloor, cur: cur} } function copyFromAdmAsset(asset) { From b05dd614046d886033467c95af783f124328d7b1 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Tue, 30 Jul 2024 17:23:00 +0300 Subject: [PATCH 07/17] less formatting undertoneBid --- modules/undertoneBidAdapter.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index 9ade36b6e9c..1ea2f2c1ce6 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -2,9 +2,9 @@ * Adapter to send bids to Undertone */ -import { deepAccess, parseUrl, extractDomainFromHost } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import {deepAccess, parseUrl, extractDomainFromHost} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {BANNER, VIDEO} from '../src/mediaTypes.js'; const BIDDER_CODE = 'undertone'; const URL = 'https://hb.undertone.com/hb'; @@ -60,13 +60,13 @@ export const spec = { code: BIDDER_CODE, gvlid: 677, supportedMediaTypes: [BANNER, VIDEO], - isBidRequestValid: function (bid) { + isBidRequestValid: function(bid) { if (bid && bid.params && bid.params.publisherId) { bid.params.publisherId = parseInt(bid.params.publisherId); return true; } }, - buildRequests: function (validBidRequests, bidderRequest) { + buildRequests: function(validBidRequests, bidderRequest) { const vw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); const vh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); const pageSizeArray = vw == 0 || vh == 0 ? null : [vw, vh]; @@ -150,7 +150,7 @@ export const spec = { data: JSON.stringify(payload) }; }, - interpretResponse: function (serverResponse, request) { + interpretResponse: function(serverResponse, request) { const bids = []; const body = serverResponse.body; @@ -180,7 +180,7 @@ export const spec = { } return bids; }, - getUserSyncs: function (syncOptions, serverResponses, gdprConsent, usPrivacy) { + getUserSyncs: function(syncOptions, serverResponses, gdprConsent, usPrivacy) { const syncs = []; let gdprParams = getGdprQueryParams(gdprConsent); @@ -212,10 +212,10 @@ export const spec = { type: 'image', url: PIXEL_USER_SYNC_1 + pixelPrivacyParams }, - { - type: 'image', - url: PIXEL_USER_SYNC_2 + pixelPrivacyParams - }); + { + type: 'image', + url: PIXEL_USER_SYNC_2 + pixelPrivacyParams + }); } return syncs; } From 3f8ef11dff1125821a5680607b3bfeef317cd681 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Tue, 30 Jul 2024 17:27:57 +0300 Subject: [PATCH 08/17] less formatting utils --- src/utils.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/utils.js b/src/utils.js index 5caa9e34540..64880b4a462 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,9 +1,9 @@ -import { config } from './config.js'; -import { klona } from 'klona/json'; -import { includes } from './polyfill.js'; +import {config} from './config.js'; +import {klona} from 'klona/json'; +import {includes} from './polyfill.js'; import { EVENTS, S2S } from './constants.js'; -import { GreedyPromise } from './utils/promise.js'; -import { getGlobal } from './prebidGlobal.js'; +import {GreedyPromise} from './utils/promise.js'; +import {getGlobal} from './prebidGlobal.js'; import { default as deepAccess } from 'dlv/index.js'; export { deepAccess }; @@ -172,7 +172,7 @@ export function parseGPTSingleSizeArray(singleSize) { } export function sizeTupleToRtbSize(size) { - return { w: size[0], h: size[1] }; + return {w: size[0], h: size[1]}; } // Parse a GPT style single size array, (i.e [300, 250]) @@ -430,7 +430,7 @@ export function insertElement(elm, doc, target, asLastChildChild) { let insertBeforeEl = asLastChildChild ? null : parentEl.firstChild; return parentEl.insertBefore(elm, insertBeforeEl); } - } catch (e) { } + } catch (e) {} } /** @@ -444,7 +444,7 @@ export function insertElement(elm, doc, target, asLastChildChild) { export function waitForElementToLoad(element, timeout) { let timer = null; return new GreedyPromise((resolve) => { - const onLoad = function () { + const onLoad = function() { element.removeEventListener('load', onLoad); element.removeEventListener('error', onLoad); if (timer != null) { @@ -689,7 +689,7 @@ export function replaceMacros(str, subs) { } export function replaceAuctionPrice(str, cpm) { - return replaceMacros(str, { AUCTION_PRICE: cpm }) + return replaceMacros(str, {AUCTION_PRICE: cpm}) } export function replaceClickThrough(str, clicktag) { @@ -786,7 +786,7 @@ export function delayExecution(func, numRequiredCalls) { * @returns {Object} {${key_value}: ${groupByArray}, key_value: {groupByArray}} */ export function groupBy(xs, key) { - return xs.reduce(function (rv, x) { + return xs.reduce(function(rv, x) { (rv[x[key]] = rv[x[key]] || []).push(x); return rv; }, {}); @@ -874,7 +874,7 @@ export function isAdUnitCodeMatchingSlot(slot) { * @return {string} warning message to display when condition is met */ export function unsupportedBidderMessage(adUnit, bidder) { - const mediaType = Object.keys(adUnit.mediaTypes || { 'banner': 'banner' }).join(', '); + const mediaType = Object.keys(adUnit.mediaTypes || {'banner': 'banner'}).join(', '); return ` ${adUnit.code} is a ${mediaType} ad unit @@ -1000,7 +1000,7 @@ export function buildUrl(obj) { * @param {boolean} [options.checkTypes=false] - If set, two objects with identical properties but different constructors will *not* be considered equivalent. * @returns {boolean} - Returns `true` if the objects are equivalent, `false` otherwise. */ -export function deepEqual(obj1, obj2, { checkTypes = false } = {}) { +export function deepEqual(obj1, obj2, {checkTypes = false} = {}) { if (obj1 === obj2) return true; else if ( (typeof obj1 === 'object' && obj1 !== null) && @@ -1011,7 +1011,7 @@ export function deepEqual(obj1, obj2, { checkTypes = false } = {}) { if (props1.length !== Object.keys(obj2).length) return false; for (let prop of props1) { if (obj2.hasOwnProperty(prop)) { - if (!deepEqual(obj1[prop], obj2[prop], { checkTypes })) { + if (!deepEqual(obj1[prop], obj2[prop], {checkTypes})) { return false; } } else { @@ -1069,7 +1069,7 @@ export function mergeDeep(target, ...sources) { export function cyrb53Hash(str, seed = 0) { // IE doesn't support imul // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul#Polyfill - let imul = function (opA, opB) { + let imul = function(opA, opB) { if (isFn(Math.imul)) { return Math.imul(opA, opB); } else { @@ -1107,7 +1107,7 @@ export function cyrb53Hash(str, seed = 0) { export function safeJSONParse(data) { try { return JSON.parse(data); - } catch (e) { } + } catch (e) {} } export function safeJSONEncode(data) { @@ -1162,7 +1162,7 @@ export function getUnixTimestampFromNow(timeValue = 0, timeUnit = 'd') { */ export function convertObjectToArray(obj) { return Object.keys(obj).map(key => { - return { [key]: obj[key] }; + return {[key]: obj[key]}; }); } From 60108e6113d5701a008acd6810044eae7880353e Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Tue, 30 Jul 2024 17:34:33 +0300 Subject: [PATCH 09/17] renamed adm to nativeAdm --- modules/mgidBidAdapter.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index b8dc5434510..d1f1a222b9b 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -600,25 +600,25 @@ function commonNativeRequestObject(nativeAsset, params) { function parseNativeResponse(bid, newBid) { newBid.native = {}; if (bid.hasOwnProperty('adm')) { - let adm = ''; + let nativeAdm = ''; try { - adm = JSON.parse(bid.adm); + nativeAdm = JSON.parse(bid.adm); } catch (ex) { logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native response for ad response: ' + newBid.adm); return; } - if (adm && adm.native && adm.native.assets && adm.native.assets.length > 0) { + if (nativeAdm && nativeAdm.native && nativeAdm.native.assets && nativeAdm.native.assets.length > 0) { newBid.mediaType = NATIVE; - for (let i = 0, len = adm.native.assets.length; i < len; i++) { - switch (adm.native.assets[i].id) { + for (let i = 0, len = nativeAdm.native.assets.length; i < len; i++) { + switch (nativeAdm.native.assets[i].id) { case NATIVE_ASSETS.TITLE.ID: - newBid.native.title = adm.native.assets[i].title && adm.native.assets[i].title.text; + newBid.native.title = nativeAdm.native.assets[i].title && nativeAdm.native.assets[i].title.text; break; case NATIVE_ASSETS.IMAGE.ID: - newBid.native.image = copyFromAdmAsset(adm.native.assets[i]); + newBid.native.image = copyFromAdmAsset(nativeAdm.native.assets[i]); break; case NATIVE_ASSETS.ICON.ID: - newBid.native.icon = copyFromAdmAsset(adm.native.assets[i]); + newBid.native.icon = copyFromAdmAsset(nativeAdm.native.assets[i]); break; case NATIVE_ASSETS.SPONSOREDBY.ID: case NATIVE_ASSETS.SPONSORED.ID: @@ -628,14 +628,14 @@ function parseNativeResponse(bid, newBid) { case NATIVE_ASSETS.BODY.ID: case NATIVE_ASSETS.DISPLAYURL.ID: case NATIVE_ASSETS.CTA.ID: - newBid.native[spec.NATIVE_ASSET_ID_TO_KEY_MAP[adm.native.assets[i].id]] = adm.native.assets[i].data && adm.native.assets[i].data.value; + newBid.native[spec.NATIVE_ASSET_ID_TO_KEY_MAP[nativeAdm.native.assets[i].id]] = nativeAdm.native.assets[i].data && nativeAdm.native.assets[i].data.value; break; } } - newBid.native.clickUrl = adm.native.link && adm.native.link.url; - newBid.native.clickTrackers = (adm.native.link && adm.native.link.clicktrackers) || []; - newBid.native.impressionTrackers = adm.native.imptrackers || []; - newBid.native.jstracker = adm.native.jstracker || []; + newBid.native.clickUrl = nativeAdm.native.link && nativeAdm.native.link.url; + newBid.native.clickTrackers = (nativeAdm.native.link && nativeAdm.native.link.clicktrackers) || []; + newBid.native.impressionTrackers = nativeAdm.native.imptrackers || []; + newBid.native.jstracker = nativeAdm.native.jstracker || []; newBid.width = 0; newBid.height = 0; } From df55f3d6c7562138ff11d1256dce9b6f59b157e0 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Wed, 31 Jul 2024 14:35:31 +0300 Subject: [PATCH 10/17] back changes for other adaptes --- modules/redtramBidAdapter.js | 7 +++++-- modules/undertoneBidAdapter.js | 20 +++++++++++++++++++- test/spec/modules/mgidBidAdapter_spec.js | 20 ++++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/modules/redtramBidAdapter.js b/modules/redtramBidAdapter.js index d544e08cf2a..e1dc0e2a148 100644 --- a/modules/redtramBidAdapter.js +++ b/modules/redtramBidAdapter.js @@ -3,7 +3,7 @@ import { isStr, deepAccess, getWindowTop, - triggerNurlWithCpm + triggerPixel } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; @@ -145,7 +145,10 @@ export const spec = { onBidWon: (bid) => { const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || ''; - triggerNurlWithCpm(bid, cpm) + if (isStr(bid.nurl) && bid.nurl !== '') { + bid.nurl = bid.nurl.replace(/\${AUCTION_PRICE}/, cpm); + triggerPixel(bid.nurl); + } } }; diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index 1ea2f2c1ce6..c7e8102ffc9 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -2,7 +2,7 @@ * Adapter to send bids to Undertone */ -import {deepAccess, parseUrl, extractDomainFromHost} from '../src/utils.js'; +import {deepAccess, parseUrl} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; @@ -26,6 +26,24 @@ function getBidFloor(bidRequest, mediaType) { return (floor && floor.currency === 'USD' && floor.floor) || 0; } +function extractDomainFromHost(pageHost) { + let domain = null; + try { + let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost); + if (domains != null && domains.length > 0) { + domain = domains[0]; + for (let i = 1; i < domains.length; i++) { + if (domains[i].length > domain.length) { + domain = domains[i]; + } + } + } + } catch (e) { + domain = null; + } + return domain; +} + function getGdprQueryParams(gdprConsent) { if (!gdprConsent) { return null; diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index 180b0dc723e..e8481cd17fe 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -1032,3 +1032,23 @@ describe('Mgid bid adapter', function () { }); }); }); + +describe('copyFromAdmAsset', function() { + it('should return all params', function() { + const asset = {img: {w: 80, h: 80, url: "image_src"}} + const returned = spec.copyFromAdmAsset(asset) + expect(returned).to.deep.equal({url: "image_src", height: 80, width: 80}); + }); + + it('should return only height and width', function() { + const asset = {img: {w: 80, h: 80}} + const returned = spec.copyFromAdmAsset(asset) + expect(returned).to.deep.equal({height: 80, width: 80}); + }); + + it('should return nothing', function() { + const asset = {} + const returned = spec.copyFromAdmAsset(asset) + expect(returned).to.deep.equal({}); + }); +}); From dfc2a7ebd0dc0dd12b7c17138245b48d991ac0d2 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Wed, 31 Jul 2024 14:48:46 +0300 Subject: [PATCH 11/17] back changes --- modules/redtramBidAdapter.js | 7 ++----- modules/undertoneBidAdapter.js | 20 +------------------- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/modules/redtramBidAdapter.js b/modules/redtramBidAdapter.js index e1dc0e2a148..d544e08cf2a 100644 --- a/modules/redtramBidAdapter.js +++ b/modules/redtramBidAdapter.js @@ -3,7 +3,7 @@ import { isStr, deepAccess, getWindowTop, - triggerPixel + triggerNurlWithCpm } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER } from '../src/mediaTypes.js'; @@ -145,10 +145,7 @@ export const spec = { onBidWon: (bid) => { const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || ''; - if (isStr(bid.nurl) && bid.nurl !== '') { - bid.nurl = bid.nurl.replace(/\${AUCTION_PRICE}/, cpm); - triggerPixel(bid.nurl); - } + triggerNurlWithCpm(bid, cpm) } }; diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index c7e8102ffc9..1ea2f2c1ce6 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -2,7 +2,7 @@ * Adapter to send bids to Undertone */ -import {deepAccess, parseUrl} from '../src/utils.js'; +import {deepAccess, parseUrl, extractDomainFromHost} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; @@ -26,24 +26,6 @@ function getBidFloor(bidRequest, mediaType) { return (floor && floor.currency === 'USD' && floor.floor) || 0; } -function extractDomainFromHost(pageHost) { - let domain = null; - try { - let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost); - if (domains != null && domains.length > 0) { - domain = domains[0]; - for (let i = 1; i < domains.length; i++) { - if (domains[i].length > domain.length) { - domain = domains[i]; - } - } - } - } catch (e) { - domain = null; - } - return domain; -} - function getGdprQueryParams(gdprConsent) { if (!gdprConsent) { return null; From 1a4061a165f643a94590af91809c71fdfcb6f45d Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Wed, 31 Jul 2024 15:02:17 +0300 Subject: [PATCH 12/17] moved getUserSyncs to lib pkg --- libraries/mgidUtils/mgidUtils.js | 71 ++++++++++++++++++++++++++++++++ modules/mgidBidAdapter.js | 64 +--------------------------- modules/mgidXBidAdapter.js | 2 +- 3 files changed, 74 insertions(+), 63 deletions(-) create mode 100644 libraries/mgidUtils/mgidUtils.js diff --git a/libraries/mgidUtils/mgidUtils.js b/libraries/mgidUtils/mgidUtils.js new file mode 100644 index 00000000000..a007b76307f --- /dev/null +++ b/libraries/mgidUtils/mgidUtils.js @@ -0,0 +1,71 @@ +import { + _each, + isPlainObject, + isArray, + isStr, + isNumber, +} from '../src/utils.js'; +import { config } from '../src/config.js'; +import { USERSYNC_DEFAULT_CONFIG } from '../src/userSync.js'; + +export function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) { + const spb = isPlainObject(config.getConfig('userSync')) && + isNumber(config.getConfig('userSync').syncsPerBidder) + ? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder; + + if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) { + let pixels = []; + if (serverResponses && + isArray(serverResponses) && + serverResponses.length > 0 && + isPlainObject(serverResponses[0].body) && + isPlainObject(serverResponses[0].body.ext) && + isArray(serverResponses[0].body.ext.cm) && + serverResponses[0].body.ext.cm.length > 0) { + pixels = serverResponses[0].body.ext.cm; + } + + const syncs = []; + const query = []; + query.push('cbuster={cbuster}'); + query.push('gdpr_consent=' + encodeURIComponent(isPlainObject(gdprConsent) && isStr(gdprConsent?.consentString) ? gdprConsent.consentString : '')); + if (isPlainObject(gdprConsent) && typeof gdprConsent?.gdprApplies === 'boolean' && gdprConsent.gdprApplies) { + query.push('gdpr=1'); + } else { + query.push('gdpr=0'); + } + if (isPlainObject(uspConsent) && uspConsent?.consentString) { + query.push(`us_privacy=${encodeURIComponent(uspConsent?.consentString)}`); + } + if (isPlainObject(gppConsent) && gppConsent?.gppString) { + query.push(`gppString=${encodeURIComponent(gppConsent?.gppString)}`); + } + if (config.getConfig('coppa')) { + query.push('coppa=1') + } + const q = query.join('&') + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: IFRAME_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) + }); + } else if (syncOptions.pixelEnabled) { + if (pixels.length === 0) { + for (let i = 0; i < spb; i++) { + syncs.push({ + type: 'image', + url: PIXEL_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required + }); + } + } else { + for (let i = 0; i < spb && i < pixels.length; i++) { + syncs.push({ + type: 'image', + url: pixels[i] + (pixels[i].indexOf('?') > 0 ? '&' : '?') + q.replace('{cbuster}', Math.round(new Date().getTime())) + }); + } + } + } + return syncs; + } +} diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index d1f1a222b9b..d113c622bfd 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -22,6 +22,8 @@ import {config} from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import {USERSYNC_DEFAULT_CONFIG} from '../src/userSync.js'; +import {USERSYNC_DEFAULT_CONFIG} from '../src/userSync.js'; +import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -703,65 +705,3 @@ function copyFromAdmAsset(asset) { width: asset.img && asset.img.w, } } - -export function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) { - const spb = isPlainObject(config.getConfig('userSync')) && - isNumber(config.getConfig('userSync').syncsPerBidder) - ? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder; - - if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) { - let pixels = []; - if (serverResponses && - isArray(serverResponses) && - serverResponses.length > 0 && - isPlainObject(serverResponses[0].body) && - isPlainObject(serverResponses[0].body.ext) && - isArray(serverResponses[0].body.ext.cm) && - serverResponses[0].body.ext.cm.length > 0) { - pixels = serverResponses[0].body.ext.cm; - } - - const syncs = []; - const query = []; - query.push('cbuster={cbuster}'); - query.push('gdpr_consent=' + encodeURIComponent(isPlainObject(gdprConsent) && isStr(gdprConsent?.consentString) ? gdprConsent.consentString : '')); - if (isPlainObject(gdprConsent) && typeof gdprConsent?.gdprApplies === 'boolean' && gdprConsent.gdprApplies) { - query.push('gdpr=1'); - } else { - query.push('gdpr=0'); - } - if (isPlainObject(uspConsent) && uspConsent?.consentString) { - query.push(`us_privacy=${encodeURIComponent(uspConsent?.consentString)}`); - } - if (isPlainObject(gppConsent) && gppConsent?.gppString) { - query.push(`gppString=${encodeURIComponent(gppConsent?.gppString)}`); - } - if (config.getConfig('coppa')) { - query.push('coppa=1') - } - const q = query.join('&') - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: IFRAME_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) - }); - } else if (syncOptions.pixelEnabled) { - if (pixels.length === 0) { - for (let i = 0; i < spb; i++) { - syncs.push({ - type: 'image', - url: PIXEL_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required - }); - } - } else { - for (let i = 0; i < spb && i < pixels.length; i++) { - syncs.push({ - type: 'image', - url: pixels[i] + (pixels[i].indexOf('?') > 0 ? '&' : '?') + q.replace('{cbuster}', Math.round(new Date().getTime())) - }); - } - } - } - return syncs; - } -} diff --git a/modules/mgidXBidAdapter.js b/modules/mgidXBidAdapter.js index 11dda9b9105..467963112bf 100644 --- a/modules/mgidXBidAdapter.js +++ b/modules/mgidXBidAdapter.js @@ -4,7 +4,7 @@ import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { USERSYNC_DEFAULT_CONFIG } from '../src/userSync.js'; import { isBidRequestValid, buildRequestsBase, interpretResponse } from '../libraries/teqblazeUtils/bidderUtils.js'; -import { getUserSyncs } from './mgidBidAdapter.js' +import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' const BIDDER_CODE = 'mgidX'; const GVLID = 358; From 6c4f36fb680fd61908e98273c56f148ef176a259 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Wed, 31 Jul 2024 15:32:42 +0300 Subject: [PATCH 13/17] less changes --- modules/mgidBidAdapter.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index d113c622bfd..2e104c02486 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -22,7 +22,6 @@ import {config} from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import {USERSYNC_DEFAULT_CONFIG} from '../src/userSync.js'; -import {USERSYNC_DEFAULT_CONFIG} from '../src/userSync.js'; import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' /** From b4c902682491e5997474475dc3be3418721b4955 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Wed, 31 Jul 2024 15:54:30 +0300 Subject: [PATCH 14/17] fixed errors --- libraries/mgidUtils/mgidUtils.js | 112 ++++++++++++----------- modules/mgidBidAdapter.js | 4 +- modules/mgidXBidAdapter.js | 2 +- test/spec/modules/mgidBidAdapter_spec.js | 8 +- 4 files changed, 63 insertions(+), 63 deletions(-) diff --git a/libraries/mgidUtils/mgidUtils.js b/libraries/mgidUtils/mgidUtils.js index a007b76307f..9ac84e231b7 100644 --- a/libraries/mgidUtils/mgidUtils.js +++ b/libraries/mgidUtils/mgidUtils.js @@ -1,71 +1,73 @@ import { - _each, - isPlainObject, - isArray, - isStr, - isNumber, -} from '../src/utils.js'; -import { config } from '../src/config.js'; -import { USERSYNC_DEFAULT_CONFIG } from '../src/userSync.js'; + isPlainObject, + isArray, + isStr, + isNumber, +} from '../../src/utils.js'; +import { config } from '../../src/config.js'; +import { USERSYNC_DEFAULT_CONFIG } from '../../src/userSync.js'; + +const PIXEL_SYNC_URL = 'https://cm.mgid.com/i.gif'; +const IFRAME_SYNC_URL = 'https://cm.mgid.com/i.html'; export function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) { - const spb = isPlainObject(config.getConfig('userSync')) && + const spb = isPlainObject(config.getConfig('userSync')) && isNumber(config.getConfig('userSync').syncsPerBidder) - ? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder; + ? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder; - if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) { - let pixels = []; - if (serverResponses && + if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) { + let pixels = []; + if (serverResponses && isArray(serverResponses) && serverResponses.length > 0 && isPlainObject(serverResponses[0].body) && isPlainObject(serverResponses[0].body.ext) && isArray(serverResponses[0].body.ext.cm) && serverResponses[0].body.ext.cm.length > 0) { - pixels = serverResponses[0].body.ext.cm; - } + pixels = serverResponses[0].body.ext.cm; + } - const syncs = []; - const query = []; - query.push('cbuster={cbuster}'); - query.push('gdpr_consent=' + encodeURIComponent(isPlainObject(gdprConsent) && isStr(gdprConsent?.consentString) ? gdprConsent.consentString : '')); - if (isPlainObject(gdprConsent) && typeof gdprConsent?.gdprApplies === 'boolean' && gdprConsent.gdprApplies) { - query.push('gdpr=1'); - } else { - query.push('gdpr=0'); - } - if (isPlainObject(uspConsent) && uspConsent?.consentString) { - query.push(`us_privacy=${encodeURIComponent(uspConsent?.consentString)}`); - } - if (isPlainObject(gppConsent) && gppConsent?.gppString) { - query.push(`gppString=${encodeURIComponent(gppConsent?.gppString)}`); - } - if (config.getConfig('coppa')) { - query.push('coppa=1') + const syncs = []; + const query = []; + query.push('cbuster={cbuster}'); + query.push('gdpr_consent=' + encodeURIComponent(isPlainObject(gdprConsent) && isStr(gdprConsent?.consentString) ? gdprConsent.consentString : '')); + if (isPlainObject(gdprConsent) && typeof gdprConsent?.gdprApplies === 'boolean' && gdprConsent.gdprApplies) { + query.push('gdpr=1'); + } else { + query.push('gdpr=0'); + } + if (isPlainObject(uspConsent) && uspConsent?.consentString) { + query.push(`us_privacy=${encodeURIComponent(uspConsent?.consentString)}`); + } + if (isPlainObject(gppConsent) && gppConsent?.gppString) { + query.push(`gppString=${encodeURIComponent(gppConsent?.gppString)}`); + } + if (config.getConfig('coppa')) { + query.push('coppa=1') + } + const q = query.join('&') + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: IFRAME_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) + }); + } else if (syncOptions.pixelEnabled) { + if (pixels.length === 0) { + for (let i = 0; i < spb; i++) { + syncs.push({ + type: 'image', + url: PIXEL_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required + }); } - const q = query.join('&') - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: IFRAME_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) - }); - } else if (syncOptions.pixelEnabled) { - if (pixels.length === 0) { - for (let i = 0; i < spb; i++) { - syncs.push({ - type: 'image', - url: PIXEL_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required - }); - } - } else { - for (let i = 0; i < spb && i < pixels.length; i++) { - syncs.push({ - type: 'image', - url: pixels[i] + (pixels[i].indexOf('?') > 0 ? '&' : '?') + q.replace('{cbuster}', Math.round(new Date().getTime())) - }); - } - } + } else { + for (let i = 0; i < spb && i < pixels.length; i++) { + syncs.push({ + type: 'image', + url: pixels[i] + (pixels[i].indexOf('?') > 0 ? '&' : '?') + q.replace('{cbuster}', Math.round(new Date().getTime())) + }); } - return syncs; + } } + return syncs; + } } diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index 2e104c02486..b5181105830 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -22,7 +22,7 @@ import {config} from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; import {USERSYNC_DEFAULT_CONFIG} from '../src/userSync.js'; -import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' +import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -59,8 +59,6 @@ const DEFAULT_IMAGE_HEIGHT = 328; const DEFAULT_ICON_WIDTH = 50; const DEFAULT_ICON_HEIGHT = 50; const DEFAULT_TITLE_LENGTH = 80; -const PIXEL_SYNC_URL = 'https://cm.mgid.com/i.gif'; -const IFRAME_SYNC_URL = 'https://cm.mgid.com/i.html'; let isInvalidNativeRequest = false; diff --git a/modules/mgidXBidAdapter.js b/modules/mgidXBidAdapter.js index 467963112bf..61d3a41fa9f 100644 --- a/modules/mgidXBidAdapter.js +++ b/modules/mgidXBidAdapter.js @@ -4,7 +4,7 @@ import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { USERSYNC_DEFAULT_CONFIG } from '../src/userSync.js'; import { isBidRequestValid, buildRequestsBase, interpretResponse } from '../libraries/teqblazeUtils/bidderUtils.js'; -import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' +import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' const BIDDER_CODE = 'mgidX'; const GVLID = 358; diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index e8481cd17fe..c0edfca9843 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -1035,19 +1035,19 @@ describe('Mgid bid adapter', function () { describe('copyFromAdmAsset', function() { it('should return all params', function() { - const asset = {img: {w: 80, h: 80, url: "image_src"}} + const asset = {img: {w: 80, h: 80, url: 'image_src'}} const returned = spec.copyFromAdmAsset(asset) - expect(returned).to.deep.equal({url: "image_src", height: 80, width: 80}); + expect(returned).to.deep.equal({url: 'image_src', height: 80, width: 80}); }); it('should return only height and width', function() { - const asset = {img: {w: 80, h: 80}} + const asset = {img: {w: 80, h: 80}} const returned = spec.copyFromAdmAsset(asset) expect(returned).to.deep.equal({height: 80, width: 80}); }); it('should return nothing', function() { - const asset = {} + const asset = {} const returned = spec.copyFromAdmAsset(asset) expect(returned).to.deep.equal({}); }); From ef4020ab6a2e300963f8bc34fee5796bab9a6e09 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Wed, 31 Jul 2024 15:57:27 +0300 Subject: [PATCH 15/17] less changes --- modules/mgidBidAdapter.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index b5181105830..3c5d353fecb 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -33,7 +33,7 @@ import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.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]: '; @@ -347,9 +347,7 @@ export const spec = { }, onBidWon: (bid) => { const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || ''; - triggerNurlWithCpm(bid, cpm) - if (bid.isBurl) { if (bid.mediaType === BANNER) { bid.ad = bid.ad.replace( From d7625404e84b692f10a0d5fda6d4d2d05bf9c1a1 Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Wed, 31 Jul 2024 16:42:41 +0300 Subject: [PATCH 16/17] fixed errors --- modules/mgidBidAdapter.js | 1 - modules/mgidXBidAdapter.js | 5 ----- modules/redtramBidAdapter.js | 1 - 3 files changed, 7 deletions(-) diff --git a/modules/mgidBidAdapter.js b/modules/mgidBidAdapter.js index 3c5d353fecb..70a9290aa4d 100644 --- a/modules/mgidBidAdapter.js +++ b/modules/mgidBidAdapter.js @@ -21,7 +21,6 @@ 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 {USERSYNC_DEFAULT_CONFIG} from '../src/userSync.js'; import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' /** diff --git a/modules/mgidXBidAdapter.js b/modules/mgidXBidAdapter.js index 61d3a41fa9f..48648389bcf 100644 --- a/modules/mgidXBidAdapter.js +++ b/modules/mgidXBidAdapter.js @@ -1,16 +1,11 @@ -import { isPlainObject, isNumber, isArray, isStr } 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 { USERSYNC_DEFAULT_CONFIG } from '../src/userSync.js'; import { isBidRequestValid, buildRequestsBase, interpretResponse } from '../libraries/teqblazeUtils/bidderUtils.js'; import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js' const BIDDER_CODE = 'mgidX'; const GVLID = 358; const AD_URL = 'https://#{REGION}#.mgid.com/pbjs'; -const PIXEL_SYNC_URL = 'https://cm.mgid.com/i.gif'; -const IFRAME_SYNC_URL = 'https://cm.mgid.com/i.html'; const buildRequests = (validBidRequests = [], bidderRequest = {}) => { const request = buildRequestsBase({ adUrl: AD_URL, validBidRequests, bidderRequest }); diff --git a/modules/redtramBidAdapter.js b/modules/redtramBidAdapter.js index d544e08cf2a..726b2d53f1c 100644 --- a/modules/redtramBidAdapter.js +++ b/modules/redtramBidAdapter.js @@ -1,6 +1,5 @@ import { isFn, - isStr, deepAccess, getWindowTop, triggerNurlWithCpm From e39369c6be5f5c752018f43d41ffeab76a46d79b Mon Sep 17 00:00:00 2001 From: Oleksandr Yermakov Date: Wed, 31 Jul 2024 17:10:31 +0300 Subject: [PATCH 17/17] fixed tests --- test/spec/modules/mgidBidAdapter_spec.js | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/test/spec/modules/mgidBidAdapter_spec.js b/test/spec/modules/mgidBidAdapter_spec.js index c0edfca9843..180b0dc723e 100644 --- a/test/spec/modules/mgidBidAdapter_spec.js +++ b/test/spec/modules/mgidBidAdapter_spec.js @@ -1032,23 +1032,3 @@ describe('Mgid bid adapter', function () { }); }); }); - -describe('copyFromAdmAsset', function() { - it('should return all params', function() { - const asset = {img: {w: 80, h: 80, url: 'image_src'}} - const returned = spec.copyFromAdmAsset(asset) - expect(returned).to.deep.equal({url: 'image_src', height: 80, width: 80}); - }); - - it('should return only height and width', function() { - const asset = {img: {w: 80, h: 80}} - const returned = spec.copyFromAdmAsset(asset) - expect(returned).to.deep.equal({height: 80, width: 80}); - }); - - it('should return nothing', function() { - const asset = {} - const returned = spec.copyFromAdmAsset(asset) - expect(returned).to.deep.equal({}); - }); -});