diff --git a/modules/minutemediaBidAdapter.js b/modules/minutemediaBidAdapter.js
index 1a9ccfdf824..604a5dd7ea8 100644
--- a/modules/minutemediaBidAdapter.js
+++ b/modules/minutemediaBidAdapter.js
@@ -1,17 +1,17 @@
-import { logWarn, isArray, isFn, deepAccess, isEmpty, contains, timestamp, getBidIdParameter } from '../src/utils.js';
+import { logWarn, logInfo, isArray, isFn, deepAccess, isEmpty, contains, timestamp, getBidIdParameter, triggerPixel, isInteger } from '../src/utils.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
-import {VIDEO} from '../src/mediaTypes.js';
+import {BANNER, VIDEO} from '../src/mediaTypes.js';
import {config} from '../src/config.js';
-const SUPPORTED_AD_TYPES = [VIDEO];
+const SUPPORTED_AD_TYPES = [BANNER, VIDEO];
const BIDDER_CODE = 'minutemedia';
-const ADAPTER_VERSION = '5.0.1';
+const ADAPTER_VERSION = '6.0.0';
const TTL = 360;
const CURRENCY = 'USD';
const SELLER_ENDPOINT = 'https://hb.minutemedia-prebid.com/';
const MODES = {
- PRODUCTION: 'hb-mm',
- TEST: 'hb-mm-test'
+ PRODUCTION: 'hb-mm-multi',
+ TEST: 'hb-multi-mm-test'
}
const SUPPORTED_SYNC_METHODS = {
IFRAME: 'iframe',
@@ -23,7 +23,7 @@ export const spec = {
gvlid: 918,
version: ADAPTER_VERSION,
supportedMediaTypes: SUPPORTED_AD_TYPES,
- isBidRequestValid: function(bidRequest) {
+ isBidRequestValid: function (bidRequest) {
if (!bidRequest.params) {
logWarn('no params have been set to MinuteMedia adapter');
return false;
@@ -36,54 +36,70 @@ export const spec = {
return true;
},
- buildRequests: function (bidRequests, bidderRequest) {
- if (bidRequests.length === 0) {
- return [];
- }
+ buildRequests: function (validBidRequests, bidderRequest) {
+ const combinedRequestsObject = {};
- const requests = [];
+ // use data from the first bid, to create the general params for all bids
+ const generalObject = validBidRequests[0];
+ const testMode = generalObject.params.testMode;
- bidRequests.forEach(bid => {
- requests.push(buildVideoRequest(bid, bidderRequest));
- });
+ combinedRequestsObject.params = generateGeneralParams(generalObject, bidderRequest);
+ combinedRequestsObject.bids = generateBidsParams(validBidRequests, bidderRequest);
- return requests;
+ return {
+ method: 'POST',
+ url: getEndpoint(testMode),
+ data: combinedRequestsObject
+ }
},
- interpretResponse: function({body}) {
+ interpretResponse: function ({body}) {
const bidResponses = [];
- const bidResponse = {
- requestId: body.requestId,
- cpm: body.cpm,
- width: body.width,
- height: body.height,
- creativeId: body.requestId,
- currency: body.currency,
- netRevenue: body.netRevenue,
- ttl: body.ttl || TTL,
- vastXml: body.vastXml,
- mediaType: VIDEO
- };
-
- if (body.adomain && body.adomain.length) {
- bidResponse.meta = {};
- bidResponse.meta.advertiserDomains = body.adomain
+ if (body.bids) {
+ body.bids.forEach(adUnit => {
+ const bidResponse = {
+ requestId: adUnit.requestId,
+ cpm: adUnit.cpm,
+ currency: adUnit.currency || CURRENCY,
+ width: adUnit.width,
+ height: adUnit.height,
+ ttl: adUnit.ttl || TTL,
+ creativeId: adUnit.requestId,
+ netRevenue: adUnit.netRevenue || true,
+ nurl: adUnit.nurl,
+ mediaType: adUnit.mediaType,
+ meta: {
+ mediaType: adUnit.mediaType
+ }
+ };
+
+ if (adUnit.mediaType === VIDEO) {
+ bidResponse.vastXml = adUnit.vastXml;
+ } else if (adUnit.mediaType === BANNER) {
+ bidResponse.ad = adUnit.ad;
+ }
+
+ if (adUnit.adomain && adUnit.adomain.length) {
+ bidResponse.meta.advertiserDomains = adUnit.adomain;
+ }
+
+ bidResponses.push(bidResponse);
+ });
}
- bidResponses.push(bidResponse);
return bidResponses;
},
- getUserSyncs: function(syncOptions, serverResponses) {
+ getUserSyncs: function (syncOptions, serverResponses) {
const syncs = [];
for (const response of serverResponses) {
- if (syncOptions.iframeEnabled && response.body.userSyncURL) {
+ if (syncOptions.iframeEnabled && response.body.params.userSyncURL) {
syncs.push({
type: 'iframe',
- url: response.body.userSyncURL
+ url: response.body.params.userSyncURL
});
}
- if (syncOptions.pixelEnabled && isArray(response.body.userSyncPixels)) {
- const pixels = response.body.userSyncPixels.map(pixel => {
+ if (syncOptions.pixelEnabled && isArray(response.body.params.userSyncPixels)) {
+ const pixels = response.body.params.userSyncPixels.map(pixel => {
return {
type: 'image',
url: pixel
@@ -93,6 +109,16 @@ export const spec = {
}
}
return syncs;
+ },
+ onBidWon: function (bid) {
+ if (bid == null) {
+ return;
+ }
+
+ logInfo('onBidWon:', bid);
+ if (bid.hasOwnProperty('nurl') && bid.nurl.length > 0) {
+ triggerPixel(bid.nurl);
+ }
}
};
@@ -103,46 +129,33 @@ registerBidder(spec);
* @param bid {bid}
* @returns {Number}
*/
-function getFloor(bid) {
+function getFloor(bid, mediaType) {
if (!isFn(bid.getFloor)) {
return 0;
}
let floorResult = bid.getFloor({
currency: CURRENCY,
- mediaType: VIDEO,
+ mediaType: mediaType,
size: '*'
});
return floorResult.currency === CURRENCY && floorResult.floor ? floorResult.floor : 0;
}
/**
- * Build the video request
- * @param bid {bid}
- * @param bidderRequest {bidderRequest}
- * @returns {Object}
- */
-function buildVideoRequest(bid, bidderRequest) {
- const sellerParams = generateParameters(bid, bidderRequest);
- const {params} = bid;
- return {
- method: 'GET',
- url: getEndpoint(params.testMode),
- data: sellerParams
- };
-}
-
-/**
- * Get the the ad size from the bid
+ * Get the the ad sizes array from the bid
* @param bid {bid}
* @returns {Array}
*/
-function getSizes(bid) {
- if (deepAccess(bid, 'mediaTypes.video.sizes')) {
- return bid.mediaTypes.video.sizes[0];
+function getSizesArray(bid, mediaType) {
+ let sizesArray = []
+
+ if (deepAccess(bid, `mediaTypes.${mediaType}.sizes`)) {
+ sizesArray = bid.mediaTypes[mediaType].sizes;
} else if (Array.isArray(bid.sizes) && bid.sizes.length > 0) {
- return bid.sizes[0];
+ sizesArray = bid.sizes;
}
- return [];
+
+ return sizesArray;
}
/**
@@ -239,122 +252,180 @@ function getDeviceType(ua) {
return '1';
}
+function generateBidsParams(validBidRequests, bidderRequest) {
+ const bidsArray = [];
+
+ if (validBidRequests.length) {
+ validBidRequests.forEach(bid => {
+ bidsArray.push(generateBidParameters(bid, bidderRequest));
+ });
+ }
+
+ return bidsArray;
+}
+
/**
- * Generate query parameters for the request
- * @param bid {bid}
- * @param bidderRequest {bidderRequest}
- * @returns {Object}
+ * Generate bid specific parameters
+ * @param {bid} bid
+ * @param {bidderRequest} bidderRequest
+ * @returns {Object} bid specific params object
*/
-function generateParameters(bid, bidderRequest) {
+function generateBidParameters(bid, bidderRequest) {
const {params} = bid;
- const timeout = config.getConfig('bidderTimeout');
- const {syncEnabled, filterSettings} = config.getConfig('userSync') || {};
- const [width, height] = getSizes(bid);
- const {bidderCode} = bidderRequest;
- const domain = window.location.hostname;
+ const mediaType = isBanner(bid) ? BANNER : VIDEO;
+ const sizesArray = getSizesArray(bid, mediaType);
// fix floor price in case of NAN
if (isNaN(params.floorPrice)) {
params.floorPrice = 0;
}
- const requestParams = {
+ const bidObject = {
+ mediaType,
+ adUnitCode: getBidIdParameter('adUnitCode', bid),
+ sizes: sizesArray,
+ floorPrice: Math.max(getFloor(bid, mediaType), params.floorPrice),
+ bidId: getBidIdParameter('bidId', bid),
+ bidderRequestId: getBidIdParameter('bidderRequestId', bid),
+ transactionId: getBidIdParameter('transactionId', bid),
+ };
+
+ const pos = deepAccess(bid, `mediaTypes.${mediaType}.pos`);
+ if (pos) {
+ bidObject.pos = pos;
+ }
+
+ const gpid = deepAccess(bid, `ortb2Imp.ext.gpid`);
+ if (gpid) {
+ bidObject.gpid = gpid;
+ }
+
+ const placementId = params.placementId || deepAccess(bid, `mediaTypes.${mediaType}.name`);
+ if (placementId) {
+ bidObject.placementId = placementId;
+ }
+
+ if (mediaType === VIDEO) {
+ const playbackMethod = deepAccess(bid, `mediaTypes.video.playbackmethod`);
+ let playbackMethodValue;
+
+ // verify playbackMethod is of type integer array, or integer only.
+ if (Array.isArray(playbackMethod) && isInteger(playbackMethod[0])) {
+ // only the first playbackMethod in the array will be used, according to OpenRTB 2.5 recommendation
+ playbackMethodValue = playbackMethod[0];
+ } else if (isInteger(playbackMethod)) {
+ playbackMethodValue = playbackMethod;
+ }
+
+ if (playbackMethodValue) {
+ bidObject.playbackMethod = playbackMethodValue;
+ }
+
+ const placement = deepAccess(bid, `mediaTypes.video.placement`);
+ if (placement) {
+ bidObject.placement = placement;
+ }
+
+ const minDuration = deepAccess(bid, `mediaTypes.video.minduration`);
+ if (minDuration) {
+ bidObject.minDuration = minDuration;
+ }
+
+ const maxDuration = deepAccess(bid, `mediaTypes.video.maxduration`);
+ if (maxDuration) {
+ bidObject.maxDuration = maxDuration;
+ }
+
+ const skip = deepAccess(bid, `mediaTypes.video.skip`);
+ if (skip) {
+ bidObject.skip = skip;
+ }
+
+ const linearity = deepAccess(bid, `mediaTypes.video.linearity`);
+ if (linearity) {
+ bidObject.linearity = linearity;
+ }
+ }
+
+ return bidObject;
+}
+
+function isBanner(bid) {
+ return bid.mediaTypes && bid.mediaTypes.banner;
+}
+
+/**
+ * Generate params that are common between all bids
+ * @param {single bid object} generalObject
+ * @param {bidderRequest} bidderRequest
+ * @returns {object} the common params object
+ */
+function generateGeneralParams(generalObject, bidderRequest) {
+ const domain = window.location.hostname;
+ const {syncEnabled, filterSettings} = config.getConfig('userSync') || {};
+ const {bidderCode} = bidderRequest;
+ const generalBidParams = generalObject.params;
+ const timeout = config.getConfig('bidderTimeout');
+
+ // these params are snake_case instead of camelCase to allow backwards compatability on the server.
+ // in the future, these will be converted to camelCase to match our convention.
+ const generalParams = {
wrapper_type: 'prebidjs',
wrapper_vendor: '$$PREBID_GLOBAL$$',
wrapper_version: '$prebid.version$',
adapter_version: ADAPTER_VERSION,
auction_start: timestamp(),
- ad_unit_code: getBidIdParameter('adUnitCode', bid),
- tmax: timeout,
- width: width,
- height: height,
- publisher_id: params.org,
- floor_price: Math.max(getFloor(bid), params.floorPrice),
- ua: navigator.userAgent,
- bid_id: getBidIdParameter('bidId', bid),
- bidder_request_id: getBidIdParameter('bidderRequestId', bid),
- transaction_id: getBidIdParameter('transactionId', bid),
- session_id: getBidIdParameter('auctionId', bid),
+ publisher_id: generalBidParams.org,
publisher_name: domain,
site_domain: domain,
dnt: (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0,
- device_type: getDeviceType(navigator.userAgent)
- };
+ device_type: getDeviceType(navigator.userAgent),
+ ua: navigator.userAgent,
+ session_id: getBidIdParameter('auctionId', generalObject),
+ tmax: timeout
+ }
- const userIdsParam = getBidIdParameter('userId', bid);
+ const userIdsParam = getBidIdParameter('userId', generalObject);
if (userIdsParam) {
- requestParams.userIds = JSON.stringify(userIdsParam);
+ generalParams.userIds = JSON.stringify(userIdsParam);
}
const ortb2Metadata = config.getConfig('ortb2') || {};
if (ortb2Metadata.site) {
- requestParams.site_metadata = JSON.stringify(ortb2Metadata.site);
+ generalParams.site_metadata = JSON.stringify(ortb2Metadata.site);
}
if (ortb2Metadata.user) {
- requestParams.user_metadata = JSON.stringify(ortb2Metadata.user);
- }
-
- const playbackMethod = deepAccess(bid, 'mediaTypes.video.playbackmethod');
- if (playbackMethod) {
- requestParams.playback_method = playbackMethod;
- }
- const placement = deepAccess(bid, 'mediaTypes.video.placement');
- if (placement) {
- requestParams.placement = placement;
- }
- const pos = deepAccess(bid, 'mediaTypes.video.pos');
- if (pos) {
- requestParams.pos = pos;
- }
- const minduration = deepAccess(bid, 'mediaTypes.video.minduration');
- if (minduration) {
- requestParams.min_duration = minduration;
- }
- const maxduration = deepAccess(bid, 'mediaTypes.video.maxduration');
- if (maxduration) {
- requestParams.max_duration = maxduration;
- }
- const skip = deepAccess(bid, 'mediaTypes.video.skip');
- if (skip) {
- requestParams.skip = skip;
- }
- const linearity = deepAccess(bid, 'mediaTypes.video.linearity');
- if (linearity) {
- requestParams.linearity = linearity;
- }
-
- if (params.placementId) {
- requestParams.placement_id = params.placementId;
+ generalParams.user_metadata = JSON.stringify(ortb2Metadata.user);
}
if (syncEnabled) {
const allowedSyncMethod = getAllowedSyncMethod(filterSettings, bidderCode);
if (allowedSyncMethod) {
- requestParams.cs_method = allowedSyncMethod;
+ generalParams.cs_method = allowedSyncMethod;
}
}
if (bidderRequest.uspConsent) {
- requestParams.us_privacy = bidderRequest.uspConsent;
+ generalParams.us_privacy = bidderRequest.uspConsent;
}
if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) {
- requestParams.gdpr = bidderRequest.gdprConsent.gdprApplies;
- requestParams.gdpr_consent = bidderRequest.gdprConsent.consentString;
+ generalParams.gdpr = bidderRequest.gdprConsent.gdprApplies;
+ generalParams.gdpr_consent = bidderRequest.gdprConsent.consentString;
}
- if (params.ifa) {
- requestParams.ifa = params.ifa;
+ if (generalBidParams.ifa) {
+ generalParams.ifa = generalBidParams.ifa;
}
- if (bid.schain) {
- requestParams.schain = getSupplyChain(bid.schain);
+ if (generalObject.schain) {
+ generalParams.schain = getSupplyChain(generalObject.schain);
}
if (bidderRequest && bidderRequest.refererInfo) {
- requestParams.referrer = deepAccess(bidderRequest, 'refererInfo.referer');
- requestParams.page_url = config.getConfig('pageUrl') || deepAccess(window, 'location.href');
+ generalParams.referrer = deepAccess(bidderRequest, 'refererInfo.referer');
+ generalParams.page_url = config.getConfig('pageUrl') || deepAccess(window, 'location.href');
}
- return requestParams;
+ return generalParams
}
diff --git a/modules/minutemediaBidAdapter.md b/modules/minutemediaBidAdapter.md
index 348cc586e08..70f106a745f 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).
+The adapter supports Video(instream) & Banner.
# Bid Parameters
## Video
@@ -27,25 +27,50 @@ The adapter supports Video(instream).
# Test Parameters
```javascript
-var adUnits = [
- {
+var adUnits = [{
code: 'dfp-video-div',
- sizes: [[640, 480]],
+ sizes: [
+ [640, 480]
+ ],
mediaTypes: {
- video: {
- playerSize: [[640, 480]],
- context: 'instream'
- }
+ video: {
+ playerSize: [
+ [640, 480]
+ ],
+ context: 'instream'
+ }
},
bids: [{
- bidder: 'minutemedia',
- params: {
- org: '56f91cd4d3e3660002000033', // Required
- floorPrice: 2.00, // Optional
- placementId: '12345678', // Optional
- testMode: false // Optional
- }
+ bidder: 'minutemedia',
+ params: {
+ org: '56f91cd4d3e3660002000033', // Required
+ floorPrice: 2.00, // Optional
+ placementId: 'video-test', // Optional
+ testMode: false // Optional
+ }
}]
- }
- ];
+ },
+ {
+ code: 'dfp-banner-div',
+ sizes: [
+ [640, 480]
+ ],
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [640, 480]
+ ]
+ }
+ },
+ bids: [{
+ bidder: 'minutemedia',
+ params: {
+ org: '56f91cd4d3e3660002000033', // Required
+ floorPrice: 2.00, // Optional
+ placementId: 'banner-test', // Optional
+ testMode: false // Optional
+ }
+ }]
+ }
+];
```
diff --git a/test/spec/modules/minutemediaBidAdapter_spec.js b/test/spec/modules/minutemediaBidAdapter_spec.js
index b1ad7f96bc4..cce08e615a3 100644
--- a/test/spec/modules/minutemediaBidAdapter_spec.js
+++ b/test/spec/modules/minutemediaBidAdapter_spec.js
@@ -2,12 +2,13 @@ import { expect } from 'chai';
import { spec } from 'modules/minutemediaBidAdapter.js';
import { newBidder } from 'src/adapters/bidderFactory.js';
import { config } from 'src/config.js';
-import { VIDEO } from '../../../src/mediaTypes.js';
-import { deepClone } from 'src/utils.js';
+import { BANNER, VIDEO } from '../../../src/mediaTypes.js';
+import * as utils from 'src/utils.js';
-const ENDPOINT = 'https://hb.minutemedia-prebid.com/hb-mm';
-const TEST_ENDPOINT = 'https://hb.minutemedia-prebid.com/hb-mm-test';
+const ENDPOINT = 'https://hb.minutemedia-prebid.com/hb-mm-multi';
+const TEST_ENDPOINT = 'https://hb.minutemedia-prebid.com/hb-multi-mm-test';
const TTL = 360;
+/* eslint no-console: ["error", { allow: ["log", "warn", "error"] }] */
describe('minutemediaAdapter', function () {
const adapter = newBidder(spec);
@@ -54,6 +55,29 @@ describe('minutemediaAdapter', function () {
'bidId': '299ffc8cca0b87',
'bidderRequestId': '1144f487e563f9',
'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d',
+ 'mediaTypes': {
+ 'video': {
+ 'playerSize': [[640, 480]],
+ 'context': 'instream'
+ }
+ },
+ 'vastXml': '"..."'
+ },
+ {
+ 'bidder': spec.code,
+ 'adUnitCode': 'adunit-code',
+ 'sizes': [[300, 250]],
+ 'params': {
+ 'org': 'jdye8weeyirk00000001'
+ },
+ 'bidId': '299ffc8cca0b87',
+ 'bidderRequestId': '1144f487e563f9',
+ 'auctionId': 'bfc420c3-8577-4568-9766-a8a935fb620d',
+ 'mediaTypes': {
+ 'banner': {
+ }
+ },
+ 'ad': '""'
}
];
@@ -77,44 +101,41 @@ describe('minutemediaAdapter', function () {
}
const placementId = '12345678';
- it('sends the placementId as a query param', function () {
+ it('sends the placementId to ENDPOINT via POST', function () {
bidRequests[0].params.placementId = placementId;
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.data.placement_id).to.equal(placementId);
- }
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.bids[0].placementId).to.equal(placementId);
});
- it('sends bid request to ENDPOINT via GET', function () {
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.url).to.equal(ENDPOINT);
- expect(request.method).to.equal('GET');
- }
+ it('sends bid request to ENDPOINT via POST', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.url).to.equal(ENDPOINT);
+ expect(request.method).to.equal('POST');
});
- it('sends bid request to test ENDPOINT via GET', function () {
- const requests = spec.buildRequests(testModeBidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.url).to.equal(TEST_ENDPOINT);
- expect(request.method).to.equal('GET');
- }
+ it('sends bid request to TEST ENDPOINT via POST', function () {
+ const request = spec.buildRequests(testModeBidRequests, bidderRequest);
+ expect(request.url).to.equal(TEST_ENDPOINT);
+ expect(request.method).to.equal('POST');
});
it('should send the correct bid Id', function () {
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.data.bid_id).to.equal('299ffc8cca0b87');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.bids[0].bidId).to.equal('299ffc8cca0b87');
});
- it('should send the correct width and height', function () {
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.have.property('width', 640);
- expect(request.data).to.have.property('height', 480);
- }
+ it('should send the correct sizes array', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.bids[0].sizes).to.be.an('array');
+ 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)
+ });
+
+ 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)
});
it('should respect syncEnabled option', function() {
@@ -129,11 +150,9 @@ describe('minutemediaAdapter', function () {
}
}
});
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.not.have.property('cs_method');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.not.have.property('cs_method');
});
it('should respect "iframe" filter settings', function () {
@@ -148,11 +167,9 @@ describe('minutemediaAdapter', function () {
}
}
});
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.have.property('cs_method', 'iframe');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.have.property('cs_method', 'iframe');
});
it('should respect "all" filter settings', function () {
@@ -167,24 +184,21 @@ describe('minutemediaAdapter', function () {
}
}
});
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.have.property('cs_method', 'iframe');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.have.property('cs_method', 'iframe');
});
it('should send the pixel user sync param if userSync is enabled and no "iframe" or "all" configs are present', function () {
+ config.resetConfig();
config.setConfig({
userSync: {
- syncEnabled: true
+ syncEnabled: true,
}
});
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.have.property('cs_method', 'pixel');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.have.property('cs_method', 'pixel');
});
it('should respect total exclusion', function() {
@@ -203,48 +217,38 @@ describe('minutemediaAdapter', function () {
}
}
});
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.not.have.property('cs_method');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.not.have.property('cs_method');
});
it('should have us_privacy param if usPrivacy is available in the bidRequest', function () {
const bidderRequestWithUSP = Object.assign({uspConsent: '1YNN'}, bidderRequest);
- const requests = spec.buildRequests(bidRequests, bidderRequestWithUSP);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.have.property('us_privacy', '1YNN');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequestWithUSP);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.have.property('us_privacy', '1YNN');
});
it('should have an empty us_privacy param if usPrivacy is missing in the bidRequest', function () {
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.not.have.property('us_privacy');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.not.have.property('us_privacy');
});
it('should not send the gdpr param if gdprApplies is false in the bidRequest', function () {
const bidderRequestWithGDPR = Object.assign({gdprConsent: {gdprApplies: false}}, bidderRequest);
- const requests = spec.buildRequests(bidRequests, bidderRequestWithGDPR);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.not.have.property('gdpr');
- expect(request.data).to.not.have.property('gdpr_consent');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.not.have.property('gdpr');
+ expect(request.data.params).to.not.have.property('gdpr_consent');
});
it('should send the gdpr param if gdprApplies is true in the bidRequest', function () {
const bidderRequestWithGDPR = Object.assign({gdprConsent: {gdprApplies: true, consentString: 'test-consent-string'}}, bidderRequest);
- const requests = spec.buildRequests(bidRequests, bidderRequestWithGDPR);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.have.property('gdpr', true);
- expect(request.data).to.have.property('gdpr_consent', 'test-consent-string');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequestWithGDPR);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.have.property('gdpr', true);
+ expect(request.data.params).to.have.property('gdpr_consent', 'test-consent-string');
});
it('should have schain param if it is available in the bidRequest', () => {
@@ -254,15 +258,13 @@ describe('minutemediaAdapter', function () {
nodes: [{ asi: 'indirectseller.com', sid: '00001', hp: 1 }],
};
bidRequests[0].schain = schain;
- const requests = spec.buildRequests(bidRequests, bidderRequest);
- for (const request of requests) {
- expect(request.data).to.be.an('object');
- expect(request.data).to.have.property('schain', '1.0,1!indirectseller.com,00001,1,,,');
- }
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.data.params).to.be.an('object');
+ expect(request.data.params).to.have.property('schain', '1.0,1!indirectseller.com,00001,1,,,');
});
- it('should set floor_price to getFloor.floor value if it is greater than params.floorPrice', function() {
- const bid = deepClone(bidRequests[0]);
+ it('should set flooPrice to getFloor.floor value if it is greater than params.floorPrice', function() {
+ const bid = utils.deepClone(bidRequests[0]);
bid.getFloor = () => {
return {
currency: 'USD',
@@ -270,13 +272,13 @@ describe('minutemediaAdapter', function () {
}
}
bid.params.floorPrice = 0.64;
- const request = spec.buildRequests([bid], bidderRequest)[0];
- expect(request.data).to.be.an('object');
- expect(request.data).to.have.property('floor_price', 3.32);
+ const request = spec.buildRequests([bid], bidderRequest);
+ expect(request.data.bids[0]).to.be.an('object');
+ expect(request.data.bids[0]).to.have.property('floorPrice', 3.32);
});
- it('should set floor_price to params.floorPrice value if it is greater than getFloor.floor', function() {
- const bid = deepClone(bidRequests[0]);
+ it('should set floorPrice to params.floorPrice value if it is greater than getFloor.floor', function() {
+ const bid = utils.deepClone(bidRequests[0]);
bid.getFloor = () => {
return {
currency: 'USD',
@@ -284,61 +286,109 @@ describe('minutemediaAdapter', function () {
}
}
bid.params.floorPrice = 1.5;
- const request = spec.buildRequests([bid], bidderRequest)[0];
- expect(request.data).to.be.an('object');
- expect(request.data).to.have.property('floor_price', 1.5);
+ const request = spec.buildRequests([bid], bidderRequest);
+ expect(request.data.bids[0]).to.be.an('object');
+ expect(request.data.bids[0]).to.have.property('floorPrice', 1.5);
});
});
describe('interpretResponse', function () {
const response = {
+ params: {
+ currency: 'USD',
+ netRevenue: true,
+ },
+ bids: [{
+ cpm: 12.5,
+ vastXml: '',
+ width: 640,
+ height: 480,
+ requestId: '21e12606d47ba7',
+ adomain: ['abc.com'],
+ mediaType: VIDEO
+ },
+ {
+ cpm: 12.5,
+ ad: '""',
+ width: 300,
+ height: 250,
+ requestId: '21e12606d47ba7',
+ adomain: ['abc.com'],
+ mediaType: BANNER
+ }]
+ };
+
+ const expectedVideoResponse = {
+ requestId: '21e12606d47ba7',
cpm: 12.5,
- vastXml: '',
+ currency: 'USD',
width: 640,
height: 480,
- requestId: '21e12606d47ba7',
+ ttl: TTL,
+ creativeId: '21e12606d47ba7',
netRevenue: true,
+ nurl: 'http://example.com/win/1234',
+ mediaType: VIDEO,
+ meta: {
+ mediaType: VIDEO,
+ advertiserDomains: ['abc.com']
+ },
+ vastXml: '',
+ };
+
+ const expectedBannerResponse = {
+ requestId: '21e12606d47ba7',
+ cpm: 12.5,
currency: 'USD',
- adomain: ['abc.com']
+ width: 640,
+ height: 480,
+ ttl: TTL,
+ creativeId: '21e12606d47ba7',
+ netRevenue: true,
+ nurl: 'http://example.com/win/1234',
+ mediaType: BANNER,
+ meta: {
+ mediaType: BANNER,
+ advertiserDomains: ['abc.com']
+ },
+ ad: '""'
};
it('should get correct bid response', function () {
- let expectedResponse = [
- {
- requestId: '21e12606d47ba7',
- cpm: 12.5,
- width: 640,
- height: 480,
- creativeId: '21e12606d47ba7',
- currency: 'USD',
- netRevenue: true,
- ttl: TTL,
- vastXml: '',
- mediaType: VIDEO,
- meta: {
- advertiserDomains: ['abc.com']
- }
- }
- ];
const result = spec.interpretResponse({ body: response });
- expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0]));
+ expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedVideoResponse));
+ expect(Object.keys(result[1])).to.deep.equal(Object.keys(expectedBannerResponse));
+ });
+
+ it('video type should have vastXml key', function () {
+ const result = spec.interpretResponse({ body: response });
+ expect(result[0].vastXml).to.equal(expectedVideoResponse.vastXml)
+ });
+
+ it('banner type should have ad key', function () {
+ const result = spec.interpretResponse({ body: response });
+ expect(result[1].ad).to.equal(expectedBannerResponse.ad)
});
})
describe('getUserSyncs', function() {
const imageSyncResponse = {
body: {
- userSyncPixels: [
- 'https://image-sync-url.test/1',
- 'https://image-sync-url.test/2',
- 'https://image-sync-url.test/3'
- ]
+ params: {
+ userSyncPixels: [
+ 'https://image-sync-url.test/1',
+ 'https://image-sync-url.test/2',
+ 'https://image-sync-url.test/3'
+ ]
+ }
}
};
const iframeSyncResponse = {
body: {
- userSyncURL: 'https://iframe-sync-url.test'
+ params: {
+ userSyncURL: 'https://iframe-sync-url.test'
+ }
}
};
@@ -402,4 +452,28 @@ describe('minutemediaAdapter', function () {
expect(syncs).to.deep.equal([]);
});
})
+
+ describe('onBidWon', function() {
+ beforeEach(function() {
+ sinon.stub(utils, 'triggerPixel');
+ });
+ afterEach(function() {
+ utils.triggerPixel.restore();
+ });
+
+ it('Should trigger pixel if bid nurl', function() {
+ const bid = {
+ 'bidder': spec.code,
+ 'adUnitCode': 'adunit-code',
+ 'sizes': [['640', '480']],
+ 'nurl': 'http://example.com/win/1234',
+ 'params': {
+ 'org': 'jdye8weeyirk00000001'
+ }
+ };
+
+ spec.onBidWon(bid);
+ expect(utils.triggerPixel.callCount).to.equal(1)
+ })
+ })
});