From 9a9bf04734015fd37cc3fd1e85582f0fa006bc85 Mon Sep 17 00:00:00 2001 From: vladi-mmg Date: Tue, 17 Dec 2019 17:21:11 +0200 Subject: [PATCH 1/7] Change publisherId to zoneId Add gdpr Add supply chain Add video media type --- modules/marsmediaBidAdapter.js | 339 ++++++++++++------ modules/marsmediaBidAdapter.md | 47 ++- test/spec/modules/marsmediaBidAdapter_spec.js | 266 +++++++++++++- 3 files changed, 517 insertions(+), 135 deletions(-) diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js index 4cc4563665d..e4befe13e87 100644 --- a/modules/marsmediaBidAdapter.js +++ b/modules/marsmediaBidAdapter.js @@ -1,130 +1,257 @@ +'use strict'; + import * as utils from '../src/utils'; import {registerBidder} from '../src/adapters/bidderFactory'; -const BIDDER_CODE = 'marsmedia'; +import { BANNER, VIDEO } from '../src/mediaTypes'; + +function MarsmediaAdapter() { + this.code = 'marsmedia'; + this.aliases = ['mars']; + this.supportedMediaTypes = [VIDEO, BANNER]; + + let SUPPORTED_VIDEO_PROTOCOLS = [2, 3, 5, 6]; + let SUPPORTED_VIDEO_MIMES = ['video/mp4']; + let SUPPORTED_VIDEO_PLAYBACK_METHODS = [1, 2, 3, 4]; + let SUPPORTED_VIDEO_DELIVERY = [1]; + let SUPPORTED_VIDEO_API = [1, 2, 5]; + let slotsToBids = {}; + let that = this; + let version = '2.1'; + + this.isBidRequestValid = function (bid) { + return !!(bid.params && bid.params.zoneId); + }; + + this.getUserSyncs = function (syncOptions, responses, gdprConsent) { + return []; + }; + + function frameImp(BRs, bidderRequest) { + var impList = []; + var isSecure = (window.location.protocol === 'https:'); + + for (var i = 0; i < BRs.length; i++) { + slotsToBids[BRs[i].adUnitCode] = BRs[i]; + var impObj = {}; + impObj.id = BRs[i].adUnitCode; + impObj.secure = isSecure; -function getDomain() { - if (!utils.inIframe()) { - return window.location.hostname + if (utils.deepAccess(BRs[i], 'mediaTypes.banner') || utils.deepAccess(BRs[i], 'mediaType') === 'banner') { + let banner = frameBanner(BRs[i]); + if (banner) { + impObj.banner = banner; + } + } + if (utils.deepAccess(BRs[i], 'mediaTypes.video') || utils.deepAccess(BRs[i], 'mediaType') === 'video') { + impObj.video = frameVideo(BRs[i]); + } + if (!(impObj.banner || impObj.video)) { + continue; + } + impObj.ext = frameExt(BRs[i]); + impList.push(impObj); + } + return impList; } - let origins = window.document.location.ancestorOrigins - if (origins && origins.length > 0) { - return origins[origins.length - 1] + + function frameSite(bidderRequest) { + var site = { + domain: '', + page: '', + ref: '' + } + if (bidderRequest && bidderRequest.refererInfo) { + var ri = bidderRequest.refererInfo; + site.ref = ri.referer; + site.page = document.URL; + site.domain = window.location.hostname; + } + return site; } -} -export const spec = { - code: BIDDER_CODE, - aliases: ['mars'], - isBidRequestValid: function(bid) { - return (bid.params.publisherID !== null); - }, - buildRequests: function(validBidRequests, bidderRequest) { - try { - let protocol = (window.location.protocol === 'https:'); - const parse = getSize(validBidRequests[0].sizes); - const publisherId = validBidRequests[0].params.publisherID; - const payload = { - id: validBidRequests[0].bidId, - cur: ['USD'], - - language: window.navigator.userLanguage || window.navigator.language, - site: { - id: publisherId, - domain: getDomain(), - page: document.URL, - ref: document.referrer, - publisher: { - id: publisherId, - domain: getDomain() - } - }, - imp: [{ - id: utils.getUniqueIdentifierStr(), - banner: { - w: parse.width, - h: parse.height, - secure: protocol - }, - bidfloor: parseFloat(validBidRequests[0].params.floor) > 0 ? validBidRequests[0].params.floor : 0 - }], - device: { - ua: navigator.userAgent - }, - user: { - id: publisherId - }, - publisher: { - id: publisherId, - domain: getDomain() - } - }; + function frameDevice() { + return { + ua: navigator.userAgent, + ip: '', // Empty Ip string is required, server gets the ip from HTTP header + dnt: utils.getDNT() ? 1 : 0, + } + } - if (bidderRequest && bidderRequest.gdprConsent) { - payload.gdpr = { - applies: bidderRequest.gdprConsent.gdprApplies, - consent: bidderRequest.gdprConsent.consentString - }; - } + function getValidSizeSet(dimensionList) { + let w = parseInt(dimensionList[0]); + let h = parseInt(dimensionList[1]); + // clever check for NaN + if (! (w !== w || h !== h)) { // eslint-disable-line + return [w, h]; + } + return false; + } + function frameBanner(adUnit) { + // adUnit.sizes is scheduled to be deprecated, continue its support but prefer adUnit.mediaTypes.banner + var sizeList = adUnit.sizes; + if (adUnit.mediaTypes && adUnit.mediaTypes.banner) { + sizeList = adUnit.mediaTypes.banner.sizes; + } + var sizeStringList = utils.parseSizesInput(sizeList); + var format = []; + sizeStringList.forEach(function(size) { + if (size) { + var dimensionList = getValidSizeSet(size.split('x')); + if (dimensionList) { + format.push({ + 'w': dimensionList[0], + 'h': dimensionList[1], + }); + } + } + }); + if (format.length) { return { - method: 'POST', - url: 'https://bid306.rtbsrv.com/bidder/?bid=3mhdom', - data: JSON.stringify(payload) + 'format': format }; - } catch (e) { - utils.logError(e, {validBidRequests, bidderRequest}); - } - }, - interpretResponse: function(serverResponse, bidRequest) { - const bidResponses = []; - let res = serverResponse.body; - if (!res) { - return [] - } - - for (let x = 0; x < res.seatbid.length; x++) { - var bidAd = res.seatbid[x].bid[0]; - - bidResponses.push({ - requestId: res.id, - cpm: Number(bidAd.price), - width: bidAd.w, - height: bidAd.h, - ad: bidAd.adm, - ttl: 60, - creativeId: bidAd.cid, - netRevenue: true, - currency: 'USD' - }) } - return bidResponses; - }, - getUserSyncs: function(syncOptions, serverResponses) { - return []; + return false; } -}; -function getSize(requestSizes) { - const parsed = {}; - const size = utils.parseSizesInput(requestSizes)[0]; + function frameVideo(bid) { + var size = []; + if (utils.deepAccess(bid, 'mediaTypes.video.playerSize')) { + var dimensionSet = bid.mediaTypes.video.playerSize; + if (utils.isArray(bid.mediaTypes.video.playerSize[0])) { + dimensionSet = bid.mediaTypes.video.playerSize[0]; + } + var validSize = getValidSizeSet(dimensionSet) + if (validSize) { + size = validSize; + } + } + return { + mimes: utils.deepAccess(bid, 'mediaTypes.video.mimes') || SUPPORTED_VIDEO_MIMES, + protocols: utils.deepAccess(bid, 'mediaTypes.video.protocols') || SUPPORTED_VIDEO_PROTOCOLS, + w: size[0], + h: size[1], + startdelay: utils.deepAccess(bid, 'mediaTypes.video.startdelay') || 0, + skip: utils.deepAccess(bid, 'mediaTypes.video.skip') || 0, + playbackmethod: utils.deepAccess(bid, 'mediaTypes.video.playbackmethod') || SUPPORTED_VIDEO_PLAYBACK_METHODS, + delivery: utils.deepAccess(bid, 'mediaTypes.video.delivery') || SUPPORTED_VIDEO_DELIVERY, + api: utils.deepAccess(bid, 'mediaTypes.video.api') || SUPPORTED_VIDEO_API, + } + } - if (typeof size !== 'string') { - return parsed; + function frameExt(bid) { + return { + bidder: { + zoneId: bid.params['zoneId'] + } + } } - const parsedSize = size.toUpperCase().split('X'); - const width = parseInt(parsedSize[0], 10); - if (width) { - parsed.width = width; + function frameBid(BRs, bidderRequest) { + let bid = { + id: BRs[0].bidderRequestId, + imp: frameImp(BRs, bidderRequest), + site: frameSite(bidderRequest), + device: frameDevice(), + user: { + ext: { + consent: utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies') ? bidderRequest.gdprConsent.consentString : '' + } + }, + at: 1, + tmax: 1000, + regs: { + ext: { + gdpr: utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies') ? Boolean(bidderRequest.gdprConsent.gdprApplies & 1) : false + } + } + }; + if (BRs[0].schain) { + bid.source = { + 'ext': { + 'schain': BRs[0].schain + } + } + } + return bid; } - const height = parseInt(parsedSize[1], 10); - if (height) { - parsed.height = height; + function getFirstParam(key, validBidRequests) { + for (let i = 0; i < validBidRequests.length; i++) { + if (validBidRequests[i].params && validBidRequests[i].params[key]) { + return validBidRequests[i].params[key]; + } + } } - return parsed; + this.buildRequests = function (BRs, bidderRequest) { + let fallbackZoneId = getFirstParam('zoneId', BRs); + if (fallbackZoneId === undefined || BRs.length < 1) { + return []; + } + + var uri = 'https://bid306.rtbsrv.com/bidder/?bid=3mhdom&zoneId=' + fallbackZoneId; + + var fat = /(^v|(\.0)+$)/gi; + var prebidVersion = '$prebid.version$'; + uri += '&hbv=' + prebidVersion.replace(fat, '') + ',' + version.replace(fat, ''); + + var bidRequest = frameBid(BRs, bidderRequest); + if (!bidRequest.imp.length) { + return {}; + } + + return { + method: 'POST', + url: uri, + data: JSON.stringify(bidRequest) + }; + }; + + this.interpretResponse = function (serverResponse) { + let responses = serverResponse.body || []; + let bids = []; + let i = 0; + + if (responses.seatbid) { + let temp = []; + for (i = 0; i < responses.seatbid.length; i++) { + for (let j = 0; j < responses.seatbid[i].bid.length; j++) { + temp.push(responses.seatbid[i].bid[j]); + } + } + responses = temp; + } + + for (i = 0; i < responses.length; i++) { + let bid = responses[i]; + let bidRequest = slotsToBids[bid.impid]; + let bidResponse = { + requestId: bidRequest.id, + bidderCode: that.code, + cpm: parseFloat(bid.price), + width: bid.w, + height: bid.h, + creativeId: bid.crid, + currency: 'USD', + netRevenue: true, + ttl: 350 + }; + + if (bidRequest.mediaTypes && bidRequest.mediaTypes.video) { + bidResponse.vastUrl = bid.nurl; + bidResponse.mediaType = 'video'; + bidResponse.ttl = 600; + } else { + bidResponse.ad = bid.adm; + } + bids.push(bidResponse); + } + + return bids; + }; } +export const spec = new MarsmediaAdapter(); registerBidder(spec); diff --git a/modules/marsmediaBidAdapter.md b/modules/marsmediaBidAdapter.md index fee962f9173..47116c83838 100644 --- a/modules/marsmediaBidAdapter.md +++ b/modules/marsmediaBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Mars Media Group (mars.media) Bidder Adapter Module Type: Bidder Adapter -Maintainer: vladi@mars.media +Maintainer: prebid@mars.media ``` # Description @@ -14,19 +14,34 @@ Prebid adapter for Mars Media Group RTB. Requires approval and account setup. ## Web ``` - var adUnits = [ - { - code: 'test-div', - sizes: [[300, 250]], - bids: [ - { - bidder: "marsmedia", - params: { - publisherID: 9999, - floor: 0.11 - } - } - ] - } - ]; + var adUnits = [{ + code: 'banner-ad-div', + mediaTypes: { + banner: { + sizes: [ + [300, 200] // banner sizes + ], + } + }, + bids: [{ + bidder: 'marsmedia', + params: { + zoneId: 9999 + } + }] + }, { + code: 'video-ad-player', + mediaTypes: { + video: { + context: 'instream', // or 'outstream' + playerSize: [640, 480] // video player size + } + }, + bids: [{ + bidder: 'marsmedia', + params: { + zoneId: 9999 + } + }] + }]; ``` \ No newline at end of file diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js index a58857e0f3f..e08832b9dc0 100644 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -1,17 +1,22 @@ import { expect } from 'chai' import { spec, _getPlatform } from 'modules/marsmediaBidAdapter' -import { newBidder } from 'src/adapters/bidderFactory' +// import { newBidder } from 'src/adapters/bidderFactory' describe('marsmediaBidAdapter', function () { - const adapter = newBidder(spec) + // const adapter = newBidder(spec) let bidRequest = { - 'bidId': '123', - 'sizes': [[ 300, 250 ]], + 'bidder': 'marsmedia', 'params': { - 'publisherID': 9999, - 'floor': 0.1 - } + 'zoneId': 9999 + }, + 'adUnitCode': 'adunit-code', + 'mediaTypes': { + 'banner': { + sizes: [[300, 250]] + } + }, + 'bidId': '37386aade21a71' } describe('codes', function () { @@ -29,7 +34,7 @@ describe('marsmediaBidAdapter', function () { }) it('should return false if any parameter missing', function () { - expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { publisherID: null } }))).to.be.false + expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { zoneId: null } }))).to.be.false }) }) @@ -50,9 +55,9 @@ describe('marsmediaBidAdapter', function () { expect(rdata.imp.length).to.equal(1) }) - it('should include all publisher params', function () { + it('should include all zoneId params', function () { let r = rdata.imp[0] - expect(r.publisherID !== null).to.be.true + expect(r.zoneId !== null).to.be.true }) }) @@ -66,7 +71,7 @@ describe('marsmediaBidAdapter', function () { 'bid': [{ 'id': '1', 'impid': '1', - 'cid': '1', + 'cid': '1', 'price': 0.1, 'nurl': '', 'adm': '', @@ -78,7 +83,7 @@ describe('marsmediaBidAdapter', function () { }; }); - it('should get the correct bid response', function () { + /* it('should get the correct bid response', function () { let expectedResponse = [{ 'requestId': '37386aade21a71', 'cpm': 0.1, @@ -93,7 +98,7 @@ describe('marsmediaBidAdapter', function () { let result = spec.interpretResponse(response); expect(result[0]).to.deep.equal(expectedResponse[0]); - }); + }); */ it('handles empty bid response', function () { let response = { @@ -120,3 +125,238 @@ describe('marsmediaBidAdapter', function () { }) */ }) }) + +/* + +import { expect } from 'chai' +import { spec } from 'modules/marsmediaBidAdapter' +import * as utils from 'src/utils'; + +describe('Marsmedia adapter', function () { + const bid1_zone1 = { + bidder: 'marsmedia', + params: {zoneId: 1}, + adUnitCode: 'ad-unit-1', + bidId: 'Bid_01', + bidderRequestId: 'req-001', + auctionId: 'auc-001', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + } + }, bid_video = { + bidder: 'marsmedia', + transactionId: '866394b8-5d37-4d49-803e-f1bdb595f73e', + bidId: 'Bid_Video', + bidderRequestId: '18b2a61ea5d9a7', + auctionId: 'de45acf1-9109-4e52-8013-f2b7cf5f6766', + params: { + zoneId: 1 + }, + mediaTypes: { + video: { + context: 'instream', + playerSize: [[640, 480]] + } + }, + adUnitCode: 'ad-unit-1' + }; + + const bidResponse1 = { + id: 'bid1', + seatbid: [{ + bid: [{ + id: '1', + impid: 'Bid_01', + crid: '100_001', + price: 3.01, + adm: '', + w: 300, + h: 250 + }] + }], + cur: 'USD' + }, videoBidResponse = { + id: '47ce4badcf7482', + seatbid: [{ + bid: [{ + id: 'sZSYq5zYMxo_0', + impid: 'Bid_Video', + crid: '100_003', + price: 0.00145, + adid: '158801', + adm: '', + cid: '16855' + }] + }], + cur: 'USD' + }; + + function buildBidderRequest(url = 'https://example.com/index.html', params = {}) { + return Object.assign({}, params, {refererInfo: {referer: url, reachedTop: true}, timeout: 3000}); + } + const DEFAULT_BIDDER_REQUEST = buildBidderRequest(); + + function buildRequest(bidRequests, bidderRequest = DEFAULT_BIDDER_REQUEST, dnt = true) { + let dntmock = sinon.stub(utils, 'getDNT').callsFake(() => dnt); + let pbRequests = spec.buildRequests(bidRequests, bidderRequest); + dntmock.restore(); + let rtbRequests = pbRequests.map(r => JSON.parse(r.data)); + return [pbRequests, rtbRequests]; + } + + describe('isBidRequestValid', function () { + it('should return true if all params present', function () { + expect(spec.isBidRequestValid(bid1_zone1)).to.be.true + }) + + it('should return false if any parameter missing', function () { + expect(spec.isBidRequestValid(Object.assign(bid1_zone1, { params: { zoneId: null } }))).to.be.false + }) + }) + + describe('banner request building', function () { + let bidRequest, bidRequests, _; + before(function () { + [_, bidRequests] = buildRequest([bid1_zone1]); + bidRequest = bidRequests[0]; + }); + + it('should be a first-price auction', function () { + expect(bidRequest).to.have.property('at', 1); + }); + + it('should have banner object', function () { + expect(bidRequest.imp[0]).to.have.property('banner'); + }); + + it('should have id', function () { + expect(bidRequest.imp[0]).to.have.property('id'); + expect(bidRequest.imp[0].id).to.be.eql('Bid_01'); + }); + + it('should have w/h', function () { + expect(bidRequest.imp[0].banner).to.have.property('format'); + expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}]); + }); + + it('should respect secure connection', function () { + expect(bidRequest.imp[0]).to.have.property('secure', 1); + }); + + it('should have tagid', function () { + expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); + }); + + it('should create proper site block', function () { + expect(bidRequest.site).to.have.property('domain', 'example.com'); + expect(bidRequest.site).to.have.property('page', 'https://example.com/index.html'); + }); + + it('should fill device with caller macro', function () { + expect(bidRequest).to.have.property('device'); + expect(bidRequest.device).to.have.property('ip', 'caller'); + expect(bidRequest.device).to.have.property('ua', 'caller'); + expect(bidRequest.device).to.have.property('dnt', 1); + }); + + it('shouldn\'t contain gdpr-related information for default request', function () { + let [_, bidRequests] = buildRequest([bid1_zone1]); + expect(bidRequests[0]).to.not.have.property('regs'); + expect(bidRequests[0]).to.not.have.property('user'); + }); + + it('should contain gdpr-related information if consent is configured', function () { + let [_, bidRequests] = buildRequest([bid1_zone1], + buildBidderRequest('https://example.com/index.html', + {gdprConsent: {gdprApplies: true, consentString: 'test-consent-string', vendorData: {}}})); + let bidRequest = bidRequests[0]; + expect(bidRequest).to.have.property('regs'); + expect(bidRequest.regs.ext).to.be.eql({'gdpr': 1}); + expect(bidRequest).to.have.property('user'); + expect(bidRequest.user.ext).to.be.eql({'consent': 'test-consent-string'}); + }); + + it('should\'t contain consent string if gdpr isn\'t applied', function () { + let [_, bidRequests] = buildRequest([bid1_zone1], buildBidderRequest('https://example.com/index.html', {gdprConsent: {gdprApplies: false}})); + let bidRequest = bidRequests[0]; + expect(bidRequest).to.have.property('regs'); + expect(bidRequest.regs.ext).to.be.eql({'gdpr': 0}); + expect(bidRequest).to.not.have.property('user'); + }); + + it('should\'t pass dnt if state is unknown', function () { + let [_, bidRequests] = buildRequest([bid1_zone1], DEFAULT_BIDDER_REQUEST, false); + expect(bidRequests[0].device).to.not.have.property('dnt'); + }); + + it('should forward default bidder timeout', function() { + let [_, bidRequests] = buildRequest([bid1_zone1], DEFAULT_BIDDER_REQUEST); + let bidRequest = bidRequests[0]; + expect(bidRequests[0]).to.have.property('tmax', 3000); + }); + }); + + describe('video request building', function () { + let _, bidRequests; + before(function () { + [_, bidRequests] = buildRequest([bid_video]); + }); + + it('should have video object', function () { + expect(bidRequests[0].imp[0]).to.have.property('video'); + }); + + it('should have h/w', function () { + expect(bidRequests[0].imp[0].video).to.have.property('w', 640); + expect(bidRequests[0].imp[0].video).to.have.property('h', 480); + }); + + it('should have tagid', function () { + expect(bidRequests[0].imp[0]).to.have.property('tagid', 'ad-unit-1'); + }); + }); + + describe('responses processing', function () { + it('should return fully-initialized banner bid-response', function () { + let [pbRequests, _] = buildRequest([bid1_zone1]); + let resp = spec.interpretResponse({body: bidResponse1}, pbRequests[0])[0]; + expect(resp).to.have.property('requestId', 'Bid_01'); + expect(resp).to.have.property('cpm', 3.01); + expect(resp).to.have.property('width', 300); + expect(resp).to.have.property('height', 250); + expect(resp).to.have.property('creativeId', '100_001'); + expect(resp).to.have.property('mediaType', 'banner'); + expect(resp).to.have.property('ad'); + expect(resp.ad).to.have.string(''); + }); + + it('should return fully-initialized video bid-response', function () { + let [pbRequests, _] = buildRequest([bid_video]); + let resp = spec.interpretResponse({body: videoBidResponse}, pbRequests[0])[0]; + expect(resp).to.have.property('requestId', 'Bid_Video'); + expect(resp.mediaType).to.equal('video'); + expect(resp.cpm).to.equal(0.00145); + expect(resp.width).to.equal(640); + expect(resp.height).to.equal(480); + expect(resp).to.have.property('ad'); + expect(resp.ad).to.have.string(''); + }); + }); + + describe('adapter configuration', () => { + it('should return a bidder code of marsmedia', function () { + expect(spec.code).to.equal('marsmedia') + }) + it('should alias mars', function () { + expect(spec.aliases.length > 0 && spec.aliases[0] === 'mars').to.be.true + }) + }); + + describe('getUserSyncs', function () { + + }) +}); + +*/ From 07f5f4982fa4b4553c1845225d7a3a38fca62e8f Mon Sep 17 00:00:00 2001 From: vladi-mmg Date: Tue, 17 Dec 2019 17:32:16 +0200 Subject: [PATCH 2/7] Remove comments --- test/spec/modules/marsmediaBidAdapter_spec.js | 252 ------------------ 1 file changed, 252 deletions(-) diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js index e08832b9dc0..ea60678c818 100644 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -83,23 +83,6 @@ describe('marsmediaBidAdapter', function () { }; }); - /* it('should get the correct bid response', function () { - let expectedResponse = [{ - 'requestId': '37386aade21a71', - 'cpm': 0.1, - 'width': 320, - 'height': 250, - 'creativeId': '1', - 'currency': 'USD', - 'netRevenue': true, - 'ad': ``, - 'ttl': 60 - }]; - - let result = spec.interpretResponse(response); - expect(result[0]).to.deep.equal(expectedResponse[0]); - }); */ - it('handles empty bid response', function () { let response = { body: '' @@ -125,238 +108,3 @@ describe('marsmediaBidAdapter', function () { }) */ }) }) - -/* - -import { expect } from 'chai' -import { spec } from 'modules/marsmediaBidAdapter' -import * as utils from 'src/utils'; - -describe('Marsmedia adapter', function () { - const bid1_zone1 = { - bidder: 'marsmedia', - params: {zoneId: 1}, - adUnitCode: 'ad-unit-1', - bidId: 'Bid_01', - bidderRequestId: 'req-001', - auctionId: 'auc-001', - mediaTypes: { - banner: { - sizes: [[300, 250]] - } - } - }, bid_video = { - bidder: 'marsmedia', - transactionId: '866394b8-5d37-4d49-803e-f1bdb595f73e', - bidId: 'Bid_Video', - bidderRequestId: '18b2a61ea5d9a7', - auctionId: 'de45acf1-9109-4e52-8013-f2b7cf5f6766', - params: { - zoneId: 1 - }, - mediaTypes: { - video: { - context: 'instream', - playerSize: [[640, 480]] - } - }, - adUnitCode: 'ad-unit-1' - }; - - const bidResponse1 = { - id: 'bid1', - seatbid: [{ - bid: [{ - id: '1', - impid: 'Bid_01', - crid: '100_001', - price: 3.01, - adm: '', - w: 300, - h: 250 - }] - }], - cur: 'USD' - }, videoBidResponse = { - id: '47ce4badcf7482', - seatbid: [{ - bid: [{ - id: 'sZSYq5zYMxo_0', - impid: 'Bid_Video', - crid: '100_003', - price: 0.00145, - adid: '158801', - adm: '', - cid: '16855' - }] - }], - cur: 'USD' - }; - - function buildBidderRequest(url = 'https://example.com/index.html', params = {}) { - return Object.assign({}, params, {refererInfo: {referer: url, reachedTop: true}, timeout: 3000}); - } - const DEFAULT_BIDDER_REQUEST = buildBidderRequest(); - - function buildRequest(bidRequests, bidderRequest = DEFAULT_BIDDER_REQUEST, dnt = true) { - let dntmock = sinon.stub(utils, 'getDNT').callsFake(() => dnt); - let pbRequests = spec.buildRequests(bidRequests, bidderRequest); - dntmock.restore(); - let rtbRequests = pbRequests.map(r => JSON.parse(r.data)); - return [pbRequests, rtbRequests]; - } - - describe('isBidRequestValid', function () { - it('should return true if all params present', function () { - expect(spec.isBidRequestValid(bid1_zone1)).to.be.true - }) - - it('should return false if any parameter missing', function () { - expect(spec.isBidRequestValid(Object.assign(bid1_zone1, { params: { zoneId: null } }))).to.be.false - }) - }) - - describe('banner request building', function () { - let bidRequest, bidRequests, _; - before(function () { - [_, bidRequests] = buildRequest([bid1_zone1]); - bidRequest = bidRequests[0]; - }); - - it('should be a first-price auction', function () { - expect(bidRequest).to.have.property('at', 1); - }); - - it('should have banner object', function () { - expect(bidRequest.imp[0]).to.have.property('banner'); - }); - - it('should have id', function () { - expect(bidRequest.imp[0]).to.have.property('id'); - expect(bidRequest.imp[0].id).to.be.eql('Bid_01'); - }); - - it('should have w/h', function () { - expect(bidRequest.imp[0].banner).to.have.property('format'); - expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}]); - }); - - it('should respect secure connection', function () { - expect(bidRequest.imp[0]).to.have.property('secure', 1); - }); - - it('should have tagid', function () { - expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); - }); - - it('should create proper site block', function () { - expect(bidRequest.site).to.have.property('domain', 'example.com'); - expect(bidRequest.site).to.have.property('page', 'https://example.com/index.html'); - }); - - it('should fill device with caller macro', function () { - expect(bidRequest).to.have.property('device'); - expect(bidRequest.device).to.have.property('ip', 'caller'); - expect(bidRequest.device).to.have.property('ua', 'caller'); - expect(bidRequest.device).to.have.property('dnt', 1); - }); - - it('shouldn\'t contain gdpr-related information for default request', function () { - let [_, bidRequests] = buildRequest([bid1_zone1]); - expect(bidRequests[0]).to.not.have.property('regs'); - expect(bidRequests[0]).to.not.have.property('user'); - }); - - it('should contain gdpr-related information if consent is configured', function () { - let [_, bidRequests] = buildRequest([bid1_zone1], - buildBidderRequest('https://example.com/index.html', - {gdprConsent: {gdprApplies: true, consentString: 'test-consent-string', vendorData: {}}})); - let bidRequest = bidRequests[0]; - expect(bidRequest).to.have.property('regs'); - expect(bidRequest.regs.ext).to.be.eql({'gdpr': 1}); - expect(bidRequest).to.have.property('user'); - expect(bidRequest.user.ext).to.be.eql({'consent': 'test-consent-string'}); - }); - - it('should\'t contain consent string if gdpr isn\'t applied', function () { - let [_, bidRequests] = buildRequest([bid1_zone1], buildBidderRequest('https://example.com/index.html', {gdprConsent: {gdprApplies: false}})); - let bidRequest = bidRequests[0]; - expect(bidRequest).to.have.property('regs'); - expect(bidRequest.regs.ext).to.be.eql({'gdpr': 0}); - expect(bidRequest).to.not.have.property('user'); - }); - - it('should\'t pass dnt if state is unknown', function () { - let [_, bidRequests] = buildRequest([bid1_zone1], DEFAULT_BIDDER_REQUEST, false); - expect(bidRequests[0].device).to.not.have.property('dnt'); - }); - - it('should forward default bidder timeout', function() { - let [_, bidRequests] = buildRequest([bid1_zone1], DEFAULT_BIDDER_REQUEST); - let bidRequest = bidRequests[0]; - expect(bidRequests[0]).to.have.property('tmax', 3000); - }); - }); - - describe('video request building', function () { - let _, bidRequests; - before(function () { - [_, bidRequests] = buildRequest([bid_video]); - }); - - it('should have video object', function () { - expect(bidRequests[0].imp[0]).to.have.property('video'); - }); - - it('should have h/w', function () { - expect(bidRequests[0].imp[0].video).to.have.property('w', 640); - expect(bidRequests[0].imp[0].video).to.have.property('h', 480); - }); - - it('should have tagid', function () { - expect(bidRequests[0].imp[0]).to.have.property('tagid', 'ad-unit-1'); - }); - }); - - describe('responses processing', function () { - it('should return fully-initialized banner bid-response', function () { - let [pbRequests, _] = buildRequest([bid1_zone1]); - let resp = spec.interpretResponse({body: bidResponse1}, pbRequests[0])[0]; - expect(resp).to.have.property('requestId', 'Bid_01'); - expect(resp).to.have.property('cpm', 3.01); - expect(resp).to.have.property('width', 300); - expect(resp).to.have.property('height', 250); - expect(resp).to.have.property('creativeId', '100_001'); - expect(resp).to.have.property('mediaType', 'banner'); - expect(resp).to.have.property('ad'); - expect(resp.ad).to.have.string(''); - }); - - it('should return fully-initialized video bid-response', function () { - let [pbRequests, _] = buildRequest([bid_video]); - let resp = spec.interpretResponse({body: videoBidResponse}, pbRequests[0])[0]; - expect(resp).to.have.property('requestId', 'Bid_Video'); - expect(resp.mediaType).to.equal('video'); - expect(resp.cpm).to.equal(0.00145); - expect(resp.width).to.equal(640); - expect(resp.height).to.equal(480); - expect(resp).to.have.property('ad'); - expect(resp.ad).to.have.string(''); - }); - }); - - describe('adapter configuration', () => { - it('should return a bidder code of marsmedia', function () { - expect(spec.code).to.equal('marsmedia') - }) - it('should alias mars', function () { - expect(spec.aliases.length > 0 && spec.aliases[0] === 'mars').to.be.true - }) - }); - - describe('getUserSyncs', function () { - - }) -}); - -*/ From b73b7e429ffef7d00cd25b34cef45eba24230694 Mon Sep 17 00:00:00 2001 From: vladi-mmg Date: Thu, 19 Dec 2019 18:27:30 +0200 Subject: [PATCH 3/7] Fix unit test coverage --- modules/marsmediaBidAdapter.js | 22 +- test/spec/modules/marsmediaBidAdapter_spec.js | 662 +++++++++++++++--- 2 files changed, 580 insertions(+), 104 deletions(-) diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js index e4befe13e87..87b6eb5e660 100644 --- a/modules/marsmediaBidAdapter.js +++ b/modules/marsmediaBidAdapter.js @@ -28,8 +28,13 @@ function MarsmediaAdapter() { function frameImp(BRs, bidderRequest) { var impList = []; - var isSecure = (window.location.protocol === 'https:'); - + var isSecure = 0; + if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.stack.length) { + // clever trick to get the protocol + var el = document.createElement('a'); + el.href = bidderRequest.refererInfo.stack[0]; + isSecure = (el.protocol == 'https:') ? 1 : 0; + } for (var i = 0; i < BRs.length; i++) { slotsToBids[BRs[i].adUnitCode] = BRs[i]; var impObj = {}; @@ -63,8 +68,15 @@ function MarsmediaAdapter() { if (bidderRequest && bidderRequest.refererInfo) { var ri = bidderRequest.refererInfo; site.ref = ri.referer; - site.page = document.URL; - site.domain = window.location.hostname; + + if (ri.stack.length) { + site.page = ri.stack[ri.stack.length - 1]; + + // clever trick to get the domain + var el = document.createElement('a'); + el.href = ri.stack[0]; + site.domain = el.hostname; + } } return site; } @@ -240,7 +252,7 @@ function MarsmediaAdapter() { }; if (bidRequest.mediaTypes && bidRequest.mediaTypes.video) { - bidResponse.vastUrl = bid.nurl; + bidResponse.vastUrl = bid.adm; bidResponse.mediaType = 'video'; bidResponse.ttl = 600; } else { diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js index ea60678c818..72329330713 100644 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -1,110 +1,574 @@ -import { expect } from 'chai' -import { spec, _getPlatform } from 'modules/marsmediaBidAdapter' -// import { newBidder } from 'src/adapters/bidderFactory' - -describe('marsmediaBidAdapter', function () { - // const adapter = newBidder(spec) - - let bidRequest = { - 'bidder': 'marsmedia', - 'params': { - 'zoneId': 9999 - }, - 'adUnitCode': 'adunit-code', - 'mediaTypes': { - 'banner': { - sizes: [[300, 250]] +import {spec} from '../../../modules/marsmediaBidAdapter'; +import * as utils from '../../../src/utils'; +import * as sinon from 'sinon'; + +var r1adapter = spec; + +describe('marsmedia adapter tests', function () { + beforeEach(function() { + this.defaultBidderRequest = { + 'refererInfo': { + 'referer': 'Reference Page', + 'stack': [ + 'aodomain.dvl', + 'page.dvl' + ] } - }, - 'bidId': '37386aade21a71' - } - - describe('codes', function () { - it('should return a bidder code of marsmedia', function () { - expect(spec.code).to.equal('marsmedia') - }) - it('should alias mars', function () { - expect(spec.aliases.length > 0 && spec.aliases[0] === 'mars').to.be.true - }) - }) + }; + }); - describe('isBidRequestValid', function () { - it('should return true if all params present', function () { - expect(spec.isBidRequestValid(bidRequest)).to.be.true - }) - - it('should return false if any parameter missing', function () { - expect(spec.isBidRequestValid(Object.assign(bidRequest, { params: { zoneId: null } }))).to.be.false - }) - }) - - describe('buildRequests', function () { - let req = spec.buildRequests([ bidRequest ], { refererInfo: { } }) - let rdata - - it('should return request object', function () { - expect(req).to.not.be.null - }) - - it('should build request data', function () { - expect(req.data).to.not.be.null - }) - - it('should include one request', function () { - rdata = JSON.parse(req.data) - expect(rdata.imp.length).to.equal(1) - }) - - it('should include all zoneId params', function () { - let r = rdata.imp[0] - expect(r.zoneId !== null).to.be.true - }) - }) - - describe('interpretResponse', function () { - let response; - beforeEach(function () { - response = { - body: { - 'id': '37386aade21a71', - 'seatbid': [{ - 'bid': [{ - 'id': '1', - 'impid': '1', - 'cid': '1', - 'price': 0.1, - 'nurl': '', - 'adm': '', - 'w': 320, - 'h': 250 - }] - }] + describe('Verify 1.0 POST Banner Bid Request', function () { + it('buildRequests works', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + expect(bidRequest.url).to.have.string('https://bid306.rtbsrv.com/bidder/?bid=3mhdom&zoneId=9999&hbv='); + expect(bidRequest.method).to.equal('POST'); + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.site).to.not.equal(null); + expect(openrtbRequest.site.ref).to.equal('Reference Page'); + expect(openrtbRequest.device).to.not.equal(null); + expect(openrtbRequest.device.ua).to.equal(navigator.userAgent); + expect(openrtbRequest.device.dnt).to.equal(0); + expect(openrtbRequest.imp[0].banner).to.not.equal(null); + expect(openrtbRequest.imp[0].banner.format[0].w).to.equal(300); + expect(openrtbRequest.imp[0].banner.format[0].h).to.equal(250); + expect(openrtbRequest.imp[0].ext.bidder.zoneId).to.equal(9999); + }); + + it('interpretResponse works', function() { + var bidList = { + 'body': [ + { + 'impid': 'div-gpt-ad-1438287399331-0', + 'w': 300, + 'h': 250, + 'adm': '
My Compelling Ad
', + 'price': 1, + 'crid': 'cr-cfy24' + } + ] }; + + var bannerBids = r1adapter.interpretResponse(bidList); + + expect(bannerBids.length).to.equal(1); + const bid = bannerBids[0]; + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.creativeId).to.equal('cr-cfy24'); + expect(bid.currency).to.equal('USD'); + expect(bid.netRevenue).to.equal(true); + expect(bid.cpm).to.equal(1.0); + expect(bid.ttl).to.equal(350); }); + }); + + describe('Verify POST Video Bid Request', function() { + it('buildRequests works', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'video': { + 'playerSize': [640, 480], + 'context': 'instream' + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'sizes': [ + [300, 250] + ], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; - it('handles empty bid response', function () { - let response = { - body: '' + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + expect(bidRequest.url).to.have.string('https://bid306.rtbsrv.com/bidder/?bid=3mhdom&zoneId=9999&hbv='); + expect(bidRequest.method).to.equal('POST'); + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.site).to.not.equal(null); + expect(openrtbRequest.device).to.not.equal(null); + expect(openrtbRequest.device.ua).to.equal(navigator.userAgent); + expect(openrtbRequest.device).to.have.property('dnt'); + expect(openrtbRequest.imp[0].video).to.not.equal(null); + expect(openrtbRequest.imp[0].video.w).to.equal(640); + expect(openrtbRequest.imp[0].video.h).to.equal(480); + expect(openrtbRequest.imp[0].video.mimes[0]).to.equal('video/mp4'); + expect(openrtbRequest.imp[0].video.protocols).to.eql([2, 3, 5, 6]); + expect(openrtbRequest.imp[0].video.startdelay).to.equal(0); + expect(openrtbRequest.imp[0].video.skip).to.equal(0); + expect(openrtbRequest.imp[0].video.playbackmethod).to.eql([1, 2, 3, 4]); + expect(openrtbRequest.imp[0].video.delivery[0]).to.equal(1); + expect(openrtbRequest.imp[0].video.api).to.eql([1, 2, 5]); + }); + + it('interpretResponse works', function() { + var bidList = { + 'body': [ + { + 'impid': 'div-gpt-ad-1438287399331-1', + 'price': 1, + 'adm': 'https://example.com/', + 'adomain': [ + 'test.com' + ], + 'cid': '467415', + 'crid': 'cr-vid', + 'w': 800, + 'h': 600 + } + ] + }; + + var videoBids = r1adapter.interpretResponse(bidList); + + expect(videoBids.length).to.equal(1); + const bid = videoBids[0]; + expect(bid.width).to.equal(800); + expect(bid.height).to.equal(600); + expect(bid.vastUrl).to.equal('https://example.com/'); + expect(bid.mediaType).to.equal('video'); + expect(bid.creativeId).to.equal('cr-vid'); + expect(bid.currency).to.equal('USD'); + expect(bid.netRevenue).to.equal(true); + expect(bid.cpm).to.equal(1.0); + expect(bid.ttl).to.equal(600); + }); + }); + + describe('misc buildRequests', function() { + it('should send GDPR Consent data to Marsmedia tag', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-3', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var consentString = 'testConsentString'; + var gdprBidderRequest = this.defaultBidderRequest; + gdprBidderRequest.gdprConsent = { + 'gdprApplies': true, + 'consentString': consentString }; - let result = spec.interpretResponse(response); - expect(result.length).to.equal(0); + + var bidRequest = r1adapter.buildRequests(bidRequestList, gdprBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.user.ext.consent).to.equal(consentString); + expect(openrtbRequest.regs.ext.gdpr).to.equal(true); + }); + + it('prefer 2.0 sizes', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 600]] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].banner.format[0].w).to.equal(300); + expect(openrtbRequest.imp[0].banner.format[0].h).to.equal(600); + }); + + it('does not return request for invalid banner size configuration', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300]] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + expect(bidRequest.method).to.be.undefined; + }); + + it('does not return request for missing banner size configuration', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'banner': {} + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + expect(bidRequest.method).to.be.undefined; + }); + + it('reject bad sizes', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'banner': {'sizes': [['400', '500'], ['4n0', '5g0']]} + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].banner.format.length).to.equal(1); + }); + + it('dnt is correctly set to 1', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 600]] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var dntStub = sinon.stub(utils, 'getDNT').returns(1); + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + dntStub.restore(); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.device.dnt).to.equal(1); + }); + + it('supports string video sizes', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'video': { + 'context': 'instream', + 'playerSize': ['600', '300'] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].video.w).to.equal(600); + expect(openrtbRequest.imp[0].video.h).to.equal(300); + }); + + it('rejects bad video sizes', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'video': { + 'context': 'instream', + 'playerSize': ['badWidth', 'badHeight'] + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].video.w).to.be.undefined; + expect(openrtbRequest.imp[0].video.h).to.be.undefined; + }); + + it('supports missing video size', function () { + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'video': { + 'context': 'instream' + } + }, + 'adUnitCode': 'div-gpt-ad-1438287399331-1', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + + const openrtbRequest = JSON.parse(bidRequest.data); + expect(openrtbRequest.imp[0].video.w).to.be.undefined; + expect(openrtbRequest.imp[0].video.h).to.be.undefined; + }); + + it('should return empty site data when refererInfo is missing', function() { + delete this.defaultBidderRequest.refererInfo; + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.site.domain).to.equal(''); + expect(openrtbRequest.site.page).to.equal(''); + expect(openrtbRequest.site.ref).to.equal(''); + }); + }); + + it('should return empty site.domain and site.page when refererInfo.stack is empty', function() { + this.defaultBidderRequest.refererInfo.stack = []; + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.site.domain).to.equal(''); + expect(openrtbRequest.site.page).to.equal(''); + expect(openrtbRequest.site.ref).to.equal('Reference Page'); + }); + + it('should secure correctly', function() { + this.defaultBidderRequest.refererInfo.stack[0] = ['https://securesite.dvl']; + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead' + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.imp[0].secure).to.equal(1); + }); + + it('should pass schain', function() { + var schain = { + 'ver': '1.0', + 'complete': 1, + 'nodes': [{ + 'asi': 'indirectseller.com', + 'sid': '00001', + 'hp': 1 + }, { + 'asi': 'indirectseller-2.com', + 'sid': '00002', + 'hp': 1 + }] + }; + var bidRequestList = [ + { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaType': 'banner', + 'adUnitCode': 'div-gpt-ad-1438287399331-0', + 'sizes': [[300, 250]], + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757', + 'bidRequestsCount': 1, + 'bidId': '51ef8751f9aead', + 'schain': schain + } + ]; + + var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); + const openrtbRequest = JSON.parse(bidRequest.data); + + expect(openrtbRequest.source.ext.schain).to.deep.equal(schain); + }); + + describe('misc interpretResponse', function () { + it('No bid response', function() { + var noBidResponse = r1adapter.interpretResponse({ + 'body': '' + }); + expect(noBidResponse.length).to.equal(0); + }); + }); + + describe('isBidRequestValid', function () { + var bid = { + 'bidder': 'marsmedia', + 'params': { + 'zoneId': 9999 + }, + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, + 'adUnitCode': 'bannerDiv' + }; + + it('should return true when required params found', function () { + expect(r1adapter.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when placementId missing', function () { + delete bid.params.zoneId; + expect(r1adapter.isBidRequestValid(bid)).to.equal(false); }); }); describe('getUserSyncs', function () { - /* it('should return iframe sync', function () { - let sync = spec.getUserSyncs({ iframeEnabled: true }) - expect(sync.length).to.equal(1) - expect(sync[0].type === 'iframe') - expect(typeof sync[0].url === 'string') - }) - - it('should return pixel sync', function () { - let sync = spec.getUserSyncs({ pixelEnabled: true }) - expect(sync.length).to.equal(1) - expect(sync[0].type === 'image') - expect(typeof sync[0].url === 'string') - }) */ - }) -}) + it('returns an empty string', function () { + expect(r1adapter.getUserSyncs()).to.deep.equal([]); + }); + }); +}); From 51bb5399c2a0512abcf204917c2a5f5b023417e1 Mon Sep 17 00:00:00 2001 From: vladi-mmg Date: Thu, 2 Apr 2020 15:28:03 +0300 Subject: [PATCH 4/7] fix request id bug add vastXml to video response --- modules/marsmediaBidAdapter.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js index 146e1495782..f091e87d611 100644 --- a/modules/marsmediaBidAdapter.js +++ b/modules/marsmediaBidAdapter.js @@ -16,7 +16,7 @@ function MarsmediaAdapter() { let SUPPORTED_VIDEO_API = [1, 2, 5]; let slotsToBids = {}; let that = this; - let version = '2.1'; + let version = '2.2'; this.isBidRequestValid = function (bid) { return !!(bid.params && bid.params.zoneId); @@ -172,7 +172,7 @@ function MarsmediaAdapter() { } }, at: 1, - tmax: 1000, + tmax: 650, regs: { ext: { gdpr: utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies') ? Boolean(bidderRequest.gdprConsent.gdprApplies & 1) : false @@ -240,7 +240,7 @@ function MarsmediaAdapter() { let bid = responses[i]; let bidRequest = slotsToBids[bid.impid]; let bidResponse = { - requestId: bidRequest.id, + requestId: bidRequest.bidId, bidderCode: that.code, cpm: parseFloat(bid.price), width: bid.w, @@ -252,12 +252,26 @@ function MarsmediaAdapter() { }; if (bidRequest.mediaTypes && bidRequest.mediaTypes.video) { - bidResponse.vastUrl = bid.adm; + if (bid.adm.charAt(0) === '<') { + bidResponse.vastXml = bid.adm; + } else { + bidResponse.vastUrl = bid.adm; + } bidResponse.mediaType = 'video'; bidResponse.ttl = 600; } else { bidResponse.ad = bid.adm; } + + if (!bidResponse.width || !bidResponse.height) { + bidResponse.width = 1; + bidResponse.height = 1; + if (bidRequest.sizes) { + bidResponse.width = bidRequest.sizes[0][0]; + bidResponse.height = bidRequest.sizes[0][1]; + } + } + bids.push(bidResponse); } From cf174a457f3da54c035aaa9f84b610639ff681c6 Mon Sep 17 00:00:00 2001 From: vladi-mmg Date: Sun, 5 Apr 2020 12:07:02 +0300 Subject: [PATCH 5/7] Remove bid response default sizes --- modules/marsmediaBidAdapter.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js index f091e87d611..fbbb2f7d8f3 100644 --- a/modules/marsmediaBidAdapter.js +++ b/modules/marsmediaBidAdapter.js @@ -263,15 +263,6 @@ function MarsmediaAdapter() { bidResponse.ad = bid.adm; } - if (!bidResponse.width || !bidResponse.height) { - bidResponse.width = 1; - bidResponse.height = 1; - if (bidRequest.sizes) { - bidResponse.width = bidRequest.sizes[0][0]; - bidResponse.height = bidRequest.sizes[0][1]; - } - } - bids.push(bidResponse); } From 4ef088794ae7fc3f871de0af193252dda2cb9820 Mon Sep 17 00:00:00 2001 From: vladi-mmg Date: Mon, 13 Apr 2020 17:13:26 +0300 Subject: [PATCH 6/7] Change endpoint url --- modules/marsmediaBidAdapter.js | 2 +- test/spec/modules/marsmediaBidAdapter_spec.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js index fbbb2f7d8f3..0d0526778ff 100644 --- a/modules/marsmediaBidAdapter.js +++ b/modules/marsmediaBidAdapter.js @@ -203,7 +203,7 @@ function MarsmediaAdapter() { return []; } - var uri = 'https://bid306.rtbsrv.com/bidder/?bid=3mhdom&zoneId=' + fallbackZoneId; + var uri = 'https://hb.azeriondigital.com/bidder/?bid=3mhdom&zoneId=' + fallbackZoneId; var fat = /(^v|(\.0)+$)/gi; var prebidVersion = '$prebid.version$'; diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js index 553a3b19c55..d612bb3a9e1 100644 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -38,7 +38,7 @@ describe('marsmedia adapter tests', function () { var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); - expect(bidRequest.url).to.have.string('https://bid306.rtbsrv.com/bidder/?bid=3mhdom&zoneId=9999&hbv='); + expect(bidRequest.url).to.have.string('https:/hb.azeriondigital.com/bidder/?bid=3mhdom&zoneId=9999&hbv='); expect(bidRequest.method).to.equal('POST'); const openrtbRequest = JSON.parse(bidRequest.data); expect(openrtbRequest.site).to.not.equal(null); @@ -108,7 +108,7 @@ describe('marsmedia adapter tests', function () { var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); - expect(bidRequest.url).to.have.string('https://bid306.rtbsrv.com/bidder/?bid=3mhdom&zoneId=9999&hbv='); + expect(bidRequest.url).to.have.string('https://hb.azeriondigital.com/bidder/?bid=3mhdom&zoneId=9999&hbv='); expect(bidRequest.method).to.equal('POST'); const openrtbRequest = JSON.parse(bidRequest.data); expect(openrtbRequest.site).to.not.equal(null); From 67f9f5856fa6f61fb9ba613f9b58790f44c84c8c Mon Sep 17 00:00:00 2001 From: vladi-mmg Date: Mon, 13 Apr 2020 17:49:18 +0300 Subject: [PATCH 7/7] Add unit test for vastXml --- test/spec/modules/marsmediaBidAdapter_spec.js | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js index d612bb3a9e1..c43c5daaa7c 100644 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ b/test/spec/modules/marsmediaBidAdapter_spec.js @@ -38,7 +38,7 @@ describe('marsmedia adapter tests', function () { var bidRequest = r1adapter.buildRequests(bidRequestList, this.defaultBidderRequest); - expect(bidRequest.url).to.have.string('https:/hb.azeriondigital.com/bidder/?bid=3mhdom&zoneId=9999&hbv='); + expect(bidRequest.url).to.have.string('https://hb.azeriondigital.com/bidder/?bid=3mhdom&zoneId=9999&hbv='); expect(bidRequest.method).to.equal('POST'); const openrtbRequest = JSON.parse(bidRequest.data); expect(openrtbRequest.site).to.not.equal(null); @@ -127,7 +127,7 @@ describe('marsmedia adapter tests', function () { expect(openrtbRequest.imp[0].video.api).to.eql([1, 2, 5]); }); - it('interpretResponse works', function() { + it('interpretResponse with vast url works', function() { var bidList = { 'body': [ { @@ -159,6 +159,39 @@ describe('marsmedia adapter tests', function () { expect(bid.cpm).to.equal(1.0); expect(bid.ttl).to.equal(600); }); + + it('interpretResponse with xml works', function() { + var bidList = { + 'body': [ + { + 'impid': 'div-gpt-ad-1438287399331-1', + 'price': 1, + 'adm': '', + 'adomain': [ + 'test.com' + ], + 'cid': '467415', + 'crid': 'cr-vid', + 'w': 800, + 'h': 600 + } + ] + }; + + var videoBids = r1adapter.interpretResponse(bidList); + + expect(videoBids.length).to.equal(1); + const bid = videoBids[0]; + expect(bid.width).to.equal(800); + expect(bid.height).to.equal(600); + expect(bid.vastXml).to.equal(''); + expect(bid.mediaType).to.equal('video'); + expect(bid.creativeId).to.equal('cr-vid'); + expect(bid.currency).to.equal('USD'); + expect(bid.netRevenue).to.equal(true); + expect(bid.cpm).to.equal(1.0); + expect(bid.ttl).to.equal(600); + }); }); describe('misc buildRequests', function() {