From 271d63460c9839d5faa2bd09afd1b1837f84250b Mon Sep 17 00:00:00 2001 From: travisbeale Date: Thu, 19 Dec 2019 14:02:07 -0500 Subject: [PATCH] Somo prebid 3.0 updates (#4595) * Re-add Somo bid adapter with v3 compliance * Somo: fixed malformed url in test * Use an alternative method of getting the domain from a url when the URL API isn't supported (IE11) * Somo: fixed indent error --- modules/somoBidAdapter.js | 289 ++++++++++++ modules/somoBidAdapter.md | 14 +- test/spec/modules/somoBidAdapter_spec.js | 545 +++++++++++++++++++++++ 3 files changed, 845 insertions(+), 3 deletions(-) create mode 100644 modules/somoBidAdapter.js create mode 100644 test/spec/modules/somoBidAdapter_spec.js diff --git a/modules/somoBidAdapter.js b/modules/somoBidAdapter.js new file mode 100644 index 00000000000..e043ad83f7b --- /dev/null +++ b/modules/somoBidAdapter.js @@ -0,0 +1,289 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import includes from 'core-js/library/fn/array/includes'; +import {BANNER, VIDEO} from '../src/mediaTypes'; + +const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', + 'startdelay', 'linearity', 'skip', 'delivery', + 'pos', 'api', 'ext', 'battr']; +const BANNER_TARGETING = ['battr', 'btype', 'pos', 'mimes', 'ext']; + +const SITE_TARGETING = ['name', 'domain', 'cat', 'keywords', 'content'] +const APP_TARGETING = ['name', 'bundle', 'domain', 'storeUrl', 'cat', 'ver', 'keywords', 'content'] + +export const spec = { + + code: 'somo', + + supportedMediaTypes: [BANNER, VIDEO], + aliases: ['somoaudience'], + + isBidRequestValid: bid => ( + !!(bid && bid.params && bid.params.placementId) + ), + + buildRequests: function(bidRequests, bidderRequest) { + return bidRequests.map(bidRequest => { + let da = openRtbRequest(bidRequest, bidderRequest); + + return { + method: 'POST', + url: 'https://publisher-east.mobileadtrading.com/rtb/bid?s=' + bidRequest.params.placementId.toString(), + data: da, + bidRequest: bidRequest + }; + }); + }, + + interpretResponse(response, request) { + return bidResponseAvailable(request, response); + }, + + getUserSyncs: (syncOptions, serverResponses, gdprConsent) => { + const syncs = []; + var url = 'https://publisher-east.mobileadtrading.com/usersync'; + + if (syncOptions.pixelEnabled) { + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + // add 'gdpr' only if 'gdprApplies' is defined + if (typeof gdprConsent.gdprApplies === 'boolean') { + url += `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } + } + syncs.push({ + type: 'image', + url: url + }); + } + return syncs; + } +}; + +function bidResponseAvailable(bidRequest, bidResponse) { + let bidResponses = []; + + if (bidResponse.body) { + let bidData = bidResponse.body.seatbid[0].bid[0]; + const bid = { + requestId: bidResponse.body.id, + cpm: bidData.price, + width: bidData.w, + height: bidData.h, + ad: bidData.adm, + ttl: 360, + creativeId: bidData.crid, + adId: bidData.impid, + netRevenue: false, + currency: 'USD', + adUnitCode: bidRequest.bidRequest.adUnitCode + }; + if (isVideo(bidRequest.bidRequest)) { + bid.vastXml = bidData.adm; + bid.mediaType = 'video'; + } else { + bid.ad = bidData.adm; + bid.mediaType = 'banner'; + } + bidResponses.push(bid); + } + return bidResponses; +} + +function openRtbRequest(bidRequest, bidderRequest) { + var openRtbRequest = { + id: bidRequest.bidId, + imp: [openRtbImpression(bidRequest)], + at: 1, + tmax: 400, + site: openRtbSite(bidRequest, bidderRequest), + app: openRtbApp(bidRequest), + device: openRtbDevice(), + bcat: openRtbBCat(bidRequest), + badv: openRtbBAdv(bidRequest), + ext: { + prebid: '$prebid.version$', + }, + }; + if (typeof bidderRequest !== 'undefined') { + openRtbRequest = populateOpenRtbGdpr(bidderRequest.gdprConsent, openRtbRequest); + } + + return openRtbRequest; +} + +function populateOpenRtbGdpr(gdpr, bidRequest) { + if (gdpr && bidRequest && 'gdprApplies' in gdpr) { + if (!('reqs' in bidRequest)) { + bidRequest.reqs = {}; + } + if (!('ext' in bidRequest.reqs)) { + bidRequest.reqs.ext = {}; + } + bidRequest.reqs.ext.gdpr = gdpr.gdprApplies; + + if ('consentString' in gdpr) { + if (!('user' in bidRequest)) { + bidRequest.user = {}; + } + if (!('ext' in bidRequest.user)) { + bidRequest.user.ext = {}; + } + bidRequest.user.ext.consent = gdpr.consentString; + } + } + + return bidRequest; +} + +function openRtbImpression(bidRequest) { + const imp = { + 'id': bidRequest.bidId, + bidfloor: bidRequest.params.bidfloor || 0, + }; + if (isVideo(bidRequest)) { + imp.video = {}; + if (bidRequest.mediaTypes && + bidRequest.mediaTypes.video && + bidRequest.mediaTypes.video.sizes) { + const sizes = getSizes(bidRequest.mediaTypes.video.sizes); + imp.video.w = sizes[0]; + imp.video.h = sizes[1]; + } + if (bidRequest.params.video) { + Object.keys(bidRequest.params.video) + .filter(param => includes(VIDEO_TARGETING, param)) + .forEach(param => imp.video[param] = bidRequest.params.video[param]); + } + } else { + imp.banner = { + topframe: 0 + }; + if (bidRequest.mediaTypes && + bidRequest.mediaTypes.banner && + bidRequest.mediaTypes.banner.sizes) { + const sizes = getSizes(bidRequest.mediaTypes.banner.sizes); + imp.banner.w = sizes[0]; + imp.banner.h = sizes[1]; + } + if (bidRequest.params.banner) { + Object.keys(bidRequest.params.banner) + .filter(param => includes(BANNER_TARGETING, param)) + .forEach(param => imp.banner[param] = bidRequest.params.banner[param]); + } + } + return imp; +} + +function isApp(bidRequest) { + if (bidRequest.params.app) { + return true; + } else { + return false; + } +} + +function openRtbSite(bidRequest, bidderRequest) { + if (!isApp(bidRequest)) { + const site = {}; + + if (bidderRequest && bidderRequest.refererInfo) { + site.ref = bidderRequest.refererInfo.referer; + site.page = bidderRequest.refererInfo.canonicalUrl; + } + + if (bidRequest.params.site) { + Object.keys(bidRequest.params.site) + .filter(param => includes(SITE_TARGETING, param)) + .forEach(param => site[param] = bidRequest.params.site[param]); + } + if (typeof site.domain === 'undefined' && + typeof site.page !== 'undefined') { + if (typeof window.URL === 'function') { + site.domain = (new window.URL(site.page)).hostname; + } else { + site.domain = getDomainFromUrl(site.page); + } + } + + return site; + } else { + return null; + } +} + +function getDomainFromUrl(url) { + var domain = url; + + if (url.indexOf('//') > -1) { + domain = url.split('/')[2]; + } else { + domain = url.split('/')[0]; + } + + domain = domain.split(':')[0]; + domain = domain.split('?')[0]; + + return domain; +} + +function openRtbApp(bidRequest) { + if (isApp(bidRequest)) { + const app = { + + } + Object.keys(bidRequest.params.app) + .filter(param => includes(APP_TARGETING, param)) + .forEach(param => app[param] = bidRequest.params.app[param]); + + return app; + } else { + return null; + } +} + +function openRtbDevice() { + return { + ip: 'check', + ua: navigator.userAgent, + language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), + }; +} + +function openRtbBCat(bidRequest) { + if (utils.isArray(bidRequest.params.bcat)) { + return bidRequest.params.bcat; + } + return []; +} + +function openRtbBAdv(bidRequest) { + if (utils.isArray(bidRequest.params.badv)) { + return bidRequest.params.badv; + } + return []; +} + +function isVideo(format) { + return utils.deepAccess(format, 'mediaTypes.video') || format.mediaType == 'video'; +} + +/* Turn bid request sizes into compatible format */ +function getSizes(requestSizes) { + let width = 0; + let height = 0; + if (utils.isArray(requestSizes) && requestSizes.length === 2 && + !utils.isArray(requestSizes[0])) { + width = parseInt(requestSizes[0], 10); + height = parseInt(requestSizes[1], 10); + } else if (typeof requestSizes === 'object') { + for (let i = 0; i < requestSizes.length; i++) { + let size = requestSizes[i]; + width = parseInt(size[0], 10); + height = parseInt(size[1], 10); + break; + } + } + return [width, height]; +} + +registerBidder(spec); diff --git a/modules/somoBidAdapter.md b/modules/somoBidAdapter.md index de395478061..e8457fc0ca2 100644 --- a/modules/somoBidAdapter.md +++ b/modules/somoBidAdapter.md @@ -7,12 +7,16 @@ Connects to Somo Audience demand source. Please use ```somo``` as the bidder code. -For video integration, somoAudience returns content as vastXML and requires the publisher to define the cache url in config passed to Prebid for it to be valid in the auction +For video integration, Somo Audience returns content as vastXML and requires the publisher to define the cache url in config passed to Prebid for it to be valid in the auction # Test Site Parameters ``` var adUnits = [{ code: 'banner-ad-div', - sizes: [[300, 250]], + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, bids: [{ bidder: 'somo', params: { @@ -25,7 +29,11 @@ For video integration, somoAudience returns content as vastXML and requires the ``` var adUnits = [{ code: 'banner-ad-div', - sizes: [[300, 250]], + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, bids: [{ bidder: 'somo', params: { diff --git a/test/spec/modules/somoBidAdapter_spec.js b/test/spec/modules/somoBidAdapter_spec.js new file mode 100644 index 00000000000..8ffed99a16a --- /dev/null +++ b/test/spec/modules/somoBidAdapter_spec.js @@ -0,0 +1,545 @@ +import {expect} from 'chai'; +import {spec} from 'modules/somoBidAdapter'; +import * as utils from 'src/utils'; + +describe('Somo Audience Adapter Tests', function () { + describe('isBidRequestValid', function () { + it('should return false when given an invalid bid', function () { + const bid = { + bidder: 'somo', + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(false); + }); + it('should return true when given a placementId bid', function () { + const bid = { + bidder: 'somo', + params: { + placementId: 'test' + } + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + }); + + describe('buildRequests', function () { + describe('buildBannerRequests', function () { + it('should properly build a banner request with type not defined and sizes not defined', function () { + const bidRequests = [{ + bidder: 'somo', + params: { + placementId: 'test' + } + }]; + const bidderRequest = { + refererInfo: { + referer: 'https://www.test.com/page?var=val', + canonicalUrl: 'https://www.test.com/page' + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].url).to.equal('https://publisher-east.mobileadtrading.com/rtb/bid?s=test'); + expect(request[0].method).to.equal('POST'); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal('https://www.test.com/page?var=val'); + expect(ortbRequest.site.page).to.equal('https://www.test.com/page'); + expect(ortbRequest.site.domain).to.not.be.undefined; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.device).to.not.equal(null); + expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + expect(ortbRequest.imp[0].bidfloor).to.not.be.null; + expect(ortbRequest.imp[0].banner).to.not.equal(null); + }); + + it('should properly build a banner request with sizes defined in 2d array', function () { + const bidRequests = [{ + bidder: 'somo', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + params: { + placementId: 'test' + } + }]; + + const bidderRequest = { + refererInfo: { + referer: 'https://www.test.com/page?var=val', + canonicalUrl: 'https://www.test.com/page' + } + } + + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].url).to.equal('https://publisher-east.mobileadtrading.com/rtb/bid?s=test'); + expect(request[0].method).to.equal('POST'); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal('https://www.test.com/page?var=val'); + expect(ortbRequest.site.page).to.equal('https://www.test.com/page'); + expect(ortbRequest.site.domain).to.not.be.undefined; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].bidfloor).to.not.be.null; + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(250); + }); + it('should properly build a banner request with sizes defined in 1d array', function () { + const bidRequests = [{ + bidder: 'somo', + mediaTypes: { + banner: { + sizes: [300, 250] + } + }, + params: { + placementId: 'test' + } + }]; + + const bidderRequest = { + refererInfo: { + referer: 'https://www.test.com/page?var=val', + canonicalUrl: 'https://www.test.com/page' + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request[0].url).to.equal('https://publisher-east.mobileadtrading.com/rtb/bid?s=test'); + expect(request[0].method).to.equal('POST'); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal('https://www.test.com/page?var=val'); + expect(ortbRequest.site.page).to.equal('https://www.test.com/page'); + expect(ortbRequest.site.domain).to.not.be.undefined; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].bidfloor).to.not.be.null; + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(250); + expect(ortbRequest.imp[0].banner.mimes).to.equal(undefined); + expect(ortbRequest.imp[0].banner.btype).to.equal(undefined); + expect(ortbRequest.imp[0].banner.pos).to.equal(undefined); + expect(ortbRequest.imp[0].banner.battr).to.equal(undefined); + }); + + it('should populate optional banner parameters', function () { + const bidRequests = [ + { + bidder: 'somo', + mediaTypes: { + banner: { + sizes: [[300, 200]] + } + }, + mediaType: 'banner', + params: { + placementId: 'test', + banner: { + mimes: 'video/mp4', + btype: '4', + pos: '1', + battr: 'ibv', + } + } + } + ]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(200); + expect(ortbRequest.imp[0].banner.mimes).to.equal('video/mp4'); + expect(ortbRequest.imp[0].banner.btype).to.equal('4'); + expect(ortbRequest.imp[0].banner.pos).to.equal('1'); + expect(ortbRequest.imp[0].banner.battr).to.equal('ibv'); + }); + }); + + describe('buildVideoRequests', function () { + it('should properly build a video request with sizes defined', function () { + const bidRequests = [{ + bidder: 'somo', + mediaTypes: { + video: { + sizes: [200, 300] + } + }, + params: { + placementId: 'test' + } + }]; + + const bidderRequest = { + refererInfo: { + referer: 'https://www.test.com/page?var=val', + canonicalUrl: 'https://www.test.com/page' + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal('https://www.test.com/page?var=val'); + expect(ortbRequest.site.page).to.equal('https://www.test.com/page'); + expect(ortbRequest.site.domain).to.not.be.undefined; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].video).to.not.equal(null); + expect(ortbRequest.imp[0].video.w).to.equal(200); + expect(ortbRequest.imp[0].video.h).to.equal(300); + }); + + it('should properly build a video request with sizes defined in 2d array', function () { + const bidRequests = [{ + bidder: 'somo', + mediaTypes: { + video: { + sizes: [[200, 300]] + } + }, + params: { + placementId: 'test' + } + }]; + + const bidderRequest = { + refererInfo: { + referer: 'https://www.test.com/page?var=val', + canonicalUrl: 'https://www.test.com/page' + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal('https://www.test.com/page?var=val'); + expect(ortbRequest.site.page).to.equal('https://www.test.com/page'); + expect(ortbRequest.site.domain).to.not.be.undefined; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].video).to.not.equal(null); + expect(ortbRequest.imp[0].video.w).to.equal(200); + expect(ortbRequest.imp[0].video.h).to.equal(300); + }); + it('should properly build a video request with sizes not defined', function () { + const bidRequests = [{ + bidder: 'somo', + mediaType: 'video', + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.imp).to.have.lengthOf(1); + expect(ortbRequest.imp[0].video).to.not.equal(null); + expect(ortbRequest.imp[0].video.mimes).to.equal(undefined); + expect(ortbRequest.imp[0].video.minduration).to.equal(undefined); + expect(ortbRequest.imp[0].video.maxduration).to.equal(undefined); + expect(ortbRequest.imp[0].video.protocols).to.equal(undefined); + expect(ortbRequest.imp[0].video.startdelay).to.equal(undefined); + expect(ortbRequest.imp[0].video.linearity).to.equal(undefined); + expect(ortbRequest.imp[0].video.skip).to.equal(undefined); + expect(ortbRequest.imp[0].video.delivery).to.equal(undefined); + expect(ortbRequest.imp[0].video.pos).to.equal(undefined); + expect(ortbRequest.imp[0].video.api).to.equal(undefined); + expect(ortbRequest.imp[0].video.battr).to.equal(undefined); + }); + + it('should populate optional video parameters', function () { + const bidRequests = [ + { + bidder: 'somo', + mediaTypes: { + video: { + sizes: [[200, 300]] + } + }, + params: { + placementId: 'test', + video: { + mimes: 'video/mp4', + minduration: '15', + maxduration: '30', + protocols: 'mp4', + startdelay: '0', + linearity: 'linear', + skip: '1', + delivery: 'web', + pos: '1', + api: 'VPAID 1.0', + battr: 'ibv', + } + } + } + ]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.imp[0].video).to.not.equal(null); + expect(ortbRequest.imp[0].video.w).to.equal(200); + expect(ortbRequest.imp[0].video.h).to.equal(300); + expect(ortbRequest.imp[0].video.mimes).to.equal('video/mp4'); + expect(ortbRequest.imp[0].video.minduration).to.equal('15'); + expect(ortbRequest.imp[0].video.maxduration).to.equal('30'); + expect(ortbRequest.imp[0].video.protocols).to.equal('mp4'); + expect(ortbRequest.imp[0].video.startdelay).to.equal('0'); + expect(ortbRequest.imp[0].video.linearity).to.equal('linear'); + expect(ortbRequest.imp[0].video.skip).to.equal('1'); + expect(ortbRequest.imp[0].video.delivery).to.equal('web'); + expect(ortbRequest.imp[0].video.pos).to.equal('1'); + expect(ortbRequest.imp[0].video.api).to.equal('VPAID 1.0'); + expect(ortbRequest.imp[0].video.battr).to.equal('ibv'); + }); + }); + + describe('buildSiteRequests', function () { + it('should fill in basic site parameters', function () { + const bidRequests = [{ + bidder: 'somo', + params: { + placementId: 'test' + } + }]; + + const bidderRequest = { + refererInfo: { + referer: 'https://www.test.com/page?var=val', + canonicalUrl: 'https://www.test.com/page' + } + }; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request[0].data; + expect(ortbRequest.app).to.equal(null); + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.ref).to.equal('https://www.test.com/page?var=val'); + expect(ortbRequest.site.page).to.equal('https://www.test.com/page'); + expect(ortbRequest.site.domain).to.not.be.undefined; + }); + + it('should fill in optional site parameters', function () { + const bidRequests = [{ + bidder: 'somo', + params: { + placementId: 'test', + site: { + domain: 'somoaudience.com', + name: 'Somo Audience', + cat: 'IAB-25', + keywords: 'unit testing', + content: 'Unit Testing' + } + } + }]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.app).to.equal(null); + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.name).to.equal('Somo Audience'); + expect(ortbRequest.site.domain).to.equal('somoaudience.com'); + expect(ortbRequest.site.cat).to.equal('IAB-25'); + expect(ortbRequest.site.keywords).to.equal('unit testing'); + expect(ortbRequest.site.content).to.equal('Unit Testing'); + }) + }); + + describe('buildAppRequests', function () { + it('should fill in app parameters', function () { + const bidRequests = [{ + bidder: 'somo', + params: { + placementId: 'test', + app: { + bundle: 'com.somoaudience.apps', + storeUrl: 'http://somoaudience.com/apps', + domain: 'somoaudience.com', + name: 'Generic SomoAudience App 5', + cat: 'IAB-25', + keywords: 'unit testing', + content: 'Unit Testing', + ver: '5.423-s', + } + } + }]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.site).to.equal(null); + expect(ortbRequest.app).to.not.be.null; + expect(ortbRequest.app.bundle).to.equal('com.somoaudience.apps'); + expect(ortbRequest.app.storeUrl).to.equal('http://somoaudience.com/apps'); + expect(ortbRequest.app.domain).to.equal('somoaudience.com'); + expect(ortbRequest.app.name).to.equal('Generic SomoAudience App 5'); + expect(ortbRequest.app.ver).to.equal('5.423-s'); + expect(ortbRequest.app.cat).to.equal('IAB-25'); + expect(ortbRequest.app.keywords).to.equal('unit testing'); + expect(ortbRequest.app.content).to.equal('Unit Testing'); + }); + }); + + describe('buildGDPRRequests', function () { + const bidderRequest = { + gdprConsent: { + gdprApplies: true, + consentString: 'test' + }, + }; + + it('should properly build request with gdpr consent', function () { + const bidRequests = [{ + bidder: 'somo', + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request[0].data; + expect(ortbRequest.reqs).to.not.equal(undefined); + expect(ortbRequest.reqs.ext).to.not.equal(undefined); + expect(ortbRequest.reqs.ext.gdpr).to.equal(true); + expect(ortbRequest.user).to.not.equal(undefined); + expect(ortbRequest.user.ext).to.not.equal(undefined); + expect(ortbRequest.user.ext.consent).to.equal('test'); + }); + it('should properly build request with gdpr not applies', function () { + bidderRequest.gdprConsent.gdprApplies = false; + const bidRequests = [{ + bidder: 'somo', + params: { + placementId: 'test' + } + }]; + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request[0].data; + expect(ortbRequest.reqs).to.not.equal(undefined); + expect(ortbRequest.reqs.ext).to.not.equal(undefined); + expect(ortbRequest.reqs.ext.gdpr).to.equal(false); + expect(ortbRequest.user).to.not.equal(undefined); + expect(ortbRequest.user.ext).to.not.equal(undefined); + expect(ortbRequest.user.ext.consent).to.equal('test'); + }); + }); + + describe('buildExtraArgsRequests', function () { + it('should populate optional parameters', function () { + const bidRequests = [ + { + bidder: 'somo', + params: { + placementId: 'test', + bcat: ['IAB-2', 'IAB-7'], + badv: ['somoaudience.com', 'mobileadtrading.com'], + bidfloor: '0.05', + }, + } + ]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + expect(ortbRequest.imp[0].bidfloor).to.not.be.null; + expect(ortbRequest.imp[0].bidfloor).to.be.equal('0.05'); + expect(ortbRequest.bcat).to.not.be.null; + expect(ortbRequest.bcat).to.have.lengthOf(2); + expect(ortbRequest.bcat).to.contain('IAB-2'); + expect(ortbRequest.badv).to.not.be.null; + expect(ortbRequest.badv).to.have.lengthOf(2); + expect(ortbRequest.badv).to.contain('somoaudience.com'); + }); + }); + }); + + describe('interpretResponse', function () { + it('Verify banner parse response', function () { + const bidRequests = [ + { + bidder: 'somo', + params: { + placementId: 'test', + }, + bidId: '234234234', + } + ]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'Somo Test Ad' + }], + bidId: '234234234' + }] + }; + const bids = spec.interpretResponse({ body: ortbResponse }, {bidRequest: bidRequests[0]}); + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.ad).to.equal('Somo Test Ad'); + }); + + it('Verify video parse response', function () { + const bidRequests = [ + { + bidder: 'somo', + mediaTypes: { + video: { + } + }, + params: { + placementId: 'test', + }, + bidId: '234234234', + } + ]; + const request = spec.buildRequests(bidRequests); + const ortbRequest = request[0].data; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'Somo Test Ad' + }], + bidId: '234234234' + }] + }; + const bids = spec.interpretResponse({ body: ortbResponse }, {bidRequest: bidRequests[0]}); + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.vastXml).to.equal('Somo Test Ad'); + }); + }); + + describe('user sync', function () { + it('should register the pixel sync url', function () { + let syncs = spec.getUserSyncs({ + pixelEnabled: true + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('image'); + }); + + it('should pass gdpr params', function () { + let syncs = spec.getUserSyncs({ pixelEnabled: true }, {}, { + gdprApplies: false, consentString: 'test' + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('image'); + expect(syncs[0].url).to.contains('gdpr=0'); + }); + + it('should pass gdpr applies params', function () { + let syncs = spec.getUserSyncs({ pixelEnabled: true }, {}, { + gdprApplies: true, consentString: 'test' + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('image'); + expect(syncs[0].url).to.contains('gdpr=1'); + expect(syncs[0].url).to.contains('gdpr_consent=test'); + }); + }); +});