diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js
index 28fb564320d..c02a0cb138f 100644
--- a/modules/adkernelAdnBidAdapter.js
+++ b/modules/adkernelAdnBidAdapter.js
@@ -80,7 +80,7 @@ export const spec = {
code: 'adkernelAdn',
- supportedMediaTypes: [VIDEO],
+ supportedMediaTypes: [BANNER, VIDEO],
isBidRequestValid: function(bidRequest) {
return 'params' in bidRequest && (typeof bidRequest.params.host === 'undefined' || typeof bidRequest.params.host === 'string') &&
diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js
index 016cc5794fb..c3f34274692 100644
--- a/modules/adkernelBidAdapter.js
+++ b/modules/adkernelBidAdapter.js
@@ -16,7 +16,7 @@ export const spec = {
code: 'adkernel',
aliases: ['headbidding'],
- supportedMediaTypes: [VIDEO],
+ supportedMediaTypes: [BANNER, VIDEO],
isBidRequestValid: function(bidRequest) {
return 'params' in bidRequest && typeof bidRequest.params.host !== 'undefined' &&
'zoneId' in bidRequest.params && !isNaN(Number(bidRequest.params.zoneId));
diff --git a/modules/adxcgBidAdapter.js b/modules/adxcgBidAdapter.js
index 44b1f381bbe..91bf0746afc 100644
--- a/modules/adxcgBidAdapter.js
+++ b/modules/adxcgBidAdapter.js
@@ -1,7 +1,7 @@
import * as utils from 'src/utils';
import * as url from 'src/url';
import {registerBidder} from 'src/adapters/bidderFactory';
-import {NATIVE, VIDEO} from 'src/mediaTypes';
+import {BANNER, NATIVE, VIDEO} from 'src/mediaTypes';
/**
* Adapter for requesting bids from adxcg.net
@@ -9,7 +9,7 @@ import {NATIVE, VIDEO} from 'src/mediaTypes';
*/
const BIDDER_CODE = 'adxcg';
-const SUPPORTED_AD_TYPES = [VIDEO, NATIVE];
+const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE];
const SOURCE = 'pbjs10';
export const spec = {
code: BIDDER_CODE,
diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js
index 21af777bdc5..6e5d4820ee1 100644
--- a/modules/appnexusBidAdapter.js
+++ b/modules/appnexusBidAdapter.js
@@ -1,13 +1,12 @@
import { Renderer } from 'src/Renderer';
import * as utils from 'src/utils';
import { registerBidder } from 'src/adapters/bidderFactory';
-import { NATIVE, VIDEO } from 'src/mediaTypes';
+import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes';
import find from 'core-js/library/fn/array/find';
import includes from 'core-js/library/fn/array/includes';
const BIDDER_CODE = 'appnexus';
const URL = '//ib.adnxs.com/ut/v3/prebid';
-const SUPPORTED_AD_TYPES = ['banner', 'video', 'native'];
const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration',
'startdelay', 'skippable', 'playback_method', 'frameworks'];
const USER_PARAMS = ['age', 'external_uid', 'segments', 'gender', 'dnt', 'language'];
@@ -31,7 +30,7 @@ const SOURCE = 'pbjs';
export const spec = {
code: BIDDER_CODE,
aliases: ['appnexusAst', 'brealtime', 'pagescience', 'defymedia', 'gourmetads', 'matomy', 'featureforward', 'oftmedia', 'districtm'],
- supportedMediaTypes: [VIDEO, NATIVE],
+ supportedMediaTypes: [BANNER, VIDEO, NATIVE],
/**
* Determines whether or not the given bid request is valid.
@@ -103,7 +102,7 @@ export const spec = {
serverResponse.tags.forEach(serverBid => {
const rtbBid = getRtbBid(serverBid);
if (rtbBid) {
- if (rtbBid.cpm !== 0 && includes(SUPPORTED_AD_TYPES, rtbBid.ad_type)) {
+ if (rtbBid.cpm !== 0 && includes(this.supportedMediaTypes, rtbBid.ad_type)) {
const bid = newBid(serverBid, rtbBid);
bid.mediaType = parseMediaType(rtbBid);
bids.push(bid);
@@ -197,7 +196,6 @@ function newBid(serverBid, rtbBid) {
width: rtbBid.rtb.video.player_width,
height: rtbBid.rtb.video.player_height,
vastUrl: rtbBid.rtb.video.asset_url,
- descriptionUrl: rtbBid.rtb.video.asset_url,
ttl: 3600
});
// This supports Outstream Video
@@ -209,9 +207,9 @@ function newBid(serverBid, rtbBid) {
bid.adResponse.ad = bid.adResponse.ads[0];
bid.adResponse.ad.video = bid.adResponse.ad.rtb.video;
}
- } else if (rtbBid.rtb['native']) {
- const nativeAd = rtbBid.rtb['native'];
- bid['native'] = {
+ } else if (rtbBid.rtb[NATIVE]) {
+ const nativeAd = rtbBid.rtb[NATIVE];
+ bid[NATIVE] = {
title: nativeAd.title,
body: nativeAd.desc,
cta: nativeAd.ctatext,
@@ -256,6 +254,7 @@ function bidToTag(bid) {
const tag = {};
tag.sizes = transformSizes(bid.sizes);
tag.primary_size = tag.sizes[0];
+ tag.ad_types = [];
tag.uuid = bid.bidId;
if (bid.params.placementId) {
tag.id = parseInt(bid.params.placementId, 10);
@@ -294,19 +293,24 @@ function bidToTag(bid) {
tag.keywords = getKeywords(bid.params.keywords);
}
- if (bid.mediaType === 'native' || utils.deepAccess(bid, 'mediaTypes.native')) {
- tag.ad_types = ['native'];
+ if (bid.mediaType === NATIVE || utils.deepAccess(bid, `mediaTypes.${NATIVE}`)) {
+ tag.ad_types.push(NATIVE);
if (bid.nativeParams) {
const nativeRequest = buildNativeRequest(bid.nativeParams);
- tag['native'] = {layouts: [nativeRequest]};
+ tag[NATIVE] = {layouts: [nativeRequest]};
}
}
- const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video');
+ const videoMediaType = utils.deepAccess(bid, `mediaTypes.${VIDEO}`);
const context = utils.deepAccess(bid, 'mediaTypes.video.context');
- if (bid.mediaType === 'video' || (videoMediaType && context !== 'outstream')) {
+ if (bid.mediaType === VIDEO || videoMediaType) {
+ tag.ad_types.push(VIDEO);
+ }
+
+ // instream gets vastUrl, outstream gets vastXml
+ if (bid.mediaType === VIDEO || (videoMediaType && context !== 'outstream')) {
tag.require_asset_url = true;
}
@@ -318,6 +322,13 @@ function bidToTag(bid) {
.forEach(param => tag.video[param] = bid.params.video[param]);
}
+ if (
+ (utils.isEmpty(bid.mediaType) && utils.isEmpty(bid.mediaTypes)) ||
+ (bid.mediaType === BANNER || (bid.mediaTypes && bid.mediaTypes[BANNER]))
+ ) {
+ tag.ad_types.push(BANNER);
+ }
+
return tag;
}
@@ -414,12 +425,12 @@ function handleOutstreamRendererEvents(bid, id, eventName) {
function parseMediaType(rtbBid) {
const adType = rtbBid.ad_type;
- if (adType === 'video') {
- return 'video';
- } else if (adType === 'native') {
- return 'native';
+ if (adType === VIDEO) {
+ return VIDEO;
+ } else if (adType === NATIVE) {
+ return NATIVE;
} else {
- return 'banner';
+ return BANNER;
}
}
diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js
index 41ca539ccba..2b0e4cd8190 100644
--- a/modules/audienceNetworkBidAdapter.js
+++ b/modules/audienceNetworkBidAdapter.js
@@ -12,7 +12,7 @@ const code = 'audienceNetwork';
const currency = 'USD';
const method = 'GET';
const url = 'https://an.facebook.com/v2/placementbid.json';
-const supportedMediaTypes = ['video'];
+const supportedMediaTypes = ['banner', 'video'];
const netRevenue = true;
const hb_bidder = 'fan';
diff --git a/modules/colossussspBidAdapter.js b/modules/colossussspBidAdapter.js
new file mode 100644
index 00000000000..df011bc102d
--- /dev/null
+++ b/modules/colossussspBidAdapter.js
@@ -0,0 +1,132 @@
+import { registerBidder } from 'src/adapters/bidderFactory';
+import * as utils from 'src/utils';
+
+const BIDDER_CODE = 'colossusssp';
+const URL = '//colossusssp.com/?c=o&m=multi';
+const URL_SYNC = '//colossusssp.com/?c=o&m=cookie';
+
+let sizeObj = {
+ '468x60': 1,
+ '728x90': 2,
+ '300x600': 10,
+ '300x250': 15,
+ '300x100': 19,
+ '320x50': 43,
+ '300x50': 44,
+ '300x300': 48,
+ '300x1050': 54,
+ '970x90': 55,
+ '970x250': 57,
+ '1000x90': 58,
+ '320x80': 59,
+ '640x480': 65,
+ '320x480': 67,
+ '320x320': 72,
+ '320x160': 73,
+ '480x300': 83,
+ '970x310': 94,
+ '970x210': 96,
+ '480x320': 101,
+ '768x1024': 102,
+ '1000x300': 113,
+ '320x100': 117,
+ '800x250': 118,
+ '200x600': 119
+};
+
+utils._each(sizeObj, (item, key) => sizeObj[item] = key);
+
+export const spec = {
+ code: BIDDER_CODE,
+
+ /**
+ * Determines whether or not the given bid request is valid.
+ *
+ * @param {object} bid The bid to validate.
+ * @return boolean True if this is a valid bid, and false otherwise.
+ */
+ isBidRequestValid: (bid) => {
+ return (!isNaN(bid.params.placement_id) &&
+ ((bid.params.sizes !== undefined && bid.params.sizes.length > 0 && bid.params.sizes.some((sizeIndex) => sizeObj[sizeIndex] !== undefined)) ||
+ (bid.sizes !== undefined && bid.sizes.length > 0 && bid.sizes.map((size) => `${size[0]}x${size[1]}`).some((size) => sizeObj[size] !== undefined))));
+ },
+
+ /**
+ * Make a server request from the list of BidRequests.
+ *
+ * @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server.
+ * @return ServerRequest Info describing the request to the server.
+ */
+ buildRequests: (validBidRequests) => {
+ let winTop = window;
+ try {
+ window.top.location.toString();
+ winTop = window.top;
+ } catch (e) {
+ utils.logMessage(e);
+ };
+ let location = utils.getTopWindowLocation();
+ let placements = [];
+ let request = {
+ 'deviceWidth': winTop.screen.width,
+ 'deviceHeight': winTop.screen.height,
+ 'language': (navigator && navigator.language) ? navigator.language : '',
+ 'secure': location.protocol === 'https:' ? 1 : 0,
+ 'host': location.host,
+ 'page': location.pathname,
+ 'placements': placements
+ };
+ for (let i = 0; i < validBidRequests.length; i++) {
+ let bid = validBidRequests[i];
+ let placement = {};
+ placement['placementId'] = bid.params.placement_id;
+ placement['bidId'] = bid.bidId;
+ placement['sizes'] = bid.sizes;
+ placements.push(placement);
+ }
+ return {
+ method: 'POST',
+ url: URL,
+ data: request
+ };
+ },
+
+ /**
+ * Unpack the response from the server into a list of bids.
+ *
+ * @param {*} serverResponse A successful response from the server.
+ * @return {Bid[]} An array of bids which were nested inside the server.
+ */
+ interpretResponse: (serverResponse) => {
+ let response = [];
+ try {
+ serverResponse = serverResponse.body;
+ for (let i = 0; i < serverResponse.length; i++) {
+ let resItem = serverResponse[i];
+ if (resItem.width && !isNaN(resItem.width) &&
+ resItem.height && !isNaN(resItem.height) &&
+ resItem.requestId && typeof resItem.requestId === 'string' &&
+ resItem.cpm && !isNaN(resItem.cpm) &&
+ resItem.ad && typeof resItem.ad === 'string' &&
+ resItem.ttl && !isNaN(resItem.ttl) &&
+ resItem.creativeId && typeof resItem.creativeId === 'string' &&
+ resItem.netRevenue && typeof resItem.netRevenue === 'boolean' &&
+ resItem.currency && typeof resItem.currency === 'string') {
+ response.push(resItem);
+ }
+ }
+ } catch (e) {
+ utils.logMessage(e);
+ };
+ return response;
+ },
+
+ getUserSyncs: () => {
+ return [{
+ type: 'image',
+ url: URL_SYNC
+ }];
+ }
+};
+
+registerBidder(spec);
diff --git a/modules/colossussspBidAdapter.md b/modules/colossussspBidAdapter.md
new file mode 100644
index 00000000000..9a5b9a0fe39
--- /dev/null
+++ b/modules/colossussspBidAdapter.md
@@ -0,0 +1,26 @@
+# Overview
+
+```
+Module Name: Colossus SSP Bidder Adapter
+Module Type: Bidder Adapter
+Maintainer: support@colossusmediallc.com
+```
+
+# Description
+
+Module that connects to Colossus SSP demand sources
+
+# Test Parameters
+```
+ var adUnits = [{
+ code: 'placementid_0',
+ sizes: [[300, 250]],
+ bids: [{
+ bidder: 'colossusssp',
+ params: {
+ placement_id: 0
+ }
+ }]
+ }
+ ];
+```
diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js
index 1f6c4f27b77..cae64983089 100644
--- a/modules/conversantBidAdapter.js
+++ b/modules/conversantBidAdapter.js
@@ -1,6 +1,6 @@
import * as utils from 'src/utils';
import {registerBidder} from 'src/adapters/bidderFactory';
-import { VIDEO } from 'src/mediaTypes';
+import { BANNER, VIDEO } from 'src/mediaTypes';
const BIDDER_CODE = 'conversant';
const URL = '//media.msg.dotomi.com/s2s/header/24';
@@ -10,7 +10,7 @@ const VERSION = '2.2.1';
export const spec = {
code: BIDDER_CODE,
aliases: ['cnvr'], // short code
- supportedMediaTypes: [VIDEO],
+ supportedMediaTypes: [BANNER, VIDEO],
/**
* Determines whether or not the given bid request is valid.
diff --git a/modules/freewheelSSPBidAdapter.js b/modules/freewheelSSPBidAdapter.js
index 64ebb36478b..632df8fe93c 100644
--- a/modules/freewheelSSPBidAdapter.js
+++ b/modules/freewheelSSPBidAdapter.js
@@ -190,7 +190,7 @@ var getOutstreamScript = function(bid) {
export const spec = {
code: BIDDER_CODE,
- supportedMediaTypes: ['video'],
+ supportedMediaTypes: ['banner', 'video'],
aliases: ['stickyadstv'], // former name for freewheel-ssp
/**
* Determines whether or not the given bid request is valid.
diff --git a/modules/inskinBidAdapter.js b/modules/inskinBidAdapter.js
new file mode 100644
index 00000000000..5274b5b2ba8
--- /dev/null
+++ b/modules/inskinBidAdapter.js
@@ -0,0 +1,210 @@
+import * as utils from 'src/utils';
+import { registerBidder } from 'src/adapters/bidderFactory';
+
+const BIDDER_CODE = 'inskin';
+
+const CONFIG = {
+ 'inskin': {
+ 'BASE_URI': 'https://mfad.inskinad.com/api/v2'
+ }
+};
+
+export const spec = {
+ code: BIDDER_CODE,
+
+ /**
+ * Determines whether or not the given bid request is valid.
+ *
+ * @param {BidRequest} bid The bid params to validate.
+ * @return boolean True if this is a valid bid, and false otherwise.
+ */
+ isBidRequestValid: function(bid) {
+ return !!(bid.params.networkId && bid.params.siteId);
+ },
+
+ /**
+ * Make a server request from the list of BidRequests.
+ *
+ * @param {validBidRequests[]} - an array of bids
+ * @return ServerRequest Info describing the request to the server.
+ */
+
+ buildRequests: function(validBidRequests) {
+ // Do we need to group by bidder? i.e. to make multiple requests for
+ // different endpoints.
+
+ let ret = {
+ method: 'POST',
+ url: '',
+ data: '',
+ bidRequest: []
+ };
+
+ if (validBidRequests.length < 1) {
+ return ret;
+ }
+
+ let ENDPOINT_URL;
+
+ const data = Object.assign({
+ placements: [],
+ time: Date.now(),
+ user: {},
+ url: utils.getTopWindowUrl(),
+ referrer: document.referrer,
+ enableBotFiltering: true,
+ includePricingData: true,
+ parallel: true
+ }, validBidRequests[0].params);
+
+ validBidRequests.map(bid => {
+ let config = CONFIG[bid.bidder];
+ ENDPOINT_URL = config.BASE_URI;
+
+ const placement = Object.assign({
+ divName: bid.bidId,
+ adTypes: bid.adTypes || getSize(bid.sizes),
+ eventIds: [40, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295]
+ }, bid.params);
+
+ placement.adTypes.push(5, 9, 163, 2163, 3006);
+
+ if (placement.networkId && placement.siteId) {
+ data.placements.push(placement);
+ }
+ });
+
+ ret.data = JSON.stringify(data);
+ ret.bidRequest = validBidRequests;
+ ret.url = ENDPOINT_URL;
+
+ return ret;
+ },
+
+ /**
+ * Unpack the response from the server into a list of bids.
+ *
+ * @param {*} serverResponse A successful response from the server.
+ * @return {Bid[]} An array of bids which were nested inside the server.
+ */
+ interpretResponse: function(serverResponse, bidRequest) {
+ let bid;
+ let bids;
+ let bidId;
+ let bidObj;
+ let bidResponses = [];
+ let bidsMap = {};
+
+ bids = bidRequest.bidRequest;
+
+ serverResponse = (serverResponse || {}).body;
+ for (let i = 0; i < bids.length; i++) {
+ bid = {};
+ bidObj = bids[i];
+ bidId = bidObj.bidId;
+
+ bidsMap[bidId] = bidObj;
+
+ if (serverResponse) {
+ const decision = serverResponse.decisions && serverResponse.decisions[bidId];
+ const price = decision && decision.pricing && decision.pricing.clearPrice;
+
+ if (decision && price) {
+ bid.requestId = bidId;
+ bid.cpm = price;
+ bid.width = decision.width;
+ bid.height = decision.height;
+ bid.ad = retrieveAd(bidId, decision);
+ bid.currency = 'USD';
+ bid.creativeId = decision.adId;
+ bid.ttl = 360;
+ bid.netRevenue = true;
+ bid.referrer = utils.getTopWindowUrl();
+
+ bidResponses.push(bid);
+ }
+ }
+ }
+
+ if (bidResponses.length) {
+ window.addEventListener('message', function(e) {
+ if (!e.data || e.data.from !== 'ism-bid') {
+ return;
+ }
+
+ const decision = serverResponse.decisions && serverResponse.decisions[e.data.bidId];
+ if (!decision) {
+ return;
+ }
+
+ const id = 'ism_tag_' + Math.floor((Math.random() * 10e16));
+ window[id] = {
+ bidId: e.data.bidId,
+ serverResponse
+ };
+ const script = document.createElement('script');
+ script.src = 'https://cdn.inskinad.com/isfe/publishercode/' + bidsMap[e.data.bidId].params.siteId + '/default.js?autoload&id=' + id;
+ document.getElementsByTagName('head')[0].appendChild(script);
+ });
+ }
+
+ return bidResponses;
+ },
+
+ getUserSyncs: function(syncOptions) {
+ return [];
+ }
+};
+
+const sizeMap = [
+ null,
+ '120x90',
+ '120x90',
+ '468x60',
+ '728x90',
+ '300x250',
+ '160x600',
+ '120x600',
+ '300x100',
+ '180x150',
+ '336x280',
+ '240x400',
+ '234x60',
+ '88x31',
+ '120x60',
+ '120x240',
+ '125x125',
+ '220x250',
+ '250x250',
+ '250x90',
+ '0x0',
+ '200x90',
+ '300x50',
+ '320x50',
+ '320x480',
+ '185x185',
+ '620x45',
+ '300x125',
+ '800x250'
+];
+
+sizeMap[77] = '970x90';
+sizeMap[123] = '970x250';
+sizeMap[43] = '300x600';
+
+function getSize(sizes) {
+ const result = [];
+ sizes.forEach(function(size) {
+ const index = sizeMap.indexOf(size[0] + 'x' + size[1]);
+ if (index >= 0) {
+ result.push(index);
+ }
+ });
+ return result;
+}
+
+function retrieveAd(bidId, decision) {
+ return "';
+
+ let responseCreativeId = '274';
+ let responseCurrency = 'USD';
+
+ let responseWidth = 300;
+ let responseHeight = 250;
+ let responseTtl = 213;
+
+ let sampleResponse = {
+ id: '66043f5ca44ecd8f8769093b1615b2d9',
+ seatbid: [
+ {
+ bid: [
+ {
+ id: 'c21bab0e-7668-4d8f-908a-63e094c09197',
+ impid: '1',
+ price: responsePrice,
+ adid: responseCreativeId,
+ adm: responseCreative,
+ adomain: [
+ 'www.rockyouteststudios.com'
+ ],
+ cid: '274',
+ attr: [],
+ w: responseWidth,
+ h: responseHeight,
+ ext: {
+ ttl: responseTtl
+ }
+ }
+ ],
+ seat: '201',
+ group: 0
+ }
+ ],
+ bidid: 'c21bab0e-7668-4d8f-908a-63e094c09197',
+ cur: responseCurrency
+ };
+
+ let sampleRequest = {
+ bidId: incomingRequestId,
+ mediaTypes: { banner: {} },
+ requestId: incomingRequestId
+ };
+
+ let result = spec.interpretResponse(
+ {
+ body: sampleResponse
+ },
+ sampleRequest
+ );
+
+ expect(result.length).to.equal(1);
+
+ let processedBid = result[0];
+
+ // expect(processedBid.requestId).to.equal(incomingRequestId);
+ expect(processedBid.cpm).to.equal(responsePrice);
+ expect(processedBid.width).to.equal(responseWidth);
+ expect(processedBid.height).to.equal(responseHeight);
+ expect(processedBid.ad).to.equal(responseCreative);
+ expect(processedBid.ttl).to.equal(responseTtl);
+ expect(processedBid.creativeId).to.equal(responseCreativeId);
+ expect(processedBid.netRevenue).to.equal(true);
+ expect(processedBid.currency).to.equal(responseCurrency);
+ });
+
+ it('returns an valid bid response on sucessful video request', () => {
+ let incomingRequestId = 'XXtesting-275XX';
+ let responsePrice = 6
+
+ let responseCreative = '\n\n \n \n Mediatastic\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n';
+
+ let responseCreativeId = '1556';
+ let responseCurrency = 'USD';
+
+ let responseWidth = 284;
+ let responseHeight = 285;
+ let responseTtl = 286;
+
+ let sampleResponse = {
+ id: '1234567890',
+ seatbid: [
+ {
+ bid: [
+ {
+ id: 'a8ae0b48-a8db-4220-ba0c-7458f452b1f5',
+ impid: '1',
+ price: responsePrice,
+ adid: responseCreativeId,
+ adm: responseCreative,
+ cid: '270',
+ attr: [],
+ w: responseWidth,
+ h: responseHeight,
+ ext: {
+ ttl: responseTtl
+ }
+ }
+ ],
+ seat: '201',
+ group: 0
+ }
+ ],
+ bidid: 'a8ae0b48-a8db-4220-ba0c-7458f452b1f5',
+ cur: 'USD'
+ };
+
+ let sampleRequest = {
+ bidId: incomingRequestId,
+ mediaTypes: {
+ video: {
+ }
+ },
+ requestId: incomingRequestId
+ };
+
+ let result = spec.interpretResponse(
+ {
+ body: sampleResponse
+ },
+ sampleRequest
+ );
+
+ expect(result.length).to.equal(1);
+
+ let processedBid = result[0];
+
+ // expect(processedBid.requestId).to.equal(incomingRequestId);
+ expect(processedBid.cpm).to.equal(responsePrice);
+ expect(processedBid.width).to.equal(responseWidth);
+ expect(processedBid.height).to.equal(responseHeight);
+ expect(processedBid.ad).to.equal(null);
+ expect(processedBid.ttl).to.equal(responseTtl);
+ expect(processedBid.creativeId).to.equal(responseCreativeId);
+ expect(processedBid.netRevenue).to.equal(true);
+ expect(processedBid.currency).to.equal(responseCurrency);
+ expect(processedBid.vastXml).to.equal(responseCreative);
+ });
+
+ it('generates event callbacks as expected', () => {
+ let tally = {};
+ let renderer = {
+ handleVideoEvent: (eventObject) => {
+ let eventName = eventObject.eventName;
+ if (tally[eventName]) {
+ tally[eventName] = tally[eventName] + 1;
+ } else {
+ tally[eventName] = 1;
+ }
+ }
+ };
+
+ let callbacks = internals.playerCallbacks(renderer);
+
+ let validCallbacks = ['LOAD', 'IMPRESSION', 'COMPLETE', 'ERROR'];
+
+ validCallbacks.forEach(event => {
+ callbacks('n/a', event);
+ });
+
+ let callbackKeys = Object.keys(tally);
+ expect(callbackKeys.length).to.equal(3);
+ expect(tally['loaded']).to.equal(1);
+ expect(tally['impression']).to.equal(1);
+ expect(tally['ended']).to.equal(2);
+ });
+
+ it('generates a renderer that will hide on complete', () => {
+ let elementName = 'test_element_id';
+ let selector = `#${elementName}`;
+
+ let mockElement = {
+ style: {
+ display: 'some'
+ }
+ };
+
+ document.querySelector = (name) => {
+ if (name === selector) {
+ return mockElement;
+ } else {
+ return null;
+ }
+ };
+
+ let renderer = internals.generateRenderer({}, elementName);
+
+ renderer.handlers['ended']();
+
+ expect(mockElement.style.display).to.equal('none');
+ })
+ });
+});
diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js
new file mode 100644
index 00000000000..5cb4a1277fb
--- /dev/null
+++ b/test/spec/modules/smartadserverBidAdapter_spec.js
@@ -0,0 +1,157 @@
+import {
+ expect
+} from 'chai';
+import {
+ spec
+} from 'modules/smartadserverBidAdapter';
+import {
+ getTopWindowLocation
+} from 'src/utils';
+import {
+ newBidder
+} from 'src/adapters/bidderFactory';
+import {
+ config
+} from 'src/config';
+import * as utils from 'src/utils';
+
+describe('Smart ad server bid adapter tests', () => {
+ var DEFAULT_PARAMS = [{
+ adUnitCode: 'sas_42',
+ bidId: 'abcd1234',
+ sizes: [
+ [300, 250],
+ [300, 200]
+ ],
+ bidder: 'smartadserver',
+ params: {
+ domain: 'http://prg.smartadserver.com',
+ siteId: '1234',
+ pageId: '5678',
+ formatId: '90',
+ target: 'test=prebid',
+ bidfloor: 0.420
+ },
+ requestId: 'efgh5678',
+ transactionId: 'zsfgzzg'
+ }];
+
+ var DEFAULT_PARAMS_WO_OPTIONAL = [{
+ adUnitCode: 'sas_42',
+ bidId: 'abcd1234',
+ sizes: [
+ [300, 250],
+ [300, 200]
+ ],
+ bidder: 'smartadserver',
+ params: {
+ domain: 'http://prg.smartadserver.com',
+ siteId: '1234',
+ pageId: '5678',
+ formatId: '90'
+ },
+ requestId: 'efgh5678'
+ }];
+
+ var BID_RESPONSE = {
+ body: {
+ cpm: 12,
+ width: 300,
+ height: 250,
+ creativeId: 'zioeufg',
+ currency: 'GBP',
+ isNetCpm: true,
+ ttl: 300,
+ adUrl: 'http://awesome.fake.url',
+ ad: '< --- awesome script --- >'
+ }
+ };
+
+ it('Verify build request', () => {
+ config.setConfig({
+ 'currency': {
+ 'adServerCurrency': 'EUR'
+ }
+ });
+ const request = spec.buildRequests(DEFAULT_PARAMS);
+ expect(request).to.have.property('url').and.to.equal('http://prg.smartadserver.com/prebid/v1');
+ expect(request).to.have.property('method').and.to.equal('POST');
+ const requestContent = JSON.parse(request.data);
+ expect(requestContent).to.have.property('siteid').and.to.equal('1234');
+ expect(requestContent).to.have.property('pageid').and.to.equal('5678');
+ expect(requestContent).to.have.property('formatid').and.to.equal('90');
+ expect(requestContent).to.have.property('currencyCode').and.to.equal('EUR');
+ expect(requestContent).to.have.property('bidfloor').and.to.equal(0.42);
+ expect(requestContent).to.have.property('targeting').and.to.equal('test=prebid');
+ expect(requestContent).to.have.property('tagId').and.to.equal('sas_42');
+ expect(requestContent).to.have.property('sizes');
+ expect(requestContent.sizes[0]).to.have.property('w').and.to.equal(300);
+ expect(requestContent.sizes[0]).to.have.property('h').and.to.equal(250);
+ expect(requestContent.sizes[1]).to.have.property('w').and.to.equal(300);
+ expect(requestContent.sizes[1]).to.have.property('h').and.to.equal(200);
+ expect(requestContent).to.have.property('pageDomain').and.to.equal(utils.getTopWindowUrl());
+ expect(requestContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined;
+ });
+
+ it('Verify parse response', () => {
+ const request = spec.buildRequests(DEFAULT_PARAMS);
+ const bids = spec.interpretResponse(BID_RESPONSE, request);
+ expect(bids).to.have.lengthOf(1);
+ const bid = bids[0];
+ expect(bid.cpm).to.equal(12);
+ expect(bid.adUrl).to.equal('http://awesome.fake.url');
+ expect(bid.ad).to.equal('< --- awesome script --- >');
+ expect(bid.width).to.equal(300);
+ expect(bid.height).to.equal(250);
+ expect(bid.creativeId).to.equal('zioeufg');
+ expect(bid.currency).to.equal('GBP');
+ expect(bid.netRevenue).to.equal(true);
+ expect(bid.ttl).to.equal(300);
+ expect(bid.requestId).to.equal(DEFAULT_PARAMS[0].bidId);
+ expect(bid.referrer).to.equal(utils.getTopWindowUrl());
+ });
+
+ it('Verifies bidder code', () => {
+ expect(spec.code).to.equal('smartadserver');
+ });
+
+ it('Verifies bidder aliases', () => {
+ expect(spec.aliases).to.have.lengthOf(1);
+ expect(spec.aliases[0]).to.equal('smart');
+ });
+
+ it('Verifies if bid request valid', () => {
+ expect(spec.isBidRequestValid(DEFAULT_PARAMS[0])).to.equal(true);
+ expect(spec.isBidRequestValid(DEFAULT_PARAMS_WO_OPTIONAL[0])).to.equal(true);
+ expect(spec.isBidRequestValid({})).to.equal(false);
+ expect(spec.isBidRequestValid({
+ params: {}
+ })).to.equal(false);
+ expect(spec.isBidRequestValid({
+ params: {
+ pageid: 123
+ }
+ })).to.equal(false);
+ expect(spec.isBidRequestValid({
+ params: {
+ siteid: 123
+ }
+ })).to.equal(false);
+ expect(spec.isBidRequestValid({
+ params: {
+ formatid: 123,
+ pageid: 234
+ }
+ })).to.equal(false);
+ expect(spec.isBidRequestValid({
+ params: {
+ domain: 'www.test.com',
+ pageid: 234
+ }
+ })).to.equal(false);
+ });
+
+ it('Verifies sync options', () => {
+ expect(spec.getUserSyncs).to.be.undefined;
+ });
+});
diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js
index c1f7fe82252..9605babf3d9 100644
--- a/test/spec/unit/pbjs_api_spec.js
+++ b/test/spec/unit/pbjs_api_spec.js
@@ -897,54 +897,22 @@ describe('Unit: Prebid Module', function () {
});
});
- describe.skip('#video', () => {
+ describe('multiformat requests', () => {
let spyCallBids;
let createAuctionStub;
let adUnits;
- before(() => {
+ beforeEach(() => {
adUnits = [{
code: 'adUnit-code',
- mediaType: 'video',
+ mediaTypes: {
+ banner: {},
+ native: {},
+ },
sizes: [[300, 250], [300, 600]],
bids: [
{bidder: 'appnexus', params: {placementId: 'id'}},
- {bidder: 'sampleBidder', params: {placementId: 'id'}}
- ]
- }];
- adUnitCodes = ['adUnit-code'];
- let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout});
- spyCallBids = sinon.spy(adaptermanager, 'callBids');
- createAuctionStub = sinon.stub(auctionModule, 'newAuction');
- createAuctionStub.returns(auction);
- });
-
- after(() => {
- auctionModule.newAuction.restore();
- adaptermanager.callBids.restore();
- });
-
- it('should not callBids if a video adUnit has non-video bidders', () => {
- const videoAdaptersBackup = adaptermanager.videoAdapters;
- adaptermanager.videoAdapters = ['appnexus'];
- $$PREBID_GLOBAL$$.requestBids({adUnits});
- sinon.assert.notCalled(adaptermanager.callBids);
- adaptermanager.videoAdapters = videoAdaptersBackup;
- });
- });
-
- describe('#video', () => {
- let spyCallBids;
- let createAuctionStub;
- let adUnits;
-
- before(() => {
- adUnits = [{
- code: 'adUnit-code',
- mediaType: 'video',
- sizes: [[300, 250], [300, 600]],
- bids: [
- {bidder: 'appnexus', params: {placementId: 'id'}}
+ {bidder: 'sampleBidder', params: {placementId: 'banner-only-bidder'}}
]
}];
adUnitCodes = ['adUnit-code'];
@@ -954,53 +922,32 @@ describe('Unit: Prebid Module', function () {
createAuctionStub.returns(auction);
})
- after(() => {
+ afterEach(() => {
auctionModule.newAuction.restore();
adaptermanager.callBids.restore();
});
- it('should callBids if a video adUnit has all video bidders', () => {
- const videoAdaptersBackup = adaptermanager.videoAdapters;
- adaptermanager.videoAdapters = ['appnexus'];
+ it('bidders that support one of the declared formats are allowed to participate', () => {
$$PREBID_GLOBAL$$.requestBids({adUnits});
sinon.assert.calledOnce(adaptermanager.callBids);
- adaptermanager.videoAdapters = videoAdaptersBackup;
- });
- });
- describe('#native', () => {
- let spyCallBids;
- let createAuctionStub;
- let adUnits;
+ const spyArgs = adaptermanager.callBids.getCall(0);
+ const biddersCalled = spyArgs.args[0][0].bids;
- before(() => {
- adUnits = [{
- code: 'adUnit-code',
- mediaType: 'native',
- sizes: [[300, 250], [300, 600]],
- bids: [
- {bidder: 'appnexus', params: {placementId: 'id'}},
- {bidder: 'sampleBidder', params: {placementId: 'id'}}
- ]
- }];
- adUnitCodes = ['adUnit-code'];
- let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout});
- spyCallBids = sinon.spy(adaptermanager, 'callBids');
- createAuctionStub = sinon.stub(auctionModule, 'newAuction');
- createAuctionStub.returns(auction);
+ // appnexus and sampleBidder both support banner
+ expect(biddersCalled.length).to.equal(2);
});
- after(() => {
- auctionModule.newAuction.restore();
- adaptermanager.callBids.restore();
- });
+ it('bidders that do not support one of the declared formats are dropped', () => {
+ delete adUnits[0].mediaTypes.banner;
- it('should only request native bidders on native adunits', () => {
- // appnexus is a native bidder, appnexus is not
$$PREBID_GLOBAL$$.requestBids({adUnits});
sinon.assert.calledOnce(adaptermanager.callBids);
+
const spyArgs = adaptermanager.callBids.getCall(0);
const biddersCalled = spyArgs.args[0][0].bids;
+
+ // only appnexus supports native
expect(biddersCalled.length).to.equal(1);
});
});