From 7f39411ee7294b09bf31bd31122f35b1788861bd Mon Sep 17 00:00:00 2001 From: Michael Chen Date: Tue, 10 Dec 2024 16:14:04 +0200 Subject: [PATCH 1/6] RPRD-1638: Add support for Native media type and multi-format bid requests in `index.js`, Populate the changes on `rise/minutemedia/openweb/shinez/stn/BidAdapter.js`, Update all relevant `***BidAdapter_spec.js`, Update all relevant `***BidAdapter.md`, Keep backwards compatibility, Move `mimes` and `api` determination to VIDEO media type as its only relevant to video. --- libraries/riseUtils/index.js | 99 +++++++++---- modules/minutemediaBidAdapter.js | 6 +- modules/minutemediaBidAdapter.md | 2 +- modules/openwebBidAdapter.js | 6 +- modules/openwebBidAdapter.md | 2 +- modules/riseBidAdapter.js | 8 +- modules/riseBidAdapter.md | 2 +- modules/shinezBidAdapter.js | 6 +- modules/shinezBidAdapter.md | 4 +- modules/stnBidAdapter.js | 6 +- modules/stnBidAdapter.md | 2 +- .../modules/minutemediaBidAdapter_spec.js | 130 +++++++++++++++- test/spec/modules/openwebBidAdapter_spec.js | 130 +++++++++++++++- test/spec/modules/riseBidAdapter_spec.js | 130 +++++++++++++++- test/spec/modules/shinezBidAdapter_spec.js | 140 ++++++++++++++++-- test/spec/modules/stnBidAdapter_spec.js | 129 +++++++++++++++- 16 files changed, 716 insertions(+), 86 deletions(-) diff --git a/libraries/riseUtils/index.js b/libraries/riseUtils/index.js index 2bc337b9c55..b5d7aa4fd1d 100644 --- a/libraries/riseUtils/index.js +++ b/libraries/riseUtils/index.js @@ -8,27 +8,58 @@ import { getBidIdParameter, isPlainObject } from '../../src/utils.js'; -import { BANNER, VIDEO } from '../../src/mediaTypes.js'; +import { BANNER, VIDEO, NATIVE } from '../../src/mediaTypes.js'; import {config} from '../../src/config.js'; -export function getFloor(bid, mediaType) { +export function getBidRequestMediaTypes(bidRequest) { + const mediaTypes = deepAccess(bidRequest, 'mediaTypes'); + if (isPlainObject(mediaTypes)) { + return Object.keys(mediaTypes); + } + return []; +} + +export function getPos(bidRequest) { + const mediaTypes = getBidRequestMediaTypes(bidRequest) + const firstMediaType = mediaTypes[0] + if (mediaTypes.length === 1) { + return deepAccess(bidRequest, `mediaTypes.${firstMediaType}.pos`) + } +} + +export function getName(bidRequest) { + const mediaTypes = getBidRequestMediaTypes(bidRequest) + const firstMediaType = mediaTypes[0] + if (mediaTypes.length === 1) { + return deepAccess(bidRequest, `mediaTypes.${firstMediaType}.name`) + } +} + +export function getFloor(bid) { if (!isFn(bid.getFloor)) { return 0; } + + const mediaTypes = getBidRequestMediaTypes(bid) + const firstMediaType = mediaTypes[0] + let floorResult = bid.getFloor({ currency: 'USD', - mediaType: mediaType, + mediaType: mediaTypes.length === 1 ? firstMediaType : '*', size: '*' }); return isPlainObject(floorResult) && floorResult.currency === 'USD' && floorResult.floor ? floorResult.floor : 0; } -export function getSizesArray(bid, mediaType) { +export function getSizesArray(bid) { let sizesArray = []; - if (deepAccess(bid, `mediaTypes.${mediaType}.sizes`)) { - sizesArray = bid.mediaTypes[mediaType].sizes; - } else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) { + const mediaTypes = getBidRequestMediaTypes(bid) + const firstMediaType = mediaTypes[0] + + if (mediaTypes.length === 1 && deepAccess(bid, `mediaTypes.${firstMediaType}.sizes`)) { + sizesArray = bid.mediaTypes[firstMediaType].sizes; + } else if (isArray(bid.sizes) && bid.sizes.length > 0) { sizesArray = bid.sizes; } @@ -111,18 +142,17 @@ export function generateBidsParams(validBidRequests, bidderRequest) { export function generateBidParameters(bid, bidderRequest) { const { params } = bid; - const mediaType = isBanner(bid) ? BANNER : VIDEO; - const sizesArray = getSizesArray(bid, mediaType); + const mediaTypes = getBidRequestMediaTypes(bid); if (isNaN(params.floorPrice)) { params.floorPrice = 0; } const bidObject = { - mediaType, + mediaType: mediaTypes.join(','), adUnitCode: getBidIdParameter('adUnitCode', bid), - sizes: sizesArray, - floorPrice: Math.max(getFloor(bid, mediaType), params.floorPrice), + sizes: getSizesArray(bid), + floorPrice: Math.max(getFloor(bid), params.floorPrice), bidId: getBidIdParameter('bidId', bid), loop: bid.bidderRequestsCount || 0, bidderRequestId: getBidIdParameter('bidderRequestId', bid), @@ -130,9 +160,9 @@ export function generateBidParameters(bid, bidderRequest) { coppa: 0, }; - const pos = deepAccess(bid, `mediaTypes.${mediaType}.pos`); + const pos = getPos(bid) if (pos) { - bidObject.pos = pos; + bidObject.pos = pos } const gpid = deepAccess(bid, `ortb2Imp.ext.gpid`); @@ -140,21 +170,11 @@ export function generateBidParameters(bid, bidderRequest) { bidObject.gpid = gpid; } - const placementId = params.placementId || deepAccess(bid, `mediaTypes.${mediaType}.name`); + const placementId = params.placementId || getName(bid); if (placementId) { bidObject.placementId = placementId; } - const mimes = deepAccess(bid, `mediaTypes.${mediaType}.mimes`); - if (mimes) { - bidObject.mimes = mimes; - } - - const api = deepAccess(bid, `mediaTypes.${mediaType}.api`); - if (api) { - bidObject.api = api; - } - const sua = deepAccess(bid, `ortb2.device.sua`); if (sua) { bidObject.sua = sua; @@ -165,11 +185,11 @@ export function generateBidParameters(bid, bidderRequest) { bidObject.coppa = 1; } - if (mediaType === VIDEO) { + if (mediaTypes.includes(VIDEO)) { const playbackMethod = deepAccess(bid, `mediaTypes.video.playbackmethod`); let playbackMethodValue; - if (Array.isArray(playbackMethod) && isInteger(playbackMethod[0])) { + if (isArray(playbackMethod) && isInteger(playbackMethod[0])) { playbackMethodValue = playbackMethod[0]; } else if (isInteger(playbackMethod)) { playbackMethodValue = playbackMethod; @@ -213,12 +233,29 @@ export function generateBidParameters(bid, bidderRequest) { if (plcmt) { bidObject.plcmt = plcmt; } + + const mimes = deepAccess(bid, `mediaTypes.video.mimes`); + if (mimes) { + bidObject.mimes = mimes; + } + + const api = deepAccess(bid, `mediaTypes.video.api`); + if (api) { + bidObject.api = api; + } + } + + if (mediaTypes.includes(NATIVE)) { + const nativeOrtbRequest = deepAccess(bid, `nativeOrtbRequest`); + if (nativeOrtbRequest) { + bidObject.nativeOrtbRequest = nativeOrtbRequest + } } return bidObject; } -export function buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL, VIDEO, BANNER) { +export function buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL) { const bidResponse = { requestId: adUnit.requestId, cpm: adUnit.cpm, @@ -239,6 +276,8 @@ export function buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL, VIDEO, BANNER) { bidResponse.vastXml = adUnit.vastXml; } else if (adUnit.mediaType === BANNER) { bidResponse.ad = adUnit.ad; + } else if (adUnit.mediaType === NATIVE) { + bidResponse.native = adUnit.native; } if (adUnit.adomain && adUnit.adomain.length) { @@ -248,10 +287,6 @@ export function buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL, VIDEO, BANNER) { return bidResponse; } -function isBanner(bid) { - return bid.mediaTypes && bid.mediaTypes.banner; -} - export function generateGeneralParams(generalObject, bidderRequest, adapterVersion) { const domain = window.location.hostname; const { syncEnabled, filterSettings } = config.getConfig('userSync') || {}; diff --git a/modules/minutemediaBidAdapter.js b/modules/minutemediaBidAdapter.js index 4e83c5c6db4..686b7b6b425 100644 --- a/modules/minutemediaBidAdapter.js +++ b/modules/minutemediaBidAdapter.js @@ -6,7 +6,7 @@ import { triggerPixel, } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { getEndpoint, generateBidsParams, @@ -14,7 +14,7 @@ import { buildBidResponse, } from '../libraries/riseUtils/index.js'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; +const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; const BIDDER_CODE = 'minutemedia'; const ADAPTER_VERSION = '6.0.0'; const TTL = 360; @@ -63,7 +63,7 @@ export const spec = { if (body.bids) { body.bids.forEach(adUnit => { - const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL, VIDEO, BANNER); + const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL); bidResponses.push(bidResponse); }); } diff --git a/modules/minutemediaBidAdapter.md b/modules/minutemediaBidAdapter.md index 66b54adaf0e..b22cf856364 100644 --- a/modules/minutemediaBidAdapter.md +++ b/modules/minutemediaBidAdapter.md @@ -13,7 +13,7 @@ Module that connects to MinuteMedia's demand sources. The MinuteMedia adapter requires setup and approval from the MinuteMedia. Please reach out to hb@minutemedia.com to create an MinuteMedia account. -The adapter supports Video(instream) & Banner. +The adapter supports Video(instream), Banner, Native and multi-format bid requests. # Bid Parameters ## Video diff --git a/modules/openwebBidAdapter.js b/modules/openwebBidAdapter.js index 60364f41d3c..9b2a4edf6e5 100644 --- a/modules/openwebBidAdapter.js +++ b/modules/openwebBidAdapter.js @@ -6,7 +6,7 @@ import { triggerPixel } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { getEndpoint, generateBidsParams, @@ -14,7 +14,7 @@ import { buildBidResponse, } from '../libraries/riseUtils/index.js'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; +const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; const BIDDER_CODE = 'openweb'; const ADAPTER_VERSION = '6.0.0'; const TTL = 360; @@ -69,7 +69,7 @@ export const spec = { if (body && body.bids && body.bids.length) { body.bids.forEach(adUnit => { - const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL, VIDEO, BANNER); + const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL); bidResponses.push(bidResponse); }); } diff --git a/modules/openwebBidAdapter.md b/modules/openwebBidAdapter.md index 5450182265c..c5bc10c3c12 100644 --- a/modules/openwebBidAdapter.md +++ b/modules/openwebBidAdapter.md @@ -13,7 +13,7 @@ Module that connects to OpenWeb's demand sources. The OpenWeb adapter requires setup and approval from OpenWeb. Please reach out to monetization@openweb.com to create an OpenWeb account. -The adapter supports Video and Display demand. +The adapter supports Video(instream), Banner, Native and multi-format bid requests. # Bid Parameters ## Video diff --git a/modules/riseBidAdapter.js b/modules/riseBidAdapter.js index 236c048982a..971e78de371 100644 --- a/modules/riseBidAdapter.js +++ b/modules/riseBidAdapter.js @@ -6,7 +6,7 @@ import { triggerPixel, } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { getEndpoint, generateBidsParams, @@ -14,9 +14,9 @@ import { buildBidResponse, } from '../libraries/riseUtils/index.js'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; +const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; const BIDDER_CODE = 'rise'; -const ADAPTER_VERSION = '6.0.0'; +const ADAPTER_VERSION = '7.0.0'; const TTL = 360; const DEFAULT_CURRENCY = 'USD'; const DEFAULT_GVLID = 1043; @@ -70,7 +70,7 @@ export const spec = { if (body.bids) { body.bids.forEach(adUnit => { - const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL, VIDEO, BANNER); + const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL); bidResponses.push(bidResponse); }); } diff --git a/modules/riseBidAdapter.md b/modules/riseBidAdapter.md index 94d36a08510..2d355cd0cb6 100644 --- a/modules/riseBidAdapter.md +++ b/modules/riseBidAdapter.md @@ -13,7 +13,7 @@ Module that connects to Rise's demand sources. The Rise adapter requires setup and approval from the Rise. Please reach out to prebid-rise-engage@risecodes.com to create an Rise account. -The adapter supports Video(instream). +The adapter supports Video(instream), Banner, Native and multi-format bid requests. # Bid Parameters ## Video diff --git a/modules/shinezBidAdapter.js b/modules/shinezBidAdapter.js index 89f39284bed..322d00a294f 100644 --- a/modules/shinezBidAdapter.js +++ b/modules/shinezBidAdapter.js @@ -6,7 +6,7 @@ import { triggerPixel, } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { getEndpoint, generateBidsParams, @@ -14,7 +14,7 @@ import { buildBidResponse, } from '../libraries/riseUtils/index.js'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; +const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; const BIDDER_CODE = 'shinez'; const ADAPTER_VERSION = '1.0.0'; const TTL = 360; @@ -63,7 +63,7 @@ export const spec = { if (body.bids) { body.bids.forEach(adUnit => { - const bidResponse = buildBidResponse(adUnit, CURRENCY, TTL, VIDEO, BANNER); + const bidResponse = buildBidResponse(adUnit, CURRENCY, TTL); bidResponses.push(bidResponse); }); } diff --git a/modules/shinezBidAdapter.md b/modules/shinezBidAdapter.md index f0ef7a6c218..203b6ece4ff 100644 --- a/modules/shinezBidAdapter.md +++ b/modules/shinezBidAdapter.md @@ -13,7 +13,7 @@ Module that connects to Shinez's demand sources. The Shinez adapter requires setup and approval from the Shinez. Please reach out to tech-team@shinez.io to create an Shinez account. -The adapter supports Video(instream) & Banner. +The adapter supports Video(instream), Banner, Native and multi-format bid requests. # Bid Parameters ## Video @@ -73,4 +73,4 @@ var adUnits = [{ }] } ]; -``` \ No newline at end of file +``` diff --git a/modules/stnBidAdapter.js b/modules/stnBidAdapter.js index ba922c0fd57..09adbd01ef5 100644 --- a/modules/stnBidAdapter.js +++ b/modules/stnBidAdapter.js @@ -6,7 +6,7 @@ import { triggerPixel, } from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { getEndpoint, generateBidsParams, @@ -14,7 +14,7 @@ import { buildBidResponse, } from '../libraries/riseUtils/index.js'; -export const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; +export const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; export const BIDDER_CODE = 'stn'; export const ADAPTER_VERSION = '6.1.0'; export const TTL = 360; @@ -66,7 +66,7 @@ export const spec = { if (body.bids) { body.bids.forEach(adUnit => { - const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL, VIDEO, BANNER); + const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL); bidResponses.push(bidResponse); }); } diff --git a/modules/stnBidAdapter.md b/modules/stnBidAdapter.md index 90b0b58e34b..d5f5f4f3e1d 100644 --- a/modules/stnBidAdapter.md +++ b/modules/stnBidAdapter.md @@ -13,7 +13,7 @@ Module that connects to STN's demand sources. The STN adapter requires setup and approval from the STN. Please reach out to hb@stnvideo.com to create an STN account. -The adapter supports Video(instream) & Banner. +The adapter supports Video(instream), Banner, Native and multi-format bid requests. # Bid Parameters ## Video diff --git a/test/spec/modules/minutemediaBidAdapter_spec.js b/test/spec/modules/minutemediaBidAdapter_spec.js index f2bdd3b6c9d..6c7cb37bf2d 100644 --- a/test/spec/modules/minutemediaBidAdapter_spec.js +++ b/test/spec/modules/minutemediaBidAdapter_spec.js @@ -2,8 +2,9 @@ import { expect } from 'chai'; import { spec } from 'modules/minutemediaBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import { config } from 'src/config.js'; -import { BANNER, VIDEO } from '../../../src/mediaTypes.js'; +import {BANNER, NATIVE, VIDEO} from '../../../src/mediaTypes.js'; import * as utils from 'src/utils.js'; +import {decorateAdUnitsWithNativeParams} from '../../../src/native'; const ENDPOINT = 'https://hb.minutemedia-prebid.com/hb-mm-multi'; const TEST_ENDPOINT = 'https://hb.minutemedia-prebid.com/hb-multi-mm-test'; @@ -63,7 +64,6 @@ describe('minutemediaAdapter', function () { 'plcmt': 1 } }, - 'vastXml': '"..."' }, { 'bidder': spec.code, @@ -80,7 +80,59 @@ describe('minutemediaAdapter', function () { 'banner': { } }, - 'ad': '""' + }, + { + 'bidder': spec.code, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'params': { + 'org': 'jdye8weeyirk00000001' + }, + 'bidId': '299ffc8cca0b87', + 'loop': 1, + 'bidderRequestId': '1144f487e563f9', + 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d', + 'mediaTypes': { + 'banner': { + 'sizes': [ + [ 300, 250 ] + ] + }, + 'video': { + 'playerSize': [[640, 480]], + 'context': 'instream', + 'plcmt': 1 + }, + 'native': { + 'ortb': { + 'assets': [ + { + 'id': 1, + 'required': 1, + 'img': { + 'type': 3, + 'w': 300, + 'h': 200, + } + }, + { + 'id': 2, + 'required': 1, + 'title': { + 'len': 80 + } + }, + { + 'id': 3, + 'required': 1, + 'data': { + 'type': 1 + } + } + ] + } + }, + }, } ]; @@ -151,10 +203,10 @@ describe('minutemediaAdapter', function () { }); it('should send the correct mimes array', function () { - bidRequests[1].mediaTypes.banner.mimes = mimes; + bidRequests[0].mediaTypes.video.mimes = mimes; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[1].mimes).to.be.an('array'); - expect(request.data.bids[1].mimes).to.eql(['application/javascript', 'video/mp4', 'video/quicktime']); + expect(request.data.bids[0].mimes).to.be.an('array'); + expect(request.data.bids[0].mimes).to.eql(['application/javascript', 'video/mp4', 'video/quicktime']); }); it('should send the correct protocols array', function () { @@ -170,12 +222,21 @@ describe('minutemediaAdapter', function () { expect(request.data.bids[0].sizes).to.equal(bidRequests[0].sizes) expect(request.data.bids[1].sizes).to.be.an('array'); expect(request.data.bids[1].sizes).to.equal(bidRequests[1].sizes) + expect(request.data.bids[2].sizes).to.be.an('array'); + expect(request.data.bids[2].sizes).to.eql(bidRequests[2].sizes) + }); + + it('should send nativeOrtbRequest in native bid request', function () { + decorateAdUnitsWithNativeParams(bidRequests) + const request = spec.buildRequests(bidRequests, bidderRequest); + assert.deepEqual(request.data.bids[2].nativeOrtbRequest, bidRequests[2].mediaTypes.native.ortb) }); it('should send the correct media type', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.bids[0].mediaType).to.equal(VIDEO) expect(request.data.bids[1].mediaType).to.equal(BANNER) + expect(request.data.bids[2].mediaType.split(',')).to.include.members([VIDEO, NATIVE, BANNER]) }); it('should respect syncEnabled option', function() { @@ -455,6 +516,28 @@ describe('minutemediaAdapter', function () { nurl: 'http://example.com/win/1234', adomain: ['abc.com'], mediaType: BANNER + }, + { + cpm: 12.5, + width: 300, + height: 200, + requestId: '21e12606d47ba7', + adomain: ['abc.com'], + creativeId: 'creative-id', + nurl: 'http://example.com/win/1234', + mediaType: NATIVE, + native: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg' + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + } }] }; @@ -494,10 +577,40 @@ describe('minutemediaAdapter', function () { ad: '""' }; + const expectedNativeResponse = { + requestId: '21e12606d47ba7', + cpm: 12.5, + currency: 'USD', + width: 300, + height: 200, + ttl: TTL, + creativeId: 'creative-id', + netRevenue: true, + nurl: 'http://example.com/win/1234', + mediaType: NATIVE, + meta: { + mediaType: NATIVE, + advertiserDomains: ['abc.com'] + }, + native: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg', + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + }, + }; + it('should get correct bid response', function () { const result = spec.interpretResponse({ body: response }); expect(result[0]).to.deep.equal(expectedVideoResponse); expect(result[1]).to.deep.equal(expectedBannerResponse); + expect(result[2]).to.deep.equal(expectedNativeResponse); }); it('video type should have vastXml key', function () { @@ -509,6 +622,11 @@ describe('minutemediaAdapter', function () { const result = spec.interpretResponse({ body: response }); expect(result[1].ad).to.equal(expectedBannerResponse.ad) }); + + it('native type should have native key', function () { + const result = spec.interpretResponse({ body: response }); + expect(result[2].native).to.eql(expectedNativeResponse.native) + }); }) describe('getUserSyncs', function() { diff --git a/test/spec/modules/openwebBidAdapter_spec.js b/test/spec/modules/openwebBidAdapter_spec.js index f6f6ad22476..8d296371e0a 100644 --- a/test/spec/modules/openwebBidAdapter_spec.js +++ b/test/spec/modules/openwebBidAdapter_spec.js @@ -2,8 +2,9 @@ import { expect } from 'chai'; import { spec } from 'modules/openwebBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import { config } from 'src/config.js'; -import { BANNER, VIDEO } from '../../../src/mediaTypes.js'; +import {BANNER, NATIVE, VIDEO} from '../../../src/mediaTypes.js'; import * as utils from 'src/utils.js'; +import {decorateAdUnitsWithNativeParams} from '../../../src/native'; const ENDPOINT = 'https://hb.openwebmp.com/hb-multi'; const TEST_ENDPOINT = 'https://hb.openwebmp.com/hb-multi-test'; @@ -74,7 +75,6 @@ describe('openwebAdapter', function () { 'plcmt': 1 } }, - 'vastXml': '"..."' }, { 'bidder': spec.code, @@ -91,7 +91,59 @@ describe('openwebAdapter', function () { 'banner': { } }, - 'ad': '""' + }, + { + 'bidder': spec.code, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'params': { + 'org': 'jdye8weeyirk00000001' + }, + 'bidId': '299ffc8cca0b87', + 'loop': 1, + 'bidderRequestId': '1144f487e563f9', + 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d', + 'mediaTypes': { + 'banner': { + 'sizes': [ + [ 300, 250 ] + ] + }, + 'video': { + 'playerSize': [[640, 480]], + 'context': 'instream', + 'plcmt': 1 + }, + 'native': { + 'ortb': { + 'assets': [ + { + 'id': 1, + 'required': 1, + 'img': { + 'type': 3, + 'w': 300, + 'h': 200, + } + }, + { + 'id': 2, + 'required': 1, + 'title': { + 'len': 80 + } + }, + { + 'id': 3, + 'required': 1, + 'data': { + 'type': 1 + } + } + ] + } + }, + }, } ]; @@ -160,10 +212,10 @@ describe('openwebAdapter', function () { }); it('should send the correct mimes array', function () { - bidRequests[1].mediaTypes.banner.mimes = mimes; + bidRequests[0].mediaTypes.video.mimes = mimes; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[1].mimes).to.be.an('array'); - expect(request.data.bids[1].mimes).to.eql(['application/javascript', 'video/mp4', 'video/quicktime']); + expect(request.data.bids[0].mimes).to.be.an('array'); + expect(request.data.bids[0].mimes).to.eql(['application/javascript', 'video/mp4', 'video/quicktime']); }); it('should send the correct protocols array', function () { @@ -179,12 +231,21 @@ describe('openwebAdapter', function () { expect(request.data.bids[0].sizes).to.equal(bidRequests[0].sizes) expect(request.data.bids[1].sizes).to.be.an('array'); expect(request.data.bids[1].sizes).to.equal(bidRequests[1].sizes) + expect(request.data.bids[2].sizes).to.be.an('array'); + expect(request.data.bids[2].sizes).to.eql(bidRequests[2].sizes) + }); + + it('should send nativeOrtbRequest in native bid request', function () { + decorateAdUnitsWithNativeParams(bidRequests) + const request = spec.buildRequests(bidRequests, bidderRequest); + assert.deepEqual(request.data.bids[2].nativeOrtbRequest, bidRequests[2].mediaTypes.native.ortb) }); it('should send the correct media type', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.bids[0].mediaType).to.equal(VIDEO) expect(request.data.bids[1].mediaType).to.equal(BANNER) + expect(request.data.bids[2].mediaType.split(',')).to.include.members([VIDEO, NATIVE, BANNER]) }); it('should respect syncEnabled option', function() { @@ -464,6 +525,28 @@ describe('openwebAdapter', function () { nurl: 'http://example.com/win/1234', adomain: ['abc.com'], mediaType: BANNER + }, + { + cpm: 12.5, + width: 300, + height: 200, + requestId: '21e12606d47ba7', + adomain: ['abc.com'], + creativeId: 'creative-id-3', + nurl: 'http://example.com/win/1234', + mediaType: NATIVE, + native: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg' + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + } }] }; @@ -503,10 +586,40 @@ describe('openwebAdapter', function () { ad: '""' }; + const expectedNativeResponse = { + requestId: '21e12606d47ba7', + cpm: 12.5, + currency: 'USD', + width: 300, + height: 200, + ttl: TTL, + creativeId: 'creative-id-3', + netRevenue: true, + nurl: 'http://example.com/win/1234', + mediaType: NATIVE, + meta: { + mediaType: NATIVE, + advertiserDomains: ['abc.com'] + }, + native: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg', + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + }, + }; + it('should get correct bid response', function () { const result = spec.interpretResponse({ body: response }); expect(result[0]).to.deep.equal(expectedVideoResponse); expect(result[1]).to.deep.equal(expectedBannerResponse); + expect(result[2]).to.deep.equal(expectedNativeResponse); }); it('video type should have vastXml key', function () { @@ -518,6 +631,11 @@ describe('openwebAdapter', function () { const result = spec.interpretResponse({ body: response }); expect(result[1].ad).to.equal(expectedBannerResponse.ad) }); + + it('native type should have native key', function () { + const result = spec.interpretResponse({ body: response }); + expect(result[2].native).to.eql(expectedNativeResponse.native) + }); }) describe('getUserSyncs', function() { diff --git a/test/spec/modules/riseBidAdapter_spec.js b/test/spec/modules/riseBidAdapter_spec.js index cb879231237..4d380590bf1 100644 --- a/test/spec/modules/riseBidAdapter_spec.js +++ b/test/spec/modules/riseBidAdapter_spec.js @@ -2,8 +2,9 @@ import { expect } from 'chai'; import { spec } from 'modules/riseBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import { config } from 'src/config.js'; -import { BANNER, VIDEO } from '../../../src/mediaTypes.js'; +import {BANNER, NATIVE, VIDEO} from '../../../src/mediaTypes.js'; import * as utils from 'src/utils.js'; +import {decorateAdUnitsWithNativeParams} from '../../../src/native'; const ENDPOINT = 'https://hb.yellowblue.io/hb-multi'; const TEST_ENDPOINT = 'https://hb.yellowblue.io/hb-multi-test'; @@ -72,7 +73,6 @@ describe('riseAdapter', function () { 'plcmt': 1 } }, - 'vastXml': '"..."' }, { 'bidder': spec.code, @@ -89,7 +89,59 @@ describe('riseAdapter', function () { 'banner': { } }, - 'ad': '""' + }, + { + 'bidder': spec.code, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'params': { + 'org': 'jdye8weeyirk00000001' + }, + 'bidId': '299ffc8cca0b87', + 'loop': 1, + 'bidderRequestId': '1144f487e563f9', + 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d', + 'mediaTypes': { + 'banner': { + 'sizes': [ + [ 300, 250 ] + ] + }, + 'video': { + 'playerSize': [[640, 480]], + 'context': 'instream', + 'plcmt': 1 + }, + 'native': { + 'ortb': { + 'assets': [ + { + 'id': 1, + 'required': 1, + 'img': { + 'type': 3, + 'w': 300, + 'h': 200, + } + }, + { + 'id': 2, + 'required': 1, + 'title': { + 'len': 80 + } + }, + { + 'id': 3, + 'required': 1, + 'data': { + 'type': 1 + } + } + ] + } + }, + }, } ]; @@ -174,10 +226,10 @@ describe('riseAdapter', function () { }); it('should send the correct mimes array', function () { - bidRequests[1].mediaTypes.banner.mimes = mimes; + bidRequests[0].mediaTypes.video.mimes = mimes; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[1].mimes).to.be.an('array'); - expect(request.data.bids[1].mimes).to.eql(['application/javascript', 'video/mp4', 'video/quicktime']); + expect(request.data.bids[0].mimes).to.be.an('array'); + expect(request.data.bids[0].mimes).to.eql(['application/javascript', 'video/mp4', 'video/quicktime']); }); it('should send the correct protocols array', function () { @@ -193,12 +245,21 @@ describe('riseAdapter', function () { expect(request.data.bids[0].sizes).to.equal(bidRequests[0].sizes) expect(request.data.bids[1].sizes).to.be.an('array'); expect(request.data.bids[1].sizes).to.equal(bidRequests[1].sizes) + expect(request.data.bids[2].sizes).to.be.an('array'); + expect(request.data.bids[2].sizes).to.eql(bidRequests[2].sizes) + }); + + it('should send nativeOrtbRequest in native bid request', function () { + decorateAdUnitsWithNativeParams(bidRequests) + const request = spec.buildRequests(bidRequests, bidderRequest); + assert.deepEqual(request.data.bids[2].nativeOrtbRequest, bidRequests[2].mediaTypes.native.ortb) }); it('should send the correct media type', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.bids[0].mediaType).to.equal(VIDEO) expect(request.data.bids[1].mediaType).to.equal(BANNER) + expect(request.data.bids[2].mediaType.split(',')).to.include.members([VIDEO, NATIVE, BANNER]) }); it('should respect syncEnabled option', function() { @@ -480,6 +541,28 @@ describe('riseAdapter', function () { creativeId: 'creative-id', nurl: 'http://example.com/win/1234', mediaType: BANNER + }, + { + cpm: 12.5, + width: 300, + height: 200, + requestId: '21e12606d47ba7', + adomain: ['abc.com'], + creativeId: 'creative-id', + nurl: 'http://example.com/win/1234', + mediaType: NATIVE, + native: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg' + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + } }] }; @@ -519,10 +602,40 @@ describe('riseAdapter', function () { ad: '""' }; + const expectedNativeResponse = { + requestId: '21e12606d47ba7', + cpm: 12.5, + currency: 'USD', + width: 300, + height: 200, + ttl: TTL, + creativeId: 'creative-id', + netRevenue: true, + nurl: 'http://example.com/win/1234', + mediaType: NATIVE, + meta: { + mediaType: NATIVE, + advertiserDomains: ['abc.com'] + }, + native: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg', + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + }, + }; + it('should get correct bid response', function () { const result = spec.interpretResponse({ body: response }); expect(result[0]).to.deep.equal(expectedVideoResponse); expect(result[1]).to.deep.equal(expectedBannerResponse); + expect(result[2]).to.deep.equal(expectedNativeResponse); }); it('video type should have vastXml key', function () { @@ -534,6 +647,11 @@ describe('riseAdapter', function () { const result = spec.interpretResponse({ body: response }); expect(result[1].ad).to.equal(expectedBannerResponse.ad) }); + + it('native type should have native key', function () { + const result = spec.interpretResponse({ body: response }); + expect(result[2].native).to.eql(expectedNativeResponse.native) + }); }) describe('getUserSyncs', function() { diff --git a/test/spec/modules/shinezBidAdapter_spec.js b/test/spec/modules/shinezBidAdapter_spec.js index 4e6c2d3420e..dfe72b48449 100644 --- a/test/spec/modules/shinezBidAdapter_spec.js +++ b/test/spec/modules/shinezBidAdapter_spec.js @@ -2,8 +2,9 @@ import { expect } from 'chai'; import { spec } from 'modules/shinezBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import { config } from 'src/config.js'; -import { BANNER, VIDEO } from '../../../src/mediaTypes.js'; +import {BANNER, NATIVE, VIDEO} from '../../../src/mediaTypes.js'; import * as utils from 'src/utils.js'; +import {decorateAdUnitsWithNativeParams} from '../../../src/native'; const ENDPOINT = 'https://hb.sweetgum.io/hb-sz-multi'; const TEST_ENDPOINT = 'https://hb.sweetgum.io/hb-multi-sz-test'; @@ -61,7 +62,6 @@ describe('shinezAdapter', function () { 'context': 'instream' } }, - 'vastXml': '"..."' }, { 'bidder': spec.code, @@ -77,7 +77,59 @@ describe('shinezAdapter', function () { 'banner': { } }, - 'ad': '""' + }, + { + 'bidder': spec.code, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'params': { + 'org': 'jdye8weeyirk00000001' + }, + 'bidId': '299ffc8cca0b87', + 'loop': 1, + 'bidderRequestId': '1144f487e563f9', + 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d', + 'mediaTypes': { + 'banner': { + 'sizes': [ + [ 300, 250 ] + ] + }, + 'video': { + 'playerSize': [[640, 480]], + 'context': 'instream', + 'plcmt': 1 + }, + 'native': { + 'ortb': { + 'assets': [ + { + 'id': 1, + 'required': 1, + 'img': { + 'type': 3, + 'w': 300, + 'h': 200, + } + }, + { + 'id': 2, + 'required': 1, + 'title': { + 'len': 80 + } + }, + { + 'id': 3, + 'required': 1, + 'data': { + 'type': 1 + } + } + ] + } + }, + }, } ]; @@ -130,12 +182,21 @@ describe('shinezAdapter', function () { expect(request.data.bids[0].sizes).to.equal(bidRequests[0].sizes) expect(request.data.bids[1].sizes).to.be.an('array'); expect(request.data.bids[1].sizes).to.equal(bidRequests[1].sizes) + expect(request.data.bids[2].sizes).to.be.an('array'); + expect(request.data.bids[2].sizes).to.eql(bidRequests[2].sizes) + }); + + it('should send nativeOrtbRequest in native bid request', function () { + decorateAdUnitsWithNativeParams(bidRequests) + const request = spec.buildRequests(bidRequests, bidderRequest); + assert.deepEqual(request.data.bids[2].nativeOrtbRequest, bidRequests[2].mediaTypes.native.ortb) }); it('should send the correct media type', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.bids[0].mediaType).to.equal(VIDEO) expect(request.data.bids[1].mediaType).to.equal(BANNER) + expect(request.data.bids[2].mediaType.split(',')).to.include.members([VIDEO, NATIVE, BANNER]) }); it('should respect syncEnabled option', function() { @@ -305,6 +366,8 @@ describe('shinezAdapter', function () { height: 480, requestId: '21e12606d47ba7', adomain: ['abc.com'], + creativeId: 'creative-id', + nurl: 'http://example.com/win/1234', mediaType: VIDEO }, { @@ -314,7 +377,31 @@ describe('shinezAdapter', function () { height: 250, requestId: '21e12606d47ba7', adomain: ['abc.com'], + creativeId: 'creative-id', + nurl: 'http://example.com/win/1234', mediaType: BANNER + }, + { + cpm: 12.5, + width: 300, + height: 200, + requestId: '21e12606d47ba7', + adomain: ['abc.com'], + creativeId: 'creative-id', + nurl: 'http://example.com/win/1234', + mediaType: NATIVE, + native: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg' + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + } }] }; @@ -325,7 +412,7 @@ describe('shinezAdapter', function () { width: 640, height: 480, ttl: TTL, - creativeId: '21e12606d47ba7', + creativeId: 'creative-id', netRevenue: true, nurl: 'http://example.com/win/1234', mediaType: VIDEO, @@ -340,10 +427,10 @@ describe('shinezAdapter', function () { requestId: '21e12606d47ba7', cpm: 12.5, currency: 'USD', - width: 640, - height: 480, + width: 300, + height: 250, ttl: TTL, - creativeId: '21e12606d47ba7', + creativeId: 'creative-id', netRevenue: true, nurl: 'http://example.com/win/1234', mediaType: BANNER, @@ -354,10 +441,40 @@ describe('shinezAdapter', function () { ad: '""' }; + const expectedNativeResponse = { + requestId: '21e12606d47ba7', + cpm: 12.5, + currency: 'USD', + width: 300, + height: 200, + ttl: TTL, + creativeId: 'creative-id', + netRevenue: true, + nurl: 'http://example.com/win/1234', + mediaType: NATIVE, + meta: { + mediaType: NATIVE, + advertiserDomains: ['abc.com'] + }, + native: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg', + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + }, + }; + it('should get correct bid response', function () { const result = spec.interpretResponse({ body: response }); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedVideoResponse)); - expect(Object.keys(result[1])).to.deep.equal(Object.keys(expectedBannerResponse)); + expect(result[0]).to.deep.equal(expectedVideoResponse); + expect(result[1]).to.deep.equal(expectedBannerResponse); + expect(result[2]).to.deep.equal(expectedNativeResponse); }); it('video type should have vastXml key', function () { @@ -369,6 +486,11 @@ describe('shinezAdapter', function () { const result = spec.interpretResponse({ body: response }); expect(result[1].ad).to.equal(expectedBannerResponse.ad) }); + + it('native type should have native key', function () { + const result = spec.interpretResponse({ body: response }); + expect(result[2].native).to.eql(expectedNativeResponse.native) + }); }) describe('getUserSyncs', function() { diff --git a/test/spec/modules/stnBidAdapter_spec.js b/test/spec/modules/stnBidAdapter_spec.js index de851158ed0..639af63c7fe 100644 --- a/test/spec/modules/stnBidAdapter_spec.js +++ b/test/spec/modules/stnBidAdapter_spec.js @@ -2,8 +2,9 @@ import { expect } from 'chai'; import { spec } from 'modules/stnBidAdapter.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; import { config } from 'src/config.js'; -import { BANNER, VIDEO } from '../../../src/mediaTypes.js'; +import {BANNER, NATIVE, VIDEO} from '../../../src/mediaTypes.js'; import * as utils from 'src/utils.js'; +import {decorateAdUnitsWithNativeParams} from '../../../src/native'; const ENDPOINT = 'https://hb.stngo.com/hb-multi'; const TEST_ENDPOINT = 'https://hb.stngo.com/hb-multi-test'; @@ -63,7 +64,6 @@ describe('stnAdapter', function () { 'plcmt': 1 } }, - 'vastXml': '"..."' }, { 'bidder': spec.code, @@ -80,6 +80,59 @@ describe('stnAdapter', function () { 'banner': { } }, + }, + { + 'bidder': spec.code, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'params': { + 'org': 'jdye8weeyirk00000001' + }, + 'bidId': '299ffc8cca0b87', + 'loop': 1, + 'bidderRequestId': '1144f487e563f9', + 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d', + 'mediaTypes': { + 'banner': { + 'sizes': [ + [ 300, 250 ] + ] + }, + 'video': { + 'playerSize': [[640, 480]], + 'context': 'instream', + 'plcmt': 1 + }, + 'native': { + 'ortb': { + 'assets': [ + { + 'id': 1, + 'required': 1, + 'img': { + 'type': 3, + 'w': 300, + 'h': 200, + } + }, + { + 'id': 2, + 'required': 1, + 'title': { + 'len': 80 + } + }, + { + 'id': 3, + 'required': 1, + 'data': { + 'type': 1 + } + } + ] + } + }, + }, 'ad': '""' } ]; @@ -151,10 +204,10 @@ describe('stnAdapter', function () { }); it('should send the correct mimes array', function () { - bidRequests[1].mediaTypes.banner.mimes = mimes; + bidRequests[0].mediaTypes.video.mimes = mimes; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.data.bids[1].mimes).to.be.an('array'); - expect(request.data.bids[1].mimes).to.eql(['application/javascript', 'video/mp4', 'video/quicktime']); + expect(request.data.bids[0].mimes).to.be.an('array'); + expect(request.data.bids[0].mimes).to.eql(['application/javascript', 'video/mp4', 'video/quicktime']); }); it('should send the correct protocols array', function () { @@ -170,12 +223,21 @@ describe('stnAdapter', function () { expect(request.data.bids[0].sizes).to.equal(bidRequests[0].sizes) expect(request.data.bids[1].sizes).to.be.an('array'); expect(request.data.bids[1].sizes).to.equal(bidRequests[1].sizes) + expect(request.data.bids[2].sizes).to.be.an('array'); + expect(request.data.bids[2].sizes).to.eql(bidRequests[2].sizes) + }); + + it('should send nativeOrtbRequest in native bid request', function () { + decorateAdUnitsWithNativeParams(bidRequests) + const request = spec.buildRequests(bidRequests, bidderRequest); + assert.deepEqual(request.data.bids[2].nativeOrtbRequest, bidRequests[2].mediaTypes.native.ortb) }); it('should send the correct media type', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.bids[0].mediaType).to.equal(VIDEO) expect(request.data.bids[1].mediaType).to.equal(BANNER) + expect(request.data.bids[2].mediaType.split(',')).to.include.members([VIDEO, NATIVE, BANNER]) }); it('should respect syncEnabled option', function() { @@ -455,6 +517,28 @@ describe('stnAdapter', function () { adomain: ['abc.com'], mediaType: BANNER, nurl: 'http://example.com/win/1234', + }, + { + cpm: 12.5, + width: 300, + height: 200, + requestId: '21e12606d47ba7', + adomain: ['abc.com'], + creativeId: 'creative-id-3', + nurl: 'http://example.com/win/1234', + mediaType: NATIVE, + native: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg' + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + } }] }; @@ -494,10 +578,40 @@ describe('stnAdapter', function () { ad: '""' }; + const expectedNativeResponse = { + requestId: '21e12606d47ba7', + cpm: 12.5, + currency: 'USD', + width: 300, + height: 200, + ttl: TTL, + creativeId: 'creative-id-3', + netRevenue: true, + nurl: 'http://example.com/win/1234', + mediaType: NATIVE, + meta: { + mediaType: NATIVE, + advertiserDomains: ['abc.com'] + }, + native: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg', + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + }, + }; + it('should get correct bid response', function () { const result = spec.interpretResponse({ body: response }); expect(result[0]).to.deep.equal(expectedVideoResponse); expect(result[1]).to.deep.equal(expectedBannerResponse); + expect(result[2]).to.deep.equal(expectedNativeResponse); }); it('video type should have vastXml key', function () { @@ -509,6 +623,11 @@ describe('stnAdapter', function () { const result = spec.interpretResponse({ body: response }); expect(result[1].ad).to.equal(expectedBannerResponse.ad) }); + + it('native type should have native key', function () { + const result = spec.interpretResponse({ body: response }); + expect(result[2].native).to.eql(expectedNativeResponse.native) + }); }) describe('getUserSyncs', function() { From fe23eff43b9bd3d5372b553c971550ab219205f4 Mon Sep 17 00:00:00 2001 From: Michael Chen Date: Wed, 11 Dec 2024 16:35:24 +0200 Subject: [PATCH 2/6] RPRD-1638: Move all `spec` code duplication to `index.js` and populate across all maintained adapters via `makeBaseSpec` factory function, Move all rise related constants to `constants.js`. --- .../creative-renderer-display/renderer.js | 2 +- libraries/riseUtils/constants.js | 19 ++++ libraries/riseUtils/index.js | 86 +++++++++++++-- modules/minutemediaBidAdapter.js | 83 +------------- modules/openwebBidAdapter.js | 84 +------------- modules/riseBidAdapter.js | 103 ++---------------- modules/shinezBidAdapter.js | 84 +------------- modules/stnBidAdapter.js | 93 ++-------------- 8 files changed, 128 insertions(+), 426 deletions(-) create mode 100644 libraries/riseUtils/constants.js diff --git a/libraries/creative-renderer-display/renderer.js b/libraries/creative-renderer-display/renderer.js index 146afab46ae..dd3f98c9b92 100644 --- a/libraries/creative-renderer-display/renderer.js +++ b/libraries/creative-renderer-display/renderer.js @@ -1,2 +1,2 @@ // this file is autogenerated, see creative/README.md -export const RENDERER = "(()=>{\"use strict\";window.render=function({ad:d,adUrl:e,width:i,height:r},{mkFrame:n},o){if(!d&&!e)throw{reason:\"noAd\",message:\"Missing ad markup or URL\"};{const s=o.document,t={width:i,height:r};e&&!d?t.src=e:t.srcdoc=d,s.body.appendChild(n(s,t))}}})();" \ No newline at end of file +export const RENDERER = "" \ No newline at end of file diff --git a/libraries/riseUtils/constants.js b/libraries/riseUtils/constants.js new file mode 100644 index 00000000000..b280715a353 --- /dev/null +++ b/libraries/riseUtils/constants.js @@ -0,0 +1,19 @@ +import {BANNER, NATIVE, VIDEO} from '../../src/mediaTypes.js'; + +export const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; +export const ADAPTER_VERSION = '7.0.0'; +export const DEFAULT_TTL = 360; +export const DEFAULT_CURRENCY = 'USD'; +export const BASE_URL = 'https://hb.yellowblue.io/'; +export const BIDDER_CODE = 'rise'; +export const DEFAULT_GVLID = 1043; + +export const ALIASES = [ + { code: 'risexchange', gvlid: DEFAULT_GVLID }, + { code: 'openwebxchange', gvlid: 280 } +] + +export const MODES = { + PRODUCTION: 'hb-multi', + TEST: 'hb-multi-test' +}; diff --git a/libraries/riseUtils/index.js b/libraries/riseUtils/index.js index b5d7aa4fd1d..3bfe5420dbc 100644 --- a/libraries/riseUtils/index.js +++ b/libraries/riseUtils/index.js @@ -1,15 +1,85 @@ import { - isArray, - isFn, + contains, deepAccess, + getBidIdParameter, + isArray, isEmpty, - contains, + isFn, isInteger, - getBidIdParameter, - isPlainObject + isPlainObject, + logInfo, + triggerPixel } from '../../src/utils.js'; -import { BANNER, VIDEO, NATIVE } from '../../src/mediaTypes.js'; +import {BANNER, NATIVE, VIDEO} from '../../src/mediaTypes.js'; import {config} from '../../src/config.js'; +import {ADAPTER_VERSION, DEFAULT_CURRENCY, DEFAULT_TTL, SUPPORTED_AD_TYPES} from './constants.js'; + +export const makeBaseSpec = (baseUrl, modes) => { + return { + version: ADAPTER_VERSION, + supportedMediaTypes: SUPPORTED_AD_TYPES, + buildRequests: function (validBidRequests, bidderRequest) { + const combinedRequestsObject = {}; + + // use data from the first bid, to create the general params for all bids + const generalObject = validBidRequests[0]; + const testMode = generalObject.params.testMode; + const rtbDomain = generalObject.params.rtbDomain || baseUrl; + + combinedRequestsObject.params = generateGeneralParams(generalObject, bidderRequest); + combinedRequestsObject.bids = generateBidsParams(validBidRequests, bidderRequest); + + return { + method: 'POST', + url: getEndpoint(testMode, rtbDomain, modes), + data: combinedRequestsObject + } + }, + interpretResponse: function ({ body }) { + const bidResponses = []; + + if (body.bids) { + body.bids.forEach(adUnit => { + const bidResponse = buildBidResponse(adUnit); + bidResponses.push(bidResponse); + }); + } + + return bidResponses; + }, + getUserSyncs: function (syncOptions, serverResponses) { + const syncs = []; + for (const response of serverResponses) { + if (syncOptions.iframeEnabled && deepAccess(response, 'body.params.userSyncURL')) { + syncs.push({ + type: 'iframe', + url: deepAccess(response, 'body.params.userSyncURL') + }); + } + if (syncOptions.pixelEnabled && isArray(deepAccess(response, 'body.params.userSyncPixels'))) { + const pixels = response.body.params.userSyncPixels.map(pixel => { + return { + type: 'image', + url: pixel + } + }); + syncs.push(...pixels); + } + } + return syncs; + }, + onBidWon: function (bid) { + if (bid == null) { + return; + } + + logInfo('onBidWon:', bid); + if (bid.hasOwnProperty('nurl') && bid.nurl.length > 0) { + triggerPixel(bid.nurl); + } + } + } +} export function getBidRequestMediaTypes(bidRequest) { const mediaTypes = deepAccess(bidRequest, 'mediaTypes'); @@ -255,14 +325,14 @@ export function generateBidParameters(bid, bidderRequest) { return bidObject; } -export function buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL) { +export function buildBidResponse(adUnit) { const bidResponse = { requestId: adUnit.requestId, cpm: adUnit.cpm, currency: adUnit.currency || DEFAULT_CURRENCY, width: adUnit.width, height: adUnit.height, - ttl: adUnit.ttl || TTL, + ttl: adUnit.ttl || DEFAULT_TTL, creativeId: adUnit.creativeId, netRevenue: adUnit.netRevenue || true, nurl: adUnit.nurl, diff --git a/modules/minutemediaBidAdapter.js b/modules/minutemediaBidAdapter.js index 686b7b6b425..d7ab97d10d9 100644 --- a/modules/minutemediaBidAdapter.js +++ b/modules/minutemediaBidAdapter.js @@ -1,24 +1,8 @@ -import { - logWarn, - logInfo, - isArray, - deepAccess, - triggerPixel, -} from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { - getEndpoint, - generateBidsParams, - generateGeneralParams, - buildBidResponse, -} from '../libraries/riseUtils/index.js'; +import {logWarn} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {makeBaseSpec} from '../libraries/riseUtils/index.js'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; const BIDDER_CODE = 'minutemedia'; -const ADAPTER_VERSION = '6.0.0'; -const TTL = 360; -const DEFAULT_CURRENCY = 'USD'; const BASE_URL = 'https://hb.minutemedia-prebid.com/'; const MODES = { PRODUCTION: 'hb-mm-multi', @@ -26,10 +10,9 @@ const MODES = { }; export const spec = { + ...makeBaseSpec(BASE_URL, MODES), code: BIDDER_CODE, gvlid: 918, - version: ADAPTER_VERSION, - supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { if (!bidRequest.params) { logWarn('no params have been set to MinuteMedia adapter'); @@ -42,64 +25,6 @@ export const spec = { } return true; - }, - buildRequests: function (validBidRequests, bidderRequest) { - const combinedRequestsObject = {}; - - const generalObject = validBidRequests[0]; - const testMode = generalObject.params.testMode; - - combinedRequestsObject.params = generateGeneralParams(generalObject, bidderRequest, ADAPTER_VERSION); - combinedRequestsObject.bids = generateBidsParams(validBidRequests, bidderRequest); - - return { - method: 'POST', - url: getEndpoint(testMode, BASE_URL, MODES), - data: combinedRequestsObject - }; - }, - interpretResponse: function ({ body }) { - const bidResponses = []; - - if (body.bids) { - body.bids.forEach(adUnit => { - const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL); - bidResponses.push(bidResponse); - }); - } - - return bidResponses; - }, - getUserSyncs: function (syncOptions, serverResponses) { - const syncs = []; - for (const response of serverResponses) { - if (syncOptions.iframeEnabled && deepAccess(response, 'body.params.userSyncURL')) { - syncs.push({ - type: 'iframe', - url: deepAccess(response, 'body.params.userSyncURL') - }); - } - if (syncOptions.pixelEnabled && isArray(deepAccess(response, 'body.params.userSyncPixels'))) { - const pixels = response.body.params.userSyncPixels.map(pixel => { - return { - type: 'image', - url: pixel - }; - }); - syncs.push(...pixels); - } - } - return syncs; - }, - onBidWon: function (bid) { - if (bid == null) { - return; - } - - logInfo('onBidWon:', bid); - if (bid.hasOwnProperty('nurl') && bid.nurl.length > 0) { - triggerPixel(bid.nurl); - } } }; diff --git a/modules/openwebBidAdapter.js b/modules/openwebBidAdapter.js index 9b2a4edf6e5..d044c98e912 100644 --- a/modules/openwebBidAdapter.js +++ b/modules/openwebBidAdapter.js @@ -1,24 +1,8 @@ -import { - logWarn, - logInfo, - isArray, - deepAccess, - triggerPixel -} from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { - getEndpoint, - generateBidsParams, - generateGeneralParams, - buildBidResponse, -} from '../libraries/riseUtils/index.js'; +import {logWarn} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {makeBaseSpec} from '../libraries/riseUtils/index.js'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; const BIDDER_CODE = 'openweb'; -const ADAPTER_VERSION = '6.0.0'; -const TTL = 360; -const DEFAULT_CURRENCY = 'USD'; const BASE_URL = 'https://hb.openwebmp.com/'; const MODES = { PRODUCTION: 'hb-multi', @@ -26,10 +10,9 @@ const MODES = { }; export const spec = { + ...makeBaseSpec(BASE_URL, MODES), code: BIDDER_CODE, gvlid: 280, - version: ADAPTER_VERSION, - supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { if (!bidRequest.params) { logWarn('no params have been set to OpenWeb adapter'); @@ -47,65 +30,6 @@ export const spec = { } return true; - }, - buildRequests: function (validBidRequests, bidderRequest) { - const combinedRequestsObject = {}; - - // use data from the first bid, to create the general params for all bids - const generalObject = validBidRequests[0]; - const testMode = generalObject.params.testMode; - - combinedRequestsObject.params = generateGeneralParams(generalObject, bidderRequest); - combinedRequestsObject.bids = generateBidsParams(validBidRequests, bidderRequest); - - return { - method: 'POST', - url: getEndpoint(testMode, BASE_URL, MODES), - data: combinedRequestsObject - } - }, - interpretResponse: function ({body}) { - const bidResponses = []; - - if (body && body.bids && body.bids.length) { - body.bids.forEach(adUnit => { - const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL); - bidResponses.push(bidResponse); - }); - } - - return bidResponses; - }, - getUserSyncs: function (syncOptions, serverResponses) { - const syncs = []; - for (const response of serverResponses) { - if (syncOptions.iframeEnabled && deepAccess(response, 'body.params.userSyncURL')) { - syncs.push({ - type: 'iframe', - url: deepAccess(response, 'body.params.userSyncURL') - }); - } - if (syncOptions.pixelEnabled && isArray(deepAccess(response, 'body.params.userSyncPixels'))) { - const pixels = response.body.params.userSyncPixels.map(pixel => { - return { - type: 'image', - url: pixel - } - }); - syncs.push(...pixels); - } - } - return syncs; - }, - onBidWon: function (bid) { - if (bid == null) { - return; - } - - logInfo('onBidWon:', bid); - if (bid.hasOwnProperty('nurl') && bid.nurl.length > 0) { - triggerPixel(bid.nurl); - } } }; diff --git a/modules/riseBidAdapter.js b/modules/riseBidAdapter.js index 971e78de371..a6970e959ce 100644 --- a/modules/riseBidAdapter.js +++ b/modules/riseBidAdapter.js @@ -1,40 +1,19 @@ +import {logWarn} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {makeBaseSpec} from '../libraries/riseUtils/index.js'; import { - logWarn, - logInfo, - isArray, - deepAccess, - triggerPixel, -} from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { - getEndpoint, - generateBidsParams, - generateGeneralParams, - buildBidResponse, -} from '../libraries/riseUtils/index.js'; - -const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; -const BIDDER_CODE = 'rise'; -const ADAPTER_VERSION = '7.0.0'; -const TTL = 360; -const DEFAULT_CURRENCY = 'USD'; -const DEFAULT_GVLID = 1043; -const BASE_URL = 'https://hb.yellowblue.io/'; -const MODES = { - PRODUCTION: 'hb-multi', - TEST: 'hb-multi-test' -}; + ALIASES, + BASE_URL, + BIDDER_CODE, + DEFAULT_GVLID, + MODES, +} from '../libraries/riseUtils/constants.js'; export const spec = { + ...makeBaseSpec(BASE_URL, MODES), code: BIDDER_CODE, - aliases: [ - { code: 'risexchange', gvlid: DEFAULT_GVLID }, - { code: 'openwebxchange', gvlid: 280 } - ], + aliases: ALIASES, gvlid: DEFAULT_GVLID, - version: ADAPTER_VERSION, - supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { if (!bidRequest.params) { logWarn('no params have been set to Rise adapter'); @@ -47,66 +26,6 @@ export const spec = { } return true; - }, - buildRequests: function (validBidRequests, bidderRequest) { - const combinedRequestsObject = {}; - - // use data from the first bid, to create the general params for all bids - const generalObject = validBidRequests[0]; - const testMode = generalObject.params.testMode; - const rtbDomain = generalObject.params.rtbDomain || BASE_URL; - - combinedRequestsObject.params = generateGeneralParams(generalObject, bidderRequest); - combinedRequestsObject.bids = generateBidsParams(validBidRequests, bidderRequest); - - return { - method: 'POST', - url: getEndpoint(testMode, rtbDomain, MODES), - data: combinedRequestsObject - } - }, - interpretResponse: function ({ body }) { - const bidResponses = []; - - if (body.bids) { - body.bids.forEach(adUnit => { - const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL); - bidResponses.push(bidResponse); - }); - } - - return bidResponses; - }, - getUserSyncs: function (syncOptions, serverResponses) { - const syncs = []; - for (const response of serverResponses) { - if (syncOptions.iframeEnabled && deepAccess(response, 'body.params.userSyncURL')) { - syncs.push({ - type: 'iframe', - url: deepAccess(response, 'body.params.userSyncURL') - }); - } - if (syncOptions.pixelEnabled && isArray(deepAccess(response, 'body.params.userSyncPixels'))) { - const pixels = response.body.params.userSyncPixels.map(pixel => { - return { - type: 'image', - url: pixel - } - }); - syncs.push(...pixels); - } - } - return syncs; - }, - onBidWon: function (bid) { - if (bid == null) { - return; - } - - logInfo('onBidWon:', bid); - if (bid.hasOwnProperty('nurl') && bid.nurl.length > 0) { - triggerPixel(bid.nurl); - } } }; diff --git a/modules/shinezBidAdapter.js b/modules/shinezBidAdapter.js index 322d00a294f..f88360c4c38 100644 --- a/modules/shinezBidAdapter.js +++ b/modules/shinezBidAdapter.js @@ -1,24 +1,8 @@ -import { - logWarn, - logInfo, - isArray, - deepAccess, - triggerPixel, -} from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { - getEndpoint, - generateBidsParams, - generateGeneralParams, - buildBidResponse, -} from '../libraries/riseUtils/index.js'; +import {logWarn} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {makeBaseSpec} from '../libraries/riseUtils/index.js'; -const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; const BIDDER_CODE = 'shinez'; -const ADAPTER_VERSION = '1.0.0'; -const TTL = 360; -const CURRENCY = 'USD'; const BASE_URL = 'https://hb.sweetgum.io/'; const MODES = { PRODUCTION: 'hb-sz-multi', @@ -26,9 +10,8 @@ const MODES = { }; export const spec = { + ...makeBaseSpec(BASE_URL, MODES), code: BIDDER_CODE, - version: ADAPTER_VERSION, - supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { if (!bidRequest.params) { logWarn('no params have been set to Shinez adapter'); @@ -41,65 +24,6 @@ export const spec = { } return true; - }, - buildRequests: function (validBidRequests, bidderRequest) { - const combinedRequestsObject = {}; - - // use data from the first bid, to create the general params for all bids - const generalObject = validBidRequests[0]; - const testMode = generalObject.params.testMode; - - combinedRequestsObject.params = generateGeneralParams(generalObject, bidderRequest); - combinedRequestsObject.bids = generateBidsParams(validBidRequests, bidderRequest); - - return { - method: 'POST', - url: getEndpoint(testMode, BASE_URL, MODES), - data: combinedRequestsObject - } - }, - interpretResponse: function ({body}) { - const bidResponses = []; - - if (body.bids) { - body.bids.forEach(adUnit => { - const bidResponse = buildBidResponse(adUnit, CURRENCY, TTL); - bidResponses.push(bidResponse); - }); - } - - return bidResponses; - }, - getUserSyncs: function (syncOptions, serverResponses) { - const syncs = []; - for (const response of serverResponses) { - if (syncOptions.iframeEnabled && deepAccess(response, 'body.params.userSyncURL')) { - syncs.push({ - type: 'iframe', - url: deepAccess(response, 'body.params.userSyncURL') - }); - } - if (syncOptions.pixelEnabled && isArray(deepAccess(response, 'body.params.userSyncPixels'))) { - const pixels = response.body.params.userSyncPixels.map(pixel => { - return { - type: 'image', - url: pixel - } - }); - syncs.push(...pixels); - } - } - return syncs; - }, - onBidWon: function (bid) { - if (bid == null) { - return; - } - - logInfo('onBidWon:', bid); - if (bid.hasOwnProperty('nurl') && bid.nurl.length > 0) { - triggerPixel(bid.nurl); - } } }; diff --git a/modules/stnBidAdapter.js b/modules/stnBidAdapter.js index 09adbd01ef5..62d82b8d4b2 100644 --- a/modules/stnBidAdapter.js +++ b/modules/stnBidAdapter.js @@ -1,38 +1,17 @@ -import { - logWarn, - logInfo, - isArray, - deepAccess, - triggerPixel, -} from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { - getEndpoint, - generateBidsParams, - generateGeneralParams, - buildBidResponse, -} from '../libraries/riseUtils/index.js'; +import {logWarn} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {makeBaseSpec} from '../libraries/riseUtils/index.js'; -export const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; -export const BIDDER_CODE = 'stn'; -export const ADAPTER_VERSION = '6.1.0'; -export const TTL = 360; -export const DEFAULT_CURRENCY = 'USD'; -export const SELLER_ENDPOINT = 'https://hb.stngo.com/'; -export const MODES = { +const BIDDER_CODE = 'stn'; +const BASE_URL = 'https://hb.stngo.com/'; +const MODES = { PRODUCTION: 'hb-multi', TEST: 'hb-multi-test' }; -export const SUPPORTED_SYNC_METHODS = { - IFRAME: 'iframe', - PIXEL: 'pixel' -}; export const spec = { + ...makeBaseSpec(BASE_URL, MODES), code: BIDDER_CODE, - version: ADAPTER_VERSION, - supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { if (!bidRequest.params) { logWarn('no params have been set to STN adapter'); @@ -45,64 +24,6 @@ export const spec = { } return true; - }, - buildRequests: function (validBidRequests, bidderRequest) { - const combinedRequestsObject = {}; - - const generalObject = validBidRequests[0]; - const testMode = generalObject.params.testMode; - - combinedRequestsObject.params = generateGeneralParams(generalObject, bidderRequest); - combinedRequestsObject.bids = generateBidsParams(validBidRequests, bidderRequest); - - return { - method: 'POST', - url: getEndpoint(testMode, SELLER_ENDPOINT, MODES), - data: combinedRequestsObject - } - }, - interpretResponse: function ({ body }) { - const bidResponses = []; - - if (body.bids) { - body.bids.forEach(adUnit => { - const bidResponse = buildBidResponse(adUnit, DEFAULT_CURRENCY, TTL); - bidResponses.push(bidResponse); - }); - } - - return bidResponses; - }, - getUserSyncs: function (syncOptions, serverResponses) { - const syncs = []; - for (const response of serverResponses) { - if (syncOptions.iframeEnabled && deepAccess(response, 'body.params.userSyncURL')) { - syncs.push({ - type: 'iframe', - url: deepAccess(response, 'body.params.userSyncURL') - }); - } - if (syncOptions.pixelEnabled && isArray(deepAccess(response, 'body.params.userSyncPixels'))) { - const pixels = response.body.params.userSyncPixels.map(pixel => { - return { - type: 'image', - url: pixel - } - }) - syncs.push(...pixels) - } - } - return syncs; - }, - onBidWon: function (bid) { - if (bid == null) { - return; - } - - logInfo('onBidWon:', bid); - if (bid.hasOwnProperty('nurl') && bid.nurl.length > 0) { - triggerPixel(bid.nurl); - } } }; From 5b548742971fc593ebfc822717f6b18a2e15f7c9 Mon Sep 17 00:00:00 2001 From: Michael Chen Date: Mon, 16 Dec 2024 13:40:52 +0200 Subject: [PATCH 3/6] RPRD-1638: Align with seller response. --- libraries/creative-renderer-display/renderer.js | 2 +- libraries/riseUtils/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/creative-renderer-display/renderer.js b/libraries/creative-renderer-display/renderer.js index dd3f98c9b92..146afab46ae 100644 --- a/libraries/creative-renderer-display/renderer.js +++ b/libraries/creative-renderer-display/renderer.js @@ -1,2 +1,2 @@ // this file is autogenerated, see creative/README.md -export const RENDERER = "" \ No newline at end of file +export const RENDERER = "(()=>{\"use strict\";window.render=function({ad:d,adUrl:e,width:i,height:r},{mkFrame:n},o){if(!d&&!e)throw{reason:\"noAd\",message:\"Missing ad markup or URL\"};{const s=o.document,t={width:i,height:r};e&&!d?t.src=e:t.srcdoc=d,s.body.appendChild(n(s,t))}}})();" \ No newline at end of file diff --git a/libraries/riseUtils/index.js b/libraries/riseUtils/index.js index 3bfe5420dbc..31db5830c3c 100644 --- a/libraries/riseUtils/index.js +++ b/libraries/riseUtils/index.js @@ -347,7 +347,7 @@ export function buildBidResponse(adUnit) { } else if (adUnit.mediaType === BANNER) { bidResponse.ad = adUnit.ad; } else if (adUnit.mediaType === NATIVE) { - bidResponse.native = adUnit.native; + bidResponse.native = {ortb: adUnit.native}; } if (adUnit.adomain && adUnit.adomain.length) { From a73a8d4598e282cea761019a267c0df9000c7e5a Mon Sep 17 00:00:00 2001 From: Michael Chen Date: Sun, 22 Dec 2024 20:50:12 +0200 Subject: [PATCH 4/6] RPRD-1638: fix cr comments --- libraries/riseUtils/constants.js | 3 ++- libraries/riseUtils/index.js | 26 +++++++++++++------------- modules/minutemediaBidAdapter.js | 3 ++- modules/openwebBidAdapter.js | 3 ++- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/libraries/riseUtils/constants.js b/libraries/riseUtils/constants.js index b280715a353..4acb9920291 100644 --- a/libraries/riseUtils/constants.js +++ b/libraries/riseUtils/constants.js @@ -1,5 +1,6 @@ import {BANNER, NATIVE, VIDEO} from '../../src/mediaTypes.js'; +const OW_GVLID = 280 export const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]; export const ADAPTER_VERSION = '7.0.0'; export const DEFAULT_TTL = 360; @@ -10,7 +11,7 @@ export const DEFAULT_GVLID = 1043; export const ALIASES = [ { code: 'risexchange', gvlid: DEFAULT_GVLID }, - { code: 'openwebxchange', gvlid: 280 } + { code: 'openwebxchange', gvlid: OW_GVLID } ] export const MODES = { diff --git a/libraries/riseUtils/index.js b/libraries/riseUtils/index.js index 31db5830c3c..ed83daf2537 100644 --- a/libraries/riseUtils/index.js +++ b/libraries/riseUtils/index.js @@ -90,18 +90,18 @@ export function getBidRequestMediaTypes(bidRequest) { } export function getPos(bidRequest) { - const mediaTypes = getBidRequestMediaTypes(bidRequest) - const firstMediaType = mediaTypes[0] + const mediaTypes = getBidRequestMediaTypes(bidRequest); + const firstMediaType = mediaTypes[0]; if (mediaTypes.length === 1) { - return deepAccess(bidRequest, `mediaTypes.${firstMediaType}.pos`) + return deepAccess(bidRequest, `mediaTypes.${firstMediaType}.pos`); } } export function getName(bidRequest) { - const mediaTypes = getBidRequestMediaTypes(bidRequest) - const firstMediaType = mediaTypes[0] + const mediaTypes = getBidRequestMediaTypes(bidRequest); + const firstMediaType = mediaTypes[0]; if (mediaTypes.length === 1) { - return deepAccess(bidRequest, `mediaTypes.${firstMediaType}.name`) + return deepAccess(bidRequest, `mediaTypes.${firstMediaType}.name`); } } @@ -111,7 +111,7 @@ export function getFloor(bid) { } const mediaTypes = getBidRequestMediaTypes(bid) - const firstMediaType = mediaTypes[0] + const firstMediaType = mediaTypes[0]; let floorResult = bid.getFloor({ currency: 'USD', @@ -124,8 +124,8 @@ export function getFloor(bid) { export function getSizesArray(bid) { let sizesArray = []; - const mediaTypes = getBidRequestMediaTypes(bid) - const firstMediaType = mediaTypes[0] + const mediaTypes = getBidRequestMediaTypes(bid); + const firstMediaType = mediaTypes[0]; if (mediaTypes.length === 1 && deepAccess(bid, `mediaTypes.${firstMediaType}.sizes`)) { sizesArray = bid.mediaTypes[firstMediaType].sizes; @@ -230,9 +230,9 @@ export function generateBidParameters(bid, bidderRequest) { coppa: 0, }; - const pos = getPos(bid) - if (pos) { - bidObject.pos = pos + const pos = getPos(bid); + if (isInteger(pos)) { + bidObject.pos = pos; } const gpid = deepAccess(bid, `ortb2Imp.ext.gpid`); @@ -318,7 +318,7 @@ export function generateBidParameters(bid, bidderRequest) { if (mediaTypes.includes(NATIVE)) { const nativeOrtbRequest = deepAccess(bid, `nativeOrtbRequest`); if (nativeOrtbRequest) { - bidObject.nativeOrtbRequest = nativeOrtbRequest + bidObject.nativeOrtbRequest = nativeOrtbRequest; } } diff --git a/modules/minutemediaBidAdapter.js b/modules/minutemediaBidAdapter.js index d7ab97d10d9..d5aae8a84d0 100644 --- a/modules/minutemediaBidAdapter.js +++ b/modules/minutemediaBidAdapter.js @@ -4,6 +4,7 @@ import {makeBaseSpec} from '../libraries/riseUtils/index.js'; const BIDDER_CODE = 'minutemedia'; const BASE_URL = 'https://hb.minutemedia-prebid.com/'; +const GVLID = 918; const MODES = { PRODUCTION: 'hb-mm-multi', TEST: 'hb-multi-mm-test' @@ -12,7 +13,7 @@ const MODES = { export const spec = { ...makeBaseSpec(BASE_URL, MODES), code: BIDDER_CODE, - gvlid: 918, + gvlid: GVLID, isBidRequestValid: function (bidRequest) { if (!bidRequest.params) { logWarn('no params have been set to MinuteMedia adapter'); diff --git a/modules/openwebBidAdapter.js b/modules/openwebBidAdapter.js index d044c98e912..0dff314ce17 100644 --- a/modules/openwebBidAdapter.js +++ b/modules/openwebBidAdapter.js @@ -4,6 +4,7 @@ import {makeBaseSpec} from '../libraries/riseUtils/index.js'; const BIDDER_CODE = 'openweb'; const BASE_URL = 'https://hb.openwebmp.com/'; +const GVLID = 280; const MODES = { PRODUCTION: 'hb-multi', TEST: 'hb-multi-test' @@ -12,7 +13,7 @@ const MODES = { export const spec = { ...makeBaseSpec(BASE_URL, MODES), code: BIDDER_CODE, - gvlid: 280, + gvlid: GVLID, isBidRequestValid: function (bidRequest) { if (!bidRequest.params) { logWarn('no params have been set to OpenWeb adapter'); From 9ebf16637e6b7b25a914db25abb56db3532dcee9 Mon Sep 17 00:00:00 2001 From: Michael Chen Date: Tue, 14 Jan 2025 11:37:30 +0200 Subject: [PATCH 5/6] RPRD-1638: Align tests with native response --- .../modules/minutemediaBidAdapter_spec.js | 22 ++++++++++--------- test/spec/modules/openwebBidAdapter_spec.js | 22 ++++++++++--------- test/spec/modules/riseBidAdapter_spec.js | 22 ++++++++++--------- test/spec/modules/shinezBidAdapter_spec.js | 22 ++++++++++--------- test/spec/modules/stnBidAdapter_spec.js | 22 ++++++++++--------- 5 files changed, 60 insertions(+), 50 deletions(-) diff --git a/test/spec/modules/minutemediaBidAdapter_spec.js b/test/spec/modules/minutemediaBidAdapter_spec.js index 6c7cb37bf2d..4e5cd4883d3 100644 --- a/test/spec/modules/minutemediaBidAdapter_spec.js +++ b/test/spec/modules/minutemediaBidAdapter_spec.js @@ -593,16 +593,18 @@ describe('minutemediaAdapter', function () { advertiserDomains: ['abc.com'] }, native: { - body: 'Advertise with Rise', - clickUrl: 'https://risecodes.com', - cta: 'Start now', - image: { - width: 300, - height: 200, - url: 'https://sdk.streamrail.com/media/rise-image.jpg', - }, - sponsoredBy: 'Rise', - title: 'Rise Ad Tech Solutions' + ortb: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg', + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + } }, }; diff --git a/test/spec/modules/openwebBidAdapter_spec.js b/test/spec/modules/openwebBidAdapter_spec.js index 8d296371e0a..9ab8f608598 100644 --- a/test/spec/modules/openwebBidAdapter_spec.js +++ b/test/spec/modules/openwebBidAdapter_spec.js @@ -602,16 +602,18 @@ describe('openwebAdapter', function () { advertiserDomains: ['abc.com'] }, native: { - body: 'Advertise with Rise', - clickUrl: 'https://risecodes.com', - cta: 'Start now', - image: { - width: 300, - height: 200, - url: 'https://sdk.streamrail.com/media/rise-image.jpg', - }, - sponsoredBy: 'Rise', - title: 'Rise Ad Tech Solutions' + ortb: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg', + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + } }, }; diff --git a/test/spec/modules/riseBidAdapter_spec.js b/test/spec/modules/riseBidAdapter_spec.js index 29a06168d11..a3fef50f825 100644 --- a/test/spec/modules/riseBidAdapter_spec.js +++ b/test/spec/modules/riseBidAdapter_spec.js @@ -644,16 +644,18 @@ describe('riseAdapter', function () { advertiserDomains: ['abc.com'] }, native: { - body: 'Advertise with Rise', - clickUrl: 'https://risecodes.com', - cta: 'Start now', - image: { - width: 300, - height: 200, - url: 'https://sdk.streamrail.com/media/rise-image.jpg', - }, - sponsoredBy: 'Rise', - title: 'Rise Ad Tech Solutions' + ortb: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg', + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + } }, }; diff --git a/test/spec/modules/shinezBidAdapter_spec.js b/test/spec/modules/shinezBidAdapter_spec.js index dfe72b48449..d4ad99359bb 100644 --- a/test/spec/modules/shinezBidAdapter_spec.js +++ b/test/spec/modules/shinezBidAdapter_spec.js @@ -457,16 +457,18 @@ describe('shinezAdapter', function () { advertiserDomains: ['abc.com'] }, native: { - body: 'Advertise with Rise', - clickUrl: 'https://risecodes.com', - cta: 'Start now', - image: { - width: 300, - height: 200, - url: 'https://sdk.streamrail.com/media/rise-image.jpg', - }, - sponsoredBy: 'Rise', - title: 'Rise Ad Tech Solutions' + ortb: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg', + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + } }, }; diff --git a/test/spec/modules/stnBidAdapter_spec.js b/test/spec/modules/stnBidAdapter_spec.js index 639af63c7fe..98859385828 100644 --- a/test/spec/modules/stnBidAdapter_spec.js +++ b/test/spec/modules/stnBidAdapter_spec.js @@ -594,16 +594,18 @@ describe('stnAdapter', function () { advertiserDomains: ['abc.com'] }, native: { - body: 'Advertise with Rise', - clickUrl: 'https://risecodes.com', - cta: 'Start now', - image: { - width: 300, - height: 200, - url: 'https://sdk.streamrail.com/media/rise-image.jpg', - }, - sponsoredBy: 'Rise', - title: 'Rise Ad Tech Solutions' + ortb: { + body: 'Advertise with Rise', + clickUrl: 'https://risecodes.com', + cta: 'Start now', + image: { + width: 300, + height: 200, + url: 'https://sdk.streamrail.com/media/rise-image.jpg', + }, + sponsoredBy: 'Rise', + title: 'Rise Ad Tech Solutions' + } }, }; From 53ecffd3f3ab0d059b5bfb8fc01d2fb2af133c9b Mon Sep 17 00:00:00 2001 From: Michael Chen Date: Tue, 14 Jan 2025 16:03:25 +0200 Subject: [PATCH 6/6] circle ci test