diff --git a/modules.json b/modules.json index 8857b8f7e25..27a7822efff 100644 --- a/modules.json +++ b/modules.json @@ -1,10 +1,11 @@ [ - "appnexusBidAdapter", + "appnexusBidAdapter", "sekindoUMBidAdapter", - "pulsepointBidAdapter", - "audienceNetworkBidAdapter", - "openxBidAdapter", + "pulsepointBidAdapter", + "audienceNetworkBidAdapter", + "openxBidAdapter", "rubiconBidAdapter", "sovrnBidAdapter", - "pubmaticBidAdapter" -] \ No newline at end of file + "pubmaticBidAdapter", + "pubmaticServerBidAdapter" +] diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 229e7df44ed..f885d0cca42 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -47,7 +47,7 @@ AppNexusAdapter = function AppNexusAdapter() { let usePaymentRule = utils.getBidIdParameter('usePaymentRule', bid.params); var jptCall = '//ib.adnxs.com/jpt?'; - jptCall = utils.tryAppendQueryString(jptCall, 'callback', preBidNameSpace+'.handleAnCB'); + jptCall = utils.tryAppendQueryString(jptCall, 'callback', preBidNameSpace + '.handleAnCB'); jptCall = utils.tryAppendQueryString(jptCall, 'callback_uid', callbackId); jptCall = utils.tryAppendQueryString(jptCall, 'psa', '0'); jptCall = utils.tryAppendQueryString(jptCall, 'id', placementId); diff --git a/modules/indexExchangeBidAdapter.js b/modules/indexExchangeBidAdapter.js index 8d8014caf99..11648ebd1ab 100644 --- a/modules/indexExchangeBidAdapter.js +++ b/modules/indexExchangeBidAdapter.js @@ -641,7 +641,7 @@ var IndexExchangeAdapter = function IndexExchangeAdapter() { } var usingSizeSpecificSiteID = false; - // Check for size defined in bidder params + // Check for size defined in bidder params if (bid.params.size && utils.isArray(bid.params.size)) { if (!(bid.sizes[j][0] == bid.params.size[0] && bid.sizes[j][1] == bid.params.size[1])) { passOnBid(bid.placementCode); diff --git a/modules/pubmaticServerBidAdapter.js b/modules/pubmaticServerBidAdapter.js new file mode 100644 index 00000000000..f58449bd096 --- /dev/null +++ b/modules/pubmaticServerBidAdapter.js @@ -0,0 +1,312 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +const constants = require('src/constants.json'); + +const BIDDER_CODE = 'pubmaticServer'; +const ENDPOINT = '//ow.pubmatic.com/openrtb/2.4/'; +const CURRENCY = 'USD'; +const AUCTION_TYPE = 1; // PubMaticServer just picking highest bidding bid from the partners configured +const UNDEFINED = undefined; +const IFRAME = 'iframe'; +const IMAGE = 'image'; +const REDIRECT = 'redirect'; +const DEFAULT_VERSION_ID = '0'; + +const CUSTOM_PARAMS = { + 'kadpageurl': '', // Custom page url + 'gender': '', // User gender + 'yob': '', // User year of birth + 'lat': '', // User location - Latitude + 'lon': '', // User Location - Longitude + 'wiid': '', // OpenWrap Wrapper Impression ID + 'profId': '', // OpenWrap Legacy: Profile ID + 'verId': '', // OpenWrap Legacy: version ID + 'divId': '' // OpenWrap new +}; + +function logNonStringParam(paramName, paramValue) { + utils.logWarn('PubMaticServer: Ignoring param : ' + paramName + ' with value : ' + paramValue + ', expects string-value, found ' + typeof paramValue); +} + +function _parseSlotParam(paramName, paramValue) { + if (!utils.isStr(paramValue)) { + paramValue && logNonStringParam(paramName, paramValue); + return UNDEFINED; + } + + paramValue = paramValue.trim(); + + switch (paramName) { + case 'pmzoneid': + return paramValue.split(',').slice(0, 50).map(id => id.trim()).join(); + case 'kadfloor': + return parseFloat(paramValue) || UNDEFINED; + case 'lat': + return parseFloat(paramValue) || UNDEFINED; + case 'lon': + return parseFloat(paramValue) || UNDEFINED; + case 'yob': + return parseInt(paramValue) || UNDEFINED; + case 'gender': + default: + return paramValue; + } +} + +function _initConf() { + var conf = {}; + conf.pageURL = utils.getTopWindowUrl().trim(); + conf.refURL = utils.getTopWindowReferrer().trim(); + return conf; +} + +function _handleCustomParams(params, conf) { + // istanbul ignore else + if (!conf.kadpageurl) { + conf.kadpageurl = conf.pageURL; + } + + var key, value, entry; + for (key in CUSTOM_PARAMS) { + // istanbul ignore else + if (CUSTOM_PARAMS.hasOwnProperty(key)) { + value = params[key]; + // istanbul ignore else + if (value) { + entry = CUSTOM_PARAMS[key]; + if (utils.isA(entry, 'Object')) { + // will be used in future when we want to process a custom param before using + // 'keyname': {f: function() {}} + value = entry.f(value, conf); + } + + if (utils.isStr(value)) { + conf[key] = value; + } else { + logNonStringParam(key, CUSTOM_PARAMS[key]); + } + } + } + } + return conf; +} + +function _createOrtbTemplate(conf) { + return { + id: '' + new Date().getTime(), + at: AUCTION_TYPE, + cur: [CURRENCY], + imp: [], + site: { + page: conf.pageURL, + ref: conf.refURL, + publisher: {} + }, + device: { + ua: navigator.userAgent, + js: 1, + dnt: (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0, + h: screen.height, + w: screen.width, + language: navigator.language + }, + user: {}, + ext: {} + }; +} + +function _createImpressionObject(bid, conf) { + return { + id: bid.bidId, + tagid: bid.params.adUnitId, + bidfloor: _parseSlotParam('kadfloor', bid.params.kadfloor), + secure: window.location.protocol === 'https:' ? 1 : 0, + banner: { + pos: 0, + topframe: utils.inIframe() ? 0 : 1, + format: (function() { + let arr = []; + for (let i = 0, l = bid.sizes.length; i < l; i++) { + arr.push({ + w: bid.sizes[i][0], + h: bid.sizes[i][1] + }); + } + return arr; + })() + }, + ext: { + pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid), + div: bid.params.divId + } + }; +} + +function mandatoryParamCheck(paramName, paramValue) { + if (!utils.isStr(paramValue)) { + utils.logWarn(BIDDER_CODE + ': ' + paramName + ' is mandatory and it should be a string, , found ' + typeof paramValue); + return false; + } + return true; +} + +export const spec = { + code: BIDDER_CODE, + + /** + * Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: bid => { + if (bid && bid.params) { + return mandatoryParamCheck('publisherId', bid.params.publisherId) && + mandatoryParamCheck('adUnitId', bid.params.adUnitId) && + mandatoryParamCheck('divId', bid.params.divId) && + mandatoryParamCheck('adUnitIndex', bid.params.adUnitIndex); + } + return false; + }, + + /** + * 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: validBidRequests => { + let conf = _initConf(); + let payload = _createOrtbTemplate(conf); + + if (utils.isEmpty(validBidRequests)) { + utils.logWarn('No Valid Bid Request found for given adUnits'); + return; + } + + validBidRequests.forEach(bid => { + conf.pubId = conf.pubId || bid.params.publisherId; + conf = _handleCustomParams(bid.params, conf); + conf.transactionId = bid.transactionId; + payload.imp.push(_createImpressionObject(bid, conf)); + }); + + payload.site.publisher.id = conf.pubId.trim(); + payload.ext.dm = { + rs: 1, + pubId: conf.pubId, + wp: 'pbjs', + wv: constants.REPO_AND_VERSION, + transactionId: conf.transactionId, + profileid: conf.profId || UNDEFINED, + versionid: conf.verId || DEFAULT_VERSION_ID, + wiid: conf.wiid || UNDEFINED + }; + payload.user = { + gender: _parseSlotParam('gender', conf.gender), + yob: _parseSlotParam('yob', conf.yob), + geo: { + lat: _parseSlotParam('lat', conf.lat), + lon: _parseSlotParam('lon', conf.lon) + } + }; + payload.device.geo = payload.user.geo; + payload.site.page = conf.kadpageurl || payload.site.page; + payload.site.domain = utils.getTopWindowHostName(); + return { + method: 'POST', + url: ENDPOINT, + data: JSON.stringify(payload) + }; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} response A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: (response, request) => { + const bidResponses = []; + try { + if (response.body && response.body.seatbid) { + // Supporting multiple bid responses for same adSize + const referrer = utils.getTopWindowUrl(); + response.body.seatbid.forEach(seatbidder => { + seatbidder.bid && + seatbidder.bid.forEach(bid => { + if (bid.id !== null && bid.ext.summary) { + bid.ext.summary.forEach((summary, index) => { + if (summary.bidder) { + const firstSummary = index === 0; + const newBid = { + requestId: bid.impid, + bidderCode: BIDDER_CODE, + originalBidder: summary.bidder, + pubmaticServerErrorCode: summary.errorCode, + cpm: (parseFloat(summary.bid) || 0).toFixed(2), + width: summary.width, + height: summary.height, + creativeId: firstSummary ? (bid.crid || bid.id) : bid.id, + dealId: firstSummary ? (bid.dealid || UNDEFINED) : UNDEFINED, + currency: CURRENCY, + netRevenue: true, + ttl: 300, + referrer: referrer, + ad: firstSummary ? bid.adm : '' + }; + bidResponses.push(newBid); + } + }); + } + }); + }); + } + } catch (error) { + utils.logError(error); + } + return bidResponses; + }, + + /** + * Register User Sync. + */ + getUserSyncs: (syncOptions, serverResponses) => { + let serverResponse; + let urls = []; + // Todo: Can fire multiple usersync calls if multiple responses for same adsize found + if (serverResponses.length > 0 && serverResponses[0] && serverResponses[0].body) { + serverResponse = serverResponses[0].body; + } + if (serverResponse && serverResponse.ext && serverResponse.ext.bidderstatus && utils.isArray(serverResponse.ext.bidderstatus)) { + serverResponse.ext.bidderstatus.forEach(bidder => { + if (bidder.usersync && bidder.usersync.url) { + if (bidder.usersync.type === IFRAME) { + if (syncOptions.iframeEnabled) { + urls.push({ + type: IFRAME, + url: bidder.usersync.url + }); + } else { + utils.logWarn(bidder.bidder + ': Please enable iframe based user sync.'); + } + } else if (bidder.usersync.type === IMAGE || bidder.usersync.type === REDIRECT) { + if (syncOptions.pixelEnabled) { + urls.push({ + type: IMAGE, + url: bidder.usersync.url + }); + } else { + utils.logWarn(bidder.bidder + ': Please enable pixel based user sync.'); + } + } else { + utils.logWarn(bidder.bidder + ': Please provide valid user sync type.'); + } + } + }); + } + return urls; + } +}; + +registerBidder(spec); diff --git a/modules/pubmaticServerBidAdapter.md b/modules/pubmaticServerBidAdapter.md new file mode 100644 index 00000000000..e6be744a066 --- /dev/null +++ b/modules/pubmaticServerBidAdapter.md @@ -0,0 +1,47 @@ +# Overview + +``` +Module Name: PubMatic-Server Bid Adapter +Module Type: Bidder Adapter +Maintainer: UOEDev@pubmatic.com +``` + +# Description + +Connects to PubMatic exchange for bids. + +PubMaticServer bid adapter supports Banner currently. + +# Sample Ad Unit: For Publishers +``` + +var pbjs = pbjs || {}; + +pbjs.que.push(function() { + + var adUnits = [{ + code: 'test-div', + sizes: [ + [300, 250], + [728, 90] + ], + bids: [{ + bidder: 'pubmaticServer', + params: { + publisherId: '301', // required + adSlot: '/15671365/DMDemo@728x90', // required + profileid: '', // required + divId: '', // required + versionid: '', // optional (Default 0) + + // openRTB params + lat: '40.712775', // optional + lon: '-74.005973', // optional + yob: '1982', // optional + gender: 'M' // optional + } + }] + }]; +}); + +``` diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js index 02c5f890073..0cc8c9e6179 100644 --- a/modules/yieldmoBidAdapter.js +++ b/modules/yieldmoBidAdapter.js @@ -68,7 +68,7 @@ var YieldmoAdapter = function YieldmoAdapter() { var dnt = (navigator.doNotTrack || false).toString(); // true if user enabled dnt (false by default) var _s = document.location.protocol === 'https:' ? 1 : 0; // 1 if page is secure var description = _getPageDescription(); - var title = document.title || ''; // Value of the title from the publisher's page. + var title = document.title || ''; // Value of the title from the publisher's page. var bust = new Date().getTime().toString(); // cache buster var scrd = window.devicePixelRatio || 0; // screen pixel density @@ -87,7 +87,7 @@ var YieldmoAdapter = function YieldmoAdapter() { function _getPageDescription() { if (document.querySelector('meta[name="description"]')) { - return document.querySelector('meta[name="description"]').getAttribute('content'); // Value of the description metadata from the publisher's page. + return document.querySelector('meta[name="description"]').getAttribute('content'); // Value of the description metadata from the publisher's page. } else { return ''; } @@ -101,7 +101,7 @@ var YieldmoAdapter = function YieldmoAdapter() { } } else { // If an incorrect response is returned, register error bids for all placements - // to prevent Prebid waiting till timeout for response + // to prevent Prebid waiting till timeout for response _registerNoResponseBids(); utils.logMessage('No prebid response for placement %%PLACEMENT%%'); diff --git a/package.json b/package.json index 146cb660d84..ed8df9da357 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "gulp-babel": "^6.1.2", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", - "gulp-connect": "^5.0.0", + "gulp-connect": "5.0.0", "gulp-documentation": "^3.2.1", "gulp-eslint": "^4.0.0", "gulp-footer": "^1.0.5", diff --git a/src/utils.js b/src/utils.js index 6dc30a184d2..0a73672a6a2 100644 --- a/src/utils.js +++ b/src/utils.js @@ -178,6 +178,17 @@ exports.getTopWindowUrl = function () { return href; }; +exports.getTopWindowHostName = function () { + let href; + try { + href = this.getTopWindowLocation().hostname; + } catch (e) { + href = ''; + } + + return href; +}; + exports.getTopWindowReferrer = function() { try { return window.top.document.referrer; diff --git a/test/helpers/prebidGlobal.js b/test/helpers/prebidGlobal.js index 0a660b83cbb..fce1bf0fa3b 100644 --- a/test/helpers/prebidGlobal.js +++ b/test/helpers/prebidGlobal.js @@ -1,8 +1,8 @@ -//window.$$PREBID_GLOBAL$$ = (window.$$PREBID_GLOBAL$$ || {}); -//window.$$PREBID_GLOBAL$$.cmd = window.$$PREBID_GLOBAL$$.cmd || []; -//window.$$PREBID_GLOBAL$$.que = window.$$PREBID_GLOBAL$$.que || []; +// window.$$PREBID_GLOBAL$$ = (window.$$PREBID_GLOBAL$$ || {}); +// window.$$PREBID_GLOBAL$$.cmd = window.$$PREBID_GLOBAL$$.cmd || []; +// window.$$PREBID_GLOBAL$$.que = window.$$PREBID_GLOBAL$$.que || []; -window.preBidNameSpace = "pbjs"; +window.preBidNameSpace = 'pbjs'; $$PREBID_GLOBAL$$ = ($$PREBID_GLOBAL$$ || {}); $$PREBID_GLOBAL$$.cmd = $$PREBID_GLOBAL$$.cmd || []; -$$PREBID_GLOBAL$$.que = $$PREBID_GLOBAL$$.que || []; \ No newline at end of file +$$PREBID_GLOBAL$$.que = $$PREBID_GLOBAL$$.que || []; diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js index efa595ecc64..4e9c308d465 100644 --- a/test/spec/modules/aolBidAdapter_spec.js +++ b/test/spec/modules/aolBidAdapter_spec.js @@ -138,8 +138,8 @@ describe('AolAdapter', () => { expect(formattedBidResponse.ad).to.equal( '' + - '' ); }); diff --git a/test/spec/modules/pubmaticServerBidAdapter_spec.js b/test/spec/modules/pubmaticServerBidAdapter_spec.js new file mode 100644 index 00000000000..99b211e9b27 --- /dev/null +++ b/test/spec/modules/pubmaticServerBidAdapter_spec.js @@ -0,0 +1,254 @@ +import {expect} from 'chai'; +import {spec} from 'modules/pubmaticServerBidAdapter'; +import * as utils from 'src/utils'; +const constants = require('src/constants.json'); + +describe('PubMaticServer adapter', () => { + let bidRequests; + let bidResponses; + + beforeEach(() => { + bidRequests = [ + { + bidder: 'pubmaticServer', + params: { + publisherId: '301', + adUnitId: '/15671365/DMDemo', + adUnitIndex: '0', + divId: '/19968336/header-bid-tag-1', + kadfloor: '1.2', + pmzoneid: 'aabc, ddef', + kadpageurl: 'www.publisher.com', + yob: '1986', + gender: 'M', + lat: '12.3', + lon: '23.7', + wiid: '1234567890', + profId: '100', + verId: '200' + }, + placementCode: '/19968336/header-bid-tag-1', + sizes: [[300, 250], [300, 600]], + bidId: '23acc48ad47af5', + requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + bidderRequestId: '1c56ad30b9b8ca8', + transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' + } + ]; + + bidResponses = { + 'body': { + 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', + 'seatbid': [{ + 'bid': [{ + 'id': '74858439-49D7-4169-BA5D-44A046315B2F', + 'impid': '22bddb28db77d', + 'price': 1.3, + 'adm': 'image3.pubmatic.com Layer based creative', + 'h': 250, + 'w': 300, + 'ext': { + 'summary': [{ + 'bidder': 'pubmatic', + 'bid': 1.3, + 'width': 300, + 'height': 250 + }] + } + }] + }] + } + }; + }); + + describe('implementation', () => { + describe('Bid validations', () => { + it('valid bid case', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adUnitId: '/15671365/DMDemo', + adUnitIndex: '0', + divId: '/19968336/header-bid-tag-1', + profId: 1 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + }); + + it('invalid bid case: publisherId not passed', () => { + let validBid = { + bidder: 'pubmatic', + params: { + adUnitId: '/15671365/DMDemo', + adUnitIndex: '0', + divId: '/19968336/header-bid-tag-1' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: publisherId is not string', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: 301, + adUnitId: '/15671365/DMDemo', + adUnitIndex: '0', + divId: '/19968336/header-bid-tag-1' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: adUnitId not passed', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adUnitIndex: '0', + divId: '/19968336/header-bid-tag-1' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: adUnitIndex not passed', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adUnitId: '/15671365/DMDemo', + divId: '/19968336/header-bid-tag-1' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: divId not passed', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adUnitId: '/15671365/DMDemo', + adUnitIndex: '0' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: adUnitId is not string', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adUnitId: 15671365, + adUnitIndex: '0', + divId: '/19968336/header-bid-tag-1' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: adUnitIndex is not string', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adUnitId: '/15671365/DMDemo', + adUnitIndex: 0, + divId: '/19968336/header-bid-tag-1' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: divId is not string', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adUnitId: '/15671365/DMDemo', + adUnitIndex: '0', + divId: 19968336 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + }); + + describe('Request formation', () => { + it('Endpoint checking', () => { + let request = spec.buildRequests(bidRequests); + expect(request.url).to.equal('//ow.pubmatic.com/openrtb/2.4/'); + expect(request.method).to.equal('POST'); + }); + + it('Request params check', () => { + let request = spec.buildRequests(bidRequests); + let data = JSON.parse(request.data); + expect(data.at).to.equal(1); // auction type + expect(data.cur[0]).to.equal('USD'); // currency + expect(data.site.domain).to.be.a('string'); // domain should be set + expect(data.site.page).to.equal(bidRequests[0].params.kadpageurl); // forced pageURL + expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id + expect(data.user.yob).to.equal(parseInt(bidRequests[0].params.yob)); // YOB + expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender + expect(data.device.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.ext.dm.wv).to.equal(constants.REPO_AND_VERSION); // Wrapper Version + expect(data.ext.dm.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.dm.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID + expect(data.ext.dm.profileid).to.equal(bidRequests[0].params.profId); // OpenWrap: Wrapper Profile ID + expect(data.ext.dm.versionid).to.equal(bidRequests[0].params.verId); // OpenWrap: Wrapper Profile Version ID + expect(data.imp[0].id).to.equal(bidRequests[0].bidId); // Prebid bid id is passed as id + expect(data.imp[0].bidfloor).to.equal(parseFloat(bidRequests[0].params.kadfloor)); // kadfloor + expect(data.imp[0].tagid).to.equal(bidRequests[0].params.divId); // tagid + expect(data.imp[0].banner.format[0].w).to.equal(300); // width + expect(data.imp[0].banner.format[0].h).to.equal(250); // height + expect(data.imp[0].banner.format[1].w).to.equal(300); // width + expect(data.imp[0].banner.format[1].h).to.equal(600); // height + expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid + expect(data.imp[0].ext.adunit).to.equal(bidRequests[0].params.adUnitId); // adUnitId + expect(data.imp[0].ext.div).to.equal(bidRequests[0].params.divId); // div + }); + }); + + describe('Response checking', () => { + it('should check for valid response values', () => { + let request = spec.buildRequests(bidRequests); + let response = spec.interpretResponse(bidResponses, request); + expect(response).to.be.an('array').with.length.above(0); + expect(response[0].requestId).to.equal(bidResponses.body.seatbid[0].bid[0].impid); + expect(response[0].cpm).to.equal((bidResponses.body.seatbid[0].bid[0].price).toFixed(2)); + expect(response[0].width).to.equal(bidResponses.body.seatbid[0].bid[0].w); + expect(response[0].height).to.equal(bidResponses.body.seatbid[0].bid[0].h); + if (bidResponses.body.seatbid[0].bid[0].crid) { + expect(response[0].creativeId).to.equal(bidResponses.body.seatbid[0].bid[0].crid); + } else { + expect(response[0].creativeId).to.equal(bidResponses.body.seatbid[0].bid[0].id); + } + expect(response[0].dealId).to.equal(bidResponses.body.seatbid[0].bid[0].dealid); + expect(response[0].currency).to.equal('USD'); + expect(response[0].netRevenue).to.equal(true); + expect(response[0].ttl).to.equal(300); + expect(response[0].referrer).to.include(utils.getTopWindowUrl()); + expect(response[0].ad).to.equal(bidResponses.body.seatbid[0].bid[0].adm); + expect(response[0].originalBidder).to.equal(bidResponses.body.seatbid[0].bid[0].ext.summary[0].bidder); + expect(response[0].bidderCode).to.equal(spec.code); + }); + }); + }); +}); diff --git a/test/spec/modules/tapsenseBidAdapter_spec.js b/test/spec/modules/tapsenseBidAdapter_spec.js index d48fc76bf96..452a1de10ba 100644 --- a/test/spec/modules/tapsenseBidAdapter_spec.js +++ b/test/spec/modules/tapsenseBidAdapter_spec.js @@ -184,11 +184,11 @@ describe('TapSenseAdapter', () => { expect(adloader.loadScript.firstCall.args[0]).to.match( /price_floor=0\.01&/ ); - - //TODO: need to fix this case + + // TODO: need to fix this case expect(adloader.loadScript.firstCall.args[0]).to.match( - //callback=$$PREBID_GLOBAL$$\.tapsense\.callback_with_price_.+&/ - new RegExp('callback='+ preBidNameSpace +'.tapsense.callback_with_price_') + // callback=$$PREBID_GLOBAL$$\.tapsense\.callback_with_price_.+&/ + new RegExp('callback=' + preBidNameSpace + '.tapsense.callback_with_price_') ); }) })