From 67798a5107143bea9bc140ac66de27175e5cfaae Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Thu, 1 Aug 2019 21:18:08 -0700 Subject: [PATCH 01/14] Nobid Prebid Adapter commit --- modules/nobidBidAdapter.js | 331 ++++++++++++++++++++++ test/spec/modules/nobidBidAdapter_spec.js | 167 +++++++++++ 2 files changed, 498 insertions(+) create mode 100644 modules/nobidBidAdapter.js create mode 100644 test/spec/modules/nobidBidAdapter_spec.js diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js new file mode 100644 index 00000000000..22e90665a5b --- /dev/null +++ b/modules/nobidBidAdapter.js @@ -0,0 +1,331 @@ +import * as utils from '../src/utils'; +import { registerBidder } from '../src/adapters/bidderFactory'; +import { BANNER } from '../src/mediaTypes'; +const BIDDER_CODE = 'nobid'; +window.nobid = window.nobid || {}; +nobid.version = '1.1.0'; +nobid.status = {}; +nobid.status.bidResponseProcessed = false; +nobid.status.bidResponseTimeout = false; +nobid.timestamp = function() { + var date = new Date(); + var zp = function (val) { return (val <= 9 ? '0' + val : '' + val); } + var d = date.getDate(); + var y = date.getFullYear(); + var m = date.getMonth() + 1; + var h = date.getHours(); + var min = date.getMinutes(); + var s = date.getSeconds(); + return '' + y + '-' + zp(m) + '-' + zp(d) + ' ' + zp(h) + ':' + zp(min) + ':' + zp(s); +}; +nobid.clientDim = function() { + try { + return `${screen.width}x${screen.height}`; + } catch (e) { + console.error(e); + } +}; +nobid.a = []; +nobid.tt = encodeURIComponent(document.title); +nobid.t = nobid.timestamp(); +nobid.tz = Math.round(new Date().getTimezoneOffset()); +nobid.r = nobid.clientDim(); +nobid.log = function(msg, obj) { + var debug = (typeof utils.getParameterByName === 'function') && (utils.getParameterByName('nobid-debug')); + if (!debug) return; + if (typeof obj != 'undefined') console.log('NoBid Prebid Adapter: ' + msg, obj); + else console.log('NoBid Prebid Adapter: ' + msg); +} +nobid.getAdUnit = function(divid) { + for (var i = 0; i < nobid.a.length; i++) { + if (nobid.a[i].d === divid) { + return nobid.a[i]; + } + } + return false; +}; +nobid.resolveEndpoint = function() { + var ret = 'https://ads.servenobid.com/'; + var env = (typeof utils.getParameterByName === 'function') && (utils.getParameterByName('nobid-env')); + if (!env) ret = 'https://ads.servenobid.com/'; + else if (env == 'beta') ret = 'https://beta.servenobid.com/'; + else if (env == 'dev') ret = '//localhost:8282/'; + else if (env == 'qa') ret = 'https://qa-ads.nobid.com/'; + return ret; +} +nobid.triggerEvent = function(params, doc) { + var r = Math.floor(Math.random() * 11000); + var path = nobid.resolveEndpoint() + 'event.js?cb=' + r; + var xhr = new XMLHttpRequest(); + xhr.withCredentials = true; + xhr.open('POST', path, true); + if (!params['l']) params['l'] = doc.location.href; + xhr.send(JSON.stringify(params)); +} +nobid.adunit = function (adunitObject) { + var removeByAttrValue = function(array, attribute, value) { + for (var i = array.length - 1; i >= 0; i--) { + var entry = array[i]; + if (entry[attribute] && entry[attribute] === value) { + array.splice(i, 1); + } + } + } + var a = nobid.getAdUnit(adunitObject.div) || {}; + if (adunitObject.account) { + a.s = adunitObject.account; + } else if (nobid.s) { + a.s = nobid.s; + } + if (adunitObject.sizes) { + a.z = adunitObject.sizes; + } + if (adunitObject.div) { + a.d = adunitObject.div; + } + if (adunitObject.targeting) { + a.g = adunitObject.targeting; + } else { + a.g = {}; + } + if (adunitObject.companion) { + a.c = adunitObject.companion; + } + if (adunitObject.div) { + removeByAttrValue(nobid.a, 'd', adunitObject.div); + } + if (adunitObject.sizeMapping) { + a.sm = adunitObject.sizeMapping; + } + if (adunitObject.siteId) { + a.sid = adunitObject.siteId; + } + /* {"BIDDER_ID":{"WxH":"TAG_ID", "WxH":"TAG_ID"}} */ + if (adunitObject.rtb) { + a.rtb = adunitObject.rtb; + } + nobid.a.push(a); + return a; +}; +nobid.setup = function(bids, bidderRequest) { + var serializeState = function(divIds, siteId) { + var filterAdUnitsByIds = function(divIds, adUnits) { + var filtered = []; + if (!divIds || !divIds.length) { + filtered = adUnits; + } else if (adUnits) { + var a = []; + if (!(divIds instanceof Array)) a.push(divIds); + else a = divIds; + for (var i = 0, l = adUnits.length; i < l; i++) { + var adUnit = adUnits[i]; + if (adUnit && adUnit.d && (a.indexOf(adUnit.d) > -1)) { + filtered.push(adUnit); + } + } + } + return filtered; + } + var gdprConsent = function(bidderRequest) { + var gdprConsent = {}; + if (bidderRequest && bidderRequest.gdprConsent) { + gdprConsent = { + consentString: bidderRequest.gdprConsent.consentString, + // will check if the gdprApplies field was populated with a boolean value (ie from page config). If it's undefined, then default to true + consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : false + } + } + return gdprConsent; + } + var topLocation = function(bidderRequest) { + var ret = ''; + if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { + ret = bidderRequest.refererInfo.referer; + } else { + ret = (window.context && window.context.location && window.context.location.href) ? window.context.location.href : document.location.href; + } + return encodeURIComponent(ret.replace('%', '')); + } + var state = {}; + state['sid'] = siteId; + state['l'] = topLocation(bidderRequest); + state['tt'] = nobid['tt']; + state['tt'] = state['tt'].replace(/'|;|quot;|39;|&|&|#|\r\n|\r|\n|\t|\f|\%0A|\"|\%22|\%5C|\%23|\%26|\%26|\%09/gm, ''); + state['a'] = filterAdUnitsByIds(divIds, nobid.a || []); + state['t'] = nobid.timestamp(); + state['tz'] = Math.round(new Date().getTimezoneOffset()); + state['r'] = nobid.clientDim(); + state['lang'] = (navigator.languages && navigator.languages[0]) || navigator.language || navigator.userLanguage; + state['ref'] = document.referrer; + state['gdpr'] = gdprConsent(bidderRequest); + return state; + }; + /* DISCOVER SLOTS */ + var divids = []; + var siteId = 0; + for (var i = 0; i < bids.length; i++) { + var bid = bids[i]; + var divid = bid.adUnitCode; + divids.push(divid); + var sizes = bid.sizes; + siteId = (typeof bid.params['siteId'] != 'undefined' && bid.params['siteId']) ? bid.params['siteId'] : siteId; + if (siteId && bid.params && bid.params.tags) { + nobid.adunit({div: divid, sizes: sizes, rtb: bid.params.tags, siteId: siteId}); + } else if (siteId) { + nobid.adunit({div: divid, sizes: sizes, siteId: siteId}); + } + } + if (siteId) { + return serializeState(divids, siteId); + } else { + return false; + } +} +nobid.ProcessBidResponse = function (response, bidRequest) { + var bidResponses = []; + nobid.status.bidResponseProcessed = true; + nobid.status.bidResponseTimeout = false; + nobid.status.bidResponse = response; + for (var i = 0; response.bids && i < response.bids.length; i++) { + var bid = response.bids[i]; + if (bid.bdrid < 100 || !bidRequest || !bidRequest.bidderRequest || !bidRequest.bidderRequest.bids) continue; + var reqBid = bidRequest.bidderRequest.bids.find(item => { return item.adUnitCode == bid.divid; }); + if (!reqBid) continue; + const bidResponse = { + requestId: reqBid.bidId, + cpm: 1 * ((bid.price) ? bid.price : (bid.bucket) ? bid.bucket : 0), + width: bid.size.w, + height: bid.size.h, + creativeId: (bid.creativeid) || '', + dealId: (bid.dealid) || '', + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: bid.adm, + mediaType: BANNER + }; + bidResponses.push(bidResponse); + } + return bidResponses; +}; +nobid.renderTag = function(doc, id, win) { + nobid.log('-NoBid Prebid Adapter- nobid.renderTag()', id); + if (nobid.bidResponse && nobid.bidResponse.bids) { + for (var i in nobid.bidResponse.bids) { + const bid = nobid.bidResponse.bids[i]; + if (id == bid.id && bid.adm2) { + nobid.log('-NoBid Prebid Adapter- nobid.renderTag() found tag', id); + var markup = bid.adm2; + doc.write(markup); + doc.close(); + break; + } + } + } +} +nobid.cookies = {}; +nobid.cookies.get = function(name) { + var value = '; ' + document.cookie; + var parts = value.split('; ' + name + '='); + if (parts.length === 2) { + return parts.pop().split(';').shift(); + } +}; +nobid.cookies.getAll = function() { + return document.cookie.split('; ').reduce(function(map, keyValue) { + var equalPos = keyValue.indexOf('='); + map[keyValue.substr(0, equalPos)] = keyValue.substr(equalPos + 1); + return map; + }, {}); +}; +nobid.cookies.set = function(name, value, lifespanInSec) { + var d = new Date(); + d.setTime(d.getTime() + (lifespanInSec * 1000)); + var expires = 'expires=' + d.toUTCString(); + document.cookie = name + '=' + value + ';' + expires + ';path=/'; +}; +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function(bid) { + nobid.log('-NoBid Prebid Adapter- isBidRequestValid', bid); + return !!bid.params.siteId; + }, + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(validBidRequests, bidderRequest) { + var buildEndpoint = function() { + return nobid.resolveEndpoint() + 'adreq?cb=' + Math.floor(Math.random() * 11000); + } + nobid.log('-NoBid Prebid Adapter- buildRequests', validBidRequests); + if (!validBidRequests || validBidRequests.length <= 0) { + nobid.log('-NoBid Prebid Adapter- Empty validBidRequests'); + return; + } + const payload = nobid.setup(validBidRequests, bidderRequest); + if (!payload) return; + const payloadString = JSON.stringify(payload).replace(/'|&|#/g, '') + const endpoint = buildEndpoint(); + return { + method: 'POST', + url: endpoint, + data: payloadString, + bidderRequest + }; + }, + /** + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, bidRequest) { + nobid.log('-NoBid Prebid Adapter- interpretResponse', serverResponse); + nobid.log('-NoBid Prebid Adapter- interpretResponse', bidRequest); + nobid.bidResponse = serverResponse.body; + return nobid.ProcessBidResponse(serverResponse.body, bidRequest); + }, + + /** + * Register the user sync pixels which should be dropped after the auction. + * + * @param {SyncOptions} syncOptions Which user syncs are allowed? + * @param {ServerResponse[]} serverResponses List of server's responses. + * @return {UserSync[]} The user syncs which should be dropped. + */ + getUserSyncs: function(syncOptions, serverResponses) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: 'https://s3.amazonaws.com/nobid-public/sync.html' + }]; + } else { + utils.logWarn('-NoBid Prebid Adapter- Please enable iframe based user sync.'); + console.log('-NoBid Prebid Adapter- Please enable iframe based user sync.', syncOptions); + return []; + } + }, + + /** + * Register bidder specific code, which will execute if bidder timed out after an auction + * @param {data} Containing timeout specific data + */ + onTimeout: function(data) { + nobid.log('-NoBid Prebid Adapter- onTimeout', data); + nobid.status.bidResponseTimeout = true; + }, + onBidWon: function(data) { + nobid.log('-NoBid Prebid Adapter- onBidWon', data); + } +} +registerBidder(spec); diff --git a/test/spec/modules/nobidBidAdapter_spec.js b/test/spec/modules/nobidBidAdapter_spec.js new file mode 100644 index 00000000000..b58cc0b0f6a --- /dev/null +++ b/test/spec/modules/nobidBidAdapter_spec.js @@ -0,0 +1,167 @@ +import { expect } from 'chai'; +import { spec } from 'modules/nobidBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; + +describe('Nobid Adapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'nobid', + 'params': { + 'siteId': 1 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when required params found', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'siteId': 1 + }; + + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'siteId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const SITE_ID = 1; + const REFERER = 'https://www.examplereferer.com'; + let bidRequests = [ + { + 'bidder': 'nobid', + 'params': { + 'siteId': SITE_ID + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + let bidderRequest = { + refererInfo: {referer: REFERER} + } + + it('should add source and verison to the tag', function () { + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + expect(payload.sid).to.equal(SITE_ID); + expect(payload.l).to.exist.and.to.equal(encodeURIComponent(REFERER)); + expect(payload.tt).to.exist; + expect(payload.a).to.exist; + expect(payload.t).to.exist; + expect(payload.tz).to.exist; + expect(payload.r).to.exist; + expect(payload.lang).to.exist; + expect(payload.ref).to.exist; + expect(payload.gdpr).to.exist; + }); + + it('sends bid request to ENDPOINT via POST', function () { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.contain('ads.servenobid.com/adreq'); + expect(request.method).to.equal('POST'); + }); + + it('should add gdpr consent information to the request', function () { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + let bidderRequest = { + 'bidderCode': 'nobid', + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + consentString: consentString, + gdprApplies: true + } + }; + bidderRequest.bids = bidRequests; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.gdpr).to.exist; + expect(payload.gdpr.consentString).to.exist.and.to.equal(consentString); + expect(payload.gdpr.consentRequired).to.exist.and.to.be.true; + }); + }); + + describe('interpretResponse', function () { + const CREATIVE_ID_300x250 = 'CREATIVE-100'; + const ADUNIT_300x250 = 'ADUNIT-1'; + const ADMARKUP_300x250 = 'ADMARKUP-300x250'; + const PRICE_300x250 = 0.51; + const REQUEST_ID = '3db3773286ee59'; + let response = { + country: 'US', + ip: '68.83.15.75', + device: 'COMPUTER', + site: 1, + bids: [ + {id: 1, + bdrid: 101, + divid: ADUNIT_300x250, + creativeid: CREATIVE_ID_300x250, + size: {'w': 300, 'h': 250}, + adm: ADMARKUP_300x250, + price: '' + PRICE_300x250 + } + ] + }; + + it('should get correct bid response', function () { + let expectedResponse = [ + { + requestId: REQUEST_ID, + cpm: PRICE_300x250, + width: 300, + height: 250, + creativeId: CREATIVE_ID_300x250, + dealId: '', + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: ADMARKUP_300x250, + mediaType: 'banner' + } + ]; + + let bidderRequest = { + bids: [{ + bidId: REQUEST_ID, + adUnitCode: ADUNIT_300x250 + }] + } + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); ; + }); + }); +}); From 7afc4bd3addb760cd8ca0540e017b3e32bb385a7 Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Thu, 1 Aug 2019 22:00:51 -0700 Subject: [PATCH 02/14] Fixed global replace and unit tests --- modules/nobidBidAdapter.js | 2 +- test/spec/modules/nobidBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index 22e90665a5b..54bb5bf14b8 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -144,7 +144,7 @@ nobid.setup = function(bids, bidderRequest) { } else { ret = (window.context && window.context.location && window.context.location.href) ? window.context.location.href : document.location.href; } - return encodeURIComponent(ret.replace('%', '')); + return encodeURIComponent(ret.replace(/\%/g, '')); } var state = {}; state['sid'] = siteId; diff --git a/test/spec/modules/nobidBidAdapter_spec.js b/test/spec/modules/nobidBidAdapter_spec.js index b58cc0b0f6a..08f877edbde 100644 --- a/test/spec/modules/nobidBidAdapter_spec.js +++ b/test/spec/modules/nobidBidAdapter_spec.js @@ -160,7 +160,7 @@ describe('Nobid Adapter', function () { adUnitCode: ADUNIT_300x250 }] } - let result = spec.interpretResponse({ body: response }, {bidderRequest}); + let result = spec.interpretResponse({ body: response }, {bidderRequest: bidderRequest}); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); ; }); }); From 9f97d34a420376e7dd7bf225ba4fbd5bb556b728 Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Thu, 1 Aug 2019 22:29:05 -0700 Subject: [PATCH 03/14] Fixed find function --- modules/nobidBidAdapter.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index 54bb5bf14b8..0d67a206255 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -182,6 +182,14 @@ nobid.setup = function(bids, bidderRequest) { } } nobid.ProcessBidResponse = function (response, bidRequest) { + var findBid = function(divid, bids) { + for (var i = 0; i < bids.length; i++) { + if (bids[i].adUnitCode === divid) { + return bids[i]; + } + } + return false; + } var bidResponses = []; nobid.status.bidResponseProcessed = true; nobid.status.bidResponseTimeout = false; @@ -189,7 +197,7 @@ nobid.ProcessBidResponse = function (response, bidRequest) { for (var i = 0; response.bids && i < response.bids.length; i++) { var bid = response.bids[i]; if (bid.bdrid < 100 || !bidRequest || !bidRequest.bidderRequest || !bidRequest.bidderRequest.bids) continue; - var reqBid = bidRequest.bidderRequest.bids.find(item => { return item.adUnitCode == bid.divid; }); + var reqBid = findBid(bid.divid, bidRequest.bidderRequest.bids); if (!reqBid) continue; const bidResponse = { requestId: reqBid.bidId, From 16e27db7d5fa7e41c976af457a6051282cca399a Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Tue, 6 Aug 2019 15:43:38 -0700 Subject: [PATCH 04/14] Added nobidBidAdapter.md --- modules/nobidBidAdapter.md | 58 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 modules/nobidBidAdapter.md diff --git a/modules/nobidBidAdapter.md b/modules/nobidBidAdapter.md new file mode 100644 index 00000000000..3e962217fea --- /dev/null +++ b/modules/nobidBidAdapter.md @@ -0,0 +1,58 @@ +--- +layout: bidder +title: Nobid +description: Prebid Nobid Bidder Adaptor +biddercode: nobid +hide: true +media_types: banner +gdpr_supported: true +--- + +# Overview + +``` +Module Name: Nobid Bidder Adapter +Module Type: Bidder Adapter +Maintainer: rob.dubois@nobid.io +``` + +# Description + +Module that connects to Nobid demand sources + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], // a display size + } + }, + bids: [ + { + bidder: "nobid", + params: { + siteId: + } + } + ] + },{ + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[320, 50]], // a mobile size + } + }, + bids: [ + { + bidder: "nobid", + params: { + siteId: + } + } + ] + } + ]; +``` \ No newline at end of file From 999d8b7deda455bcc40c70fc4c9b0facf6b93ee3 Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Sun, 11 Aug 2019 07:57:43 -0700 Subject: [PATCH 05/14] Removed description and added "Bid Params" section. --- modules/nobidBidAdapter.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/modules/nobidBidAdapter.md b/modules/nobidBidAdapter.md index 3e962217fea..a506d5cfdab 100644 --- a/modules/nobidBidAdapter.md +++ b/modules/nobidBidAdapter.md @@ -8,17 +8,12 @@ media_types: banner gdpr_supported: true --- -# Overview +### Bid Params -``` -Module Name: Nobid Bidder Adapter -Module Type: Bidder Adapter -Maintainer: rob.dubois@nobid.io -``` - -# Description - -Module that connects to Nobid demand sources +{: .table .table-bordered .table-striped } +| Name | Scope | Description | Example | Type | +|---------------|----------|-------------|---------|----------| +| `siteId` | required | siteId is provided by your Nobid account manager | | `integer` | # Test Parameters ``` From dbc675c3d21cc0f1f20d52f220fa8a8582585786 Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Wed, 14 Aug 2019 17:28:42 -0700 Subject: [PATCH 06/14] Added test siteId 2 for testing. --- modules/nobidBidAdapter.md | 4 ++-- test/spec/modules/nobidBidAdapter_spec.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/nobidBidAdapter.md b/modules/nobidBidAdapter.md index a506d5cfdab..b80a7f6c4b6 100644 --- a/modules/nobidBidAdapter.md +++ b/modules/nobidBidAdapter.md @@ -29,7 +29,7 @@ gdpr_supported: true { bidder: "nobid", params: { - siteId: + siteId: 2 } } ] @@ -44,7 +44,7 @@ gdpr_supported: true { bidder: "nobid", params: { - siteId: + siteId: 2 } } ] diff --git a/test/spec/modules/nobidBidAdapter_spec.js b/test/spec/modules/nobidBidAdapter_spec.js index 08f877edbde..e4f36f7ff20 100644 --- a/test/spec/modules/nobidBidAdapter_spec.js +++ b/test/spec/modules/nobidBidAdapter_spec.js @@ -16,7 +16,7 @@ describe('Nobid Adapter', function () { let bid = { 'bidder': 'nobid', 'params': { - 'siteId': 1 + 'siteId': 2 }, 'adUnitCode': 'adunit-code', 'sizes': [[300, 250]], @@ -33,7 +33,7 @@ describe('Nobid Adapter', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { - 'siteId': 1 + 'siteId': 2 }; expect(spec.isBidRequestValid(bid)).to.equal(true); @@ -50,7 +50,7 @@ describe('Nobid Adapter', function () { }); describe('buildRequests', function () { - const SITE_ID = 1; + const SITE_ID = 2; const REFERER = 'https://www.examplereferer.com'; let bidRequests = [ { @@ -124,7 +124,7 @@ describe('Nobid Adapter', function () { country: 'US', ip: '68.83.15.75', device: 'COMPUTER', - site: 1, + site: 2, bids: [ {id: 1, bdrid: 101, From d08381c78398c57df87119d7d707914e3ae5fb99 Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Sun, 25 Aug 2019 12:16:16 -0700 Subject: [PATCH 07/14] Refactored the Adapter to remove most references to the nobid object. We still need the nobid object because we have a passback tag in DFP that makes reference to it. --- modules/nobidBidAdapter.js | 271 +++++++++++++++---------------------- 1 file changed, 112 insertions(+), 159 deletions(-) diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index 0d67a206255..311b5115556 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -2,113 +2,12 @@ import * as utils from '../src/utils'; import { registerBidder } from '../src/adapters/bidderFactory'; import { BANNER } from '../src/mediaTypes'; const BIDDER_CODE = 'nobid'; -window.nobid = window.nobid || {}; -nobid.version = '1.1.0'; -nobid.status = {}; -nobid.status.bidResponseProcessed = false; -nobid.status.bidResponseTimeout = false; -nobid.timestamp = function() { - var date = new Date(); - var zp = function (val) { return (val <= 9 ? '0' + val : '' + val); } - var d = date.getDate(); - var y = date.getFullYear(); - var m = date.getMonth() + 1; - var h = date.getHours(); - var min = date.getMinutes(); - var s = date.getSeconds(); - return '' + y + '-' + zp(m) + '-' + zp(d) + ' ' + zp(h) + ':' + zp(min) + ':' + zp(s); -}; -nobid.clientDim = function() { - try { - return `${screen.width}x${screen.height}`; - } catch (e) { - console.error(e); - } -}; -nobid.a = []; -nobid.tt = encodeURIComponent(document.title); -nobid.t = nobid.timestamp(); -nobid.tz = Math.round(new Date().getTimezoneOffset()); -nobid.r = nobid.clientDim(); -nobid.log = function(msg, obj) { - var debug = (typeof utils.getParameterByName === 'function') && (utils.getParameterByName('nobid-debug')); - if (!debug) return; - if (typeof obj != 'undefined') console.log('NoBid Prebid Adapter: ' + msg, obj); - else console.log('NoBid Prebid Adapter: ' + msg); +window.nobidVersion = '1.1.0'; +function log(msg, obj) { + utils.logInfo('-NoBid- ' + msg, obj) } -nobid.getAdUnit = function(divid) { - for (var i = 0; i < nobid.a.length; i++) { - if (nobid.a[i].d === divid) { - return nobid.a[i]; - } - } - return false; -}; -nobid.resolveEndpoint = function() { - var ret = 'https://ads.servenobid.com/'; - var env = (typeof utils.getParameterByName === 'function') && (utils.getParameterByName('nobid-env')); - if (!env) ret = 'https://ads.servenobid.com/'; - else if (env == 'beta') ret = 'https://beta.servenobid.com/'; - else if (env == 'dev') ret = '//localhost:8282/'; - else if (env == 'qa') ret = 'https://qa-ads.nobid.com/'; - return ret; -} -nobid.triggerEvent = function(params, doc) { - var r = Math.floor(Math.random() * 11000); - var path = nobid.resolveEndpoint() + 'event.js?cb=' + r; - var xhr = new XMLHttpRequest(); - xhr.withCredentials = true; - xhr.open('POST', path, true); - if (!params['l']) params['l'] = doc.location.href; - xhr.send(JSON.stringify(params)); -} -nobid.adunit = function (adunitObject) { - var removeByAttrValue = function(array, attribute, value) { - for (var i = array.length - 1; i >= 0; i--) { - var entry = array[i]; - if (entry[attribute] && entry[attribute] === value) { - array.splice(i, 1); - } - } - } - var a = nobid.getAdUnit(adunitObject.div) || {}; - if (adunitObject.account) { - a.s = adunitObject.account; - } else if (nobid.s) { - a.s = nobid.s; - } - if (adunitObject.sizes) { - a.z = adunitObject.sizes; - } - if (adunitObject.div) { - a.d = adunitObject.div; - } - if (adunitObject.targeting) { - a.g = adunitObject.targeting; - } else { - a.g = {}; - } - if (adunitObject.companion) { - a.c = adunitObject.companion; - } - if (adunitObject.div) { - removeByAttrValue(nobid.a, 'd', adunitObject.div); - } - if (adunitObject.sizeMapping) { - a.sm = adunitObject.sizeMapping; - } - if (adunitObject.siteId) { - a.sid = adunitObject.siteId; - } - /* {"BIDDER_ID":{"WxH":"TAG_ID", "WxH":"TAG_ID"}} */ - if (adunitObject.rtb) { - a.rtb = adunitObject.rtb; - } - nobid.a.push(a); - return a; -}; -nobid.setup = function(bids, bidderRequest) { - var serializeState = function(divIds, siteId) { +function nobidBuildRequests(bids, bidderRequest) { + var serializeState = function(divIds, siteId, adunits) { var filterAdUnitsByIds = function(divIds, adUnits) { var filtered = []; if (!divIds || !divIds.length) { @@ -146,23 +45,93 @@ nobid.setup = function(bids, bidderRequest) { } return encodeURIComponent(ret.replace(/\%/g, '')); } + var timestamp = function() { + var date = new Date(); + var zp = function (val) { return (val <= 9 ? '0' + val : '' + val); } + var d = date.getDate(); + var y = date.getFullYear(); + var m = date.getMonth() + 1; + var h = date.getHours(); + var min = date.getMinutes(); + var s = date.getSeconds(); + return '' + y + '-' + zp(m) + '-' + zp(d) + ' ' + zp(h) + ':' + zp(min) + ':' + zp(s); + }; + var clientDim = function() { + try { + return `${screen.width}x${screen.height}`; + } catch (e) { + console.error(e); + } + } var state = {}; state['sid'] = siteId; state['l'] = topLocation(bidderRequest); - state['tt'] = nobid['tt']; + state['tt'] = encodeURIComponent(document.title); state['tt'] = state['tt'].replace(/'|;|quot;|39;|&|&|#|\r\n|\r|\n|\t|\f|\%0A|\"|\%22|\%5C|\%23|\%26|\%26|\%09/gm, ''); - state['a'] = filterAdUnitsByIds(divIds, nobid.a || []); - state['t'] = nobid.timestamp(); + state['a'] = filterAdUnitsByIds(divIds, adunits || []); + state['t'] = timestamp(); state['tz'] = Math.round(new Date().getTimezoneOffset()); - state['r'] = nobid.clientDim(); + state['r'] = clientDim(); state['lang'] = (navigator.languages && navigator.languages[0]) || navigator.language || navigator.userLanguage; state['ref'] = document.referrer; state['gdpr'] = gdprConsent(bidderRequest); return state; - }; + } + function newAdunit(adunitObject, adunits) { + var getAdUnit = function(divid, adunits) { + for (var i = 0; i < adunits.length; i++) { + if (adunits[i].d === divid) { + return adunits[i]; + } + } + return false; + } + var removeByAttrValue = function(array, attribute, value) { + for (var i = array.length - 1; i >= 0; i--) { + var entry = array[i]; + if (entry[attribute] && entry[attribute] === value) { + array.splice(i, 1); + } + } + } + var a = getAdUnit(adunitObject.div, adunits) || {}; + if (adunitObject.account) { + a.s = adunitObject.account; + } + if (adunitObject.sizes) { + a.z = adunitObject.sizes; + } + if (adunitObject.div) { + a.d = adunitObject.div; + } + if (adunitObject.targeting) { + a.g = adunitObject.targeting; + } else { + a.g = {}; + } + if (adunitObject.companion) { + a.c = adunitObject.companion; + } + if (adunitObject.div) { + removeByAttrValue(adunits, 'd', adunitObject.div); + } + if (adunitObject.sizeMapping) { + a.sm = adunitObject.sizeMapping; + } + if (adunitObject.siteId) { + a.sid = adunitObject.siteId; + } + /* {"BIDDER_ID":{"WxH":"TAG_ID", "WxH":"TAG_ID"}} */ + if (adunitObject.rtb) { + a.rtb = adunitObject.rtb; + } + adunits.push(a); + return adunits; + } /* DISCOVER SLOTS */ var divids = []; var siteId = 0; + var adunits = []; for (var i = 0; i < bids.length; i++) { var bid = bids[i]; var divid = bid.adUnitCode; @@ -170,18 +139,18 @@ nobid.setup = function(bids, bidderRequest) { var sizes = bid.sizes; siteId = (typeof bid.params['siteId'] != 'undefined' && bid.params['siteId']) ? bid.params['siteId'] : siteId; if (siteId && bid.params && bid.params.tags) { - nobid.adunit({div: divid, sizes: sizes, rtb: bid.params.tags, siteId: siteId}); + newAdunit({div: divid, sizes: sizes, rtb: bid.params.tags, siteId: siteId}, adunits); } else if (siteId) { - nobid.adunit({div: divid, sizes: sizes, siteId: siteId}); + newAdunit({div: divid, sizes: sizes, siteId: siteId}, adunits); } } if (siteId) { - return serializeState(divids, siteId); + return serializeState(divids, siteId, adunits); } else { return false; } } -nobid.ProcessBidResponse = function (response, bidRequest) { +function nobidInterpretResponse(response, bidRequest) { var findBid = function(divid, bids) { for (var i = 0; i < bids.length; i++) { if (bids[i].adUnitCode === divid) { @@ -191,9 +160,6 @@ nobid.ProcessBidResponse = function (response, bidRequest) { return false; } var bidResponses = []; - nobid.status.bidResponseProcessed = true; - nobid.status.bidResponseTimeout = false; - nobid.status.bidResponse = response; for (var i = 0; response.bids && i < response.bids.length; i++) { var bid = response.bids[i]; if (bid.bdrid < 100 || !bidRequest || !bidRequest.bidderRequest || !bidRequest.bidderRequest.bids) continue; @@ -216,13 +182,14 @@ nobid.ProcessBidResponse = function (response, bidRequest) { } return bidResponses; }; +window.nobid = window.nobid || {}; nobid.renderTag = function(doc, id, win) { - nobid.log('-NoBid Prebid Adapter- nobid.renderTag()', id); + log('nobid.renderTag()', id); if (nobid.bidResponse && nobid.bidResponse.bids) { for (var i in nobid.bidResponse.bids) { const bid = nobid.bidResponse.bids[i]; if (id == bid.id && bid.adm2) { - nobid.log('-NoBid Prebid Adapter- nobid.renderTag() found tag', id); + log('nobid.renderTag() found tag', id); var markup = bid.adm2; doc.write(markup); doc.close(); @@ -231,27 +198,6 @@ nobid.renderTag = function(doc, id, win) { } } } -nobid.cookies = {}; -nobid.cookies.get = function(name) { - var value = '; ' + document.cookie; - var parts = value.split('; ' + name + '='); - if (parts.length === 2) { - return parts.pop().split(';').shift(); - } -}; -nobid.cookies.getAll = function() { - return document.cookie.split('; ').reduce(function(map, keyValue) { - var equalPos = keyValue.indexOf('='); - map[keyValue.substr(0, equalPos)] = keyValue.substr(equalPos + 1); - return map; - }, {}); -}; -nobid.cookies.set = function(name, value, lifespanInSec) { - var d = new Date(); - d.setTime(d.getTime() + (lifespanInSec * 1000)); - var expires = 'expires=' + d.toUTCString(); - document.cookie = name + '=' + value + ';' + expires + ';path=/'; -}; export const spec = { code: BIDDER_CODE, supportedMediaTypes: [BANNER], @@ -262,7 +208,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function(bid) { - nobid.log('-NoBid Prebid Adapter- isBidRequestValid', bid); + log('isBidRequestValid', bid); return !!bid.params.siteId; }, /** @@ -272,15 +218,24 @@ export const spec = { * @return ServerRequest Info describing the request to the server. */ buildRequests: function(validBidRequests, bidderRequest) { + function resolveEndpoint() { + var ret = 'https://ads.servenobid.com/'; + var env = (typeof utils.getParameterByName === 'function') && (utils.getParameterByName('nobid-env')); + if (!env) ret = 'https://ads.servenobid.com/'; + else if (env == 'beta') ret = 'https://beta.servenobid.com/'; + else if (env == 'dev') ret = '//localhost:8282/'; + else if (env == 'qa') ret = 'https://qa-ads.nobid.com/'; + return ret; + } var buildEndpoint = function() { - return nobid.resolveEndpoint() + 'adreq?cb=' + Math.floor(Math.random() * 11000); + return resolveEndpoint() + 'adreq?cb=' + Math.floor(Math.random() * 11000); } - nobid.log('-NoBid Prebid Adapter- buildRequests', validBidRequests); + log('buildRequests', validBidRequests); if (!validBidRequests || validBidRequests.length <= 0) { - nobid.log('-NoBid Prebid Adapter- Empty validBidRequests'); + log('Empty validBidRequests'); return; } - const payload = nobid.setup(validBidRequests, bidderRequest); + const payload = nobidBuildRequests(validBidRequests, bidderRequest); if (!payload) return; const payloadString = JSON.stringify(payload).replace(/'|&|#/g, '') const endpoint = buildEndpoint(); @@ -292,16 +247,16 @@ export const spec = { }; }, /** - * Unpack the response from the server into a list of bids. - * - * @param {ServerResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ + * Unpack the response from the server into a list of bids. + * + * @param {ServerResponse} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ interpretResponse: function(serverResponse, bidRequest) { - nobid.log('-NoBid Prebid Adapter- interpretResponse', serverResponse); - nobid.log('-NoBid Prebid Adapter- interpretResponse', bidRequest); + log('interpretResponse', serverResponse); + log('interpretResponse', bidRequest); nobid.bidResponse = serverResponse.body; - return nobid.ProcessBidResponse(serverResponse.body, bidRequest); + return nobidInterpretResponse(serverResponse.body, bidRequest); }, /** @@ -318,8 +273,7 @@ export const spec = { url: 'https://s3.amazonaws.com/nobid-public/sync.html' }]; } else { - utils.logWarn('-NoBid Prebid Adapter- Please enable iframe based user sync.'); - console.log('-NoBid Prebid Adapter- Please enable iframe based user sync.', syncOptions); + utils.logWarn('-NoBid- Please enable iframe based user sync.', syncOptions); return []; } }, @@ -329,11 +283,10 @@ export const spec = { * @param {data} Containing timeout specific data */ onTimeout: function(data) { - nobid.log('-NoBid Prebid Adapter- onTimeout', data); - nobid.status.bidResponseTimeout = true; + log('Timeout', data); }, onBidWon: function(data) { - nobid.log('-NoBid Prebid Adapter- onBidWon', data); + log('BidWon', data); } } registerBidder(spec); From 385e0a35e749c65879498c84a0f2d478e30c576c Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Wed, 28 Aug 2019 10:58:57 -0700 Subject: [PATCH 08/14] Fix concurrent responses on the page --- modules/nobidBidAdapter.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index 311b5115556..f8b59cf52e8 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -163,6 +163,7 @@ function nobidInterpretResponse(response, bidRequest) { for (var i = 0; response.bids && i < response.bids.length; i++) { var bid = response.bids[i]; if (bid.bdrid < 100 || !bidRequest || !bidRequest.bidderRequest || !bidRequest.bidderRequest.bids) continue; + nobid.bidResponses['' + bid.id] = bid; var reqBid = findBid(bid.divid, bidRequest.bidderRequest.bids); if (!reqBid) continue; const bidResponse = { @@ -183,19 +184,15 @@ function nobidInterpretResponse(response, bidRequest) { return bidResponses; }; window.nobid = window.nobid || {}; +nobid.bidResponses = {}; nobid.renderTag = function(doc, id, win) { log('nobid.renderTag()', id); - if (nobid.bidResponse && nobid.bidResponse.bids) { - for (var i in nobid.bidResponse.bids) { - const bid = nobid.bidResponse.bids[i]; - if (id == bid.id && bid.adm2) { - log('nobid.renderTag() found tag', id); - var markup = bid.adm2; - doc.write(markup); - doc.close(); - break; - } - } + var bid = nobid.bidResponses['' + id]; + if (bid && bid.adm2) { + log('nobid.renderTag() found tag', id); + var markup = bid.adm2; + doc.write(markup); + doc.close(); } } export const spec = { @@ -255,7 +252,6 @@ export const spec = { interpretResponse: function(serverResponse, bidRequest) { log('interpretResponse', serverResponse); log('interpretResponse', bidRequest); - nobid.bidResponse = serverResponse.body; return nobidInterpretResponse(serverResponse.body, bidRequest); }, From 80247787e20e247f82aa3d53e6656e1d14c9fc8f Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Wed, 28 Aug 2019 17:10:02 -0700 Subject: [PATCH 09/14] Cosmetic change to log an error in case of missing ad markup --- modules/nobidBidAdapter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index f8b59cf52e8..1f7c83fca1b 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -193,7 +193,9 @@ nobid.renderTag = function(doc, id, win) { var markup = bid.adm2; doc.write(markup); doc.close(); + return; } + log('nobid.renderTag() tag NOT FOUND *ERROR*', id); } export const spec = { code: BIDDER_CODE, From b351e8940aa97dd4bd55fb6914b408737d45c03f Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Wed, 28 Aug 2019 21:21:04 -0700 Subject: [PATCH 10/14] Keep nobid.bidResponses cross adapters. --- modules/nobidBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index 1f7c83fca1b..0cf287ae868 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -184,7 +184,7 @@ function nobidInterpretResponse(response, bidRequest) { return bidResponses; }; window.nobid = window.nobid || {}; -nobid.bidResponses = {}; +nobid.bidResponses = nobid.bidResponses || {}; nobid.renderTag = function(doc, id, win) { log('nobid.renderTag()', id); var bid = nobid.bidResponses['' + id]; From e401d984254fb1e0f292a47aa5394edd220cc9fd Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Tue, 3 Sep 2019 12:59:30 -0700 Subject: [PATCH 11/14] Added GDPR support in user sync and added test coverage. gulp test-coverage gulp view-coverage --- modules/nobidBidAdapter.js | 23 +++++- test/spec/modules/nobidBidAdapter_spec.js | 95 ++++++++++++++++++++++- 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index 0cf287ae868..b10ee3ece3d 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -185,6 +185,8 @@ function nobidInterpretResponse(response, bidRequest) { }; window.nobid = window.nobid || {}; nobid.bidResponses = nobid.bidResponses || {}; +nobid.timeoutTotal = 0; +nobid.bidWonTotal = 0; nobid.renderTag = function(doc, id, win) { log('nobid.renderTag()', id); var bid = nobid.bidResponses['' + id]; @@ -264,11 +266,20 @@ export const spec = { * @param {ServerResponse[]} serverResponses List of server's responses. * @return {UserSync[]} The user syncs which should be dropped. */ - getUserSyncs: function(syncOptions, serverResponses) { + getUserSyncs: function(syncOptions, serverResponses, gdprConsent) { if (syncOptions.iframeEnabled) { + let params = ''; + if (gdprConsent && typeof gdprConsent.consentString === 'string') { + // add 'gdpr' only if 'gdprApplies' is defined + if (typeof gdprConsent.gdprApplies === 'boolean') { + params += `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { + params += `?gdpr_consent=${gdprConsent.consentString}`; + } + } return [{ type: 'iframe', - url: 'https://s3.amazonaws.com/nobid-public/sync.html' + url: 'https://s3.amazonaws.com/nobid-public/sync.html'+params }]; } else { utils.logWarn('-NoBid- Please enable iframe based user sync.', syncOptions); @@ -281,10 +292,14 @@ export const spec = { * @param {data} Containing timeout specific data */ onTimeout: function(data) { - log('Timeout', data); + nobid.timeoutTotal++; + log('Timeout total: '+nobid.timeoutTotal, data); + return nobid.timeoutTotal; }, onBidWon: function(data) { - log('BidWon', data); + nobid.bidWonTotal++; + log('BidWon total: '+nobid.bidWonTotal, data); + return nobid.bidWonTotal; } } registerBidder(spec); diff --git a/test/spec/modules/nobidBidAdapter_spec.js b/test/spec/modules/nobidBidAdapter_spec.js index e4f36f7ff20..8973461bf9a 100644 --- a/test/spec/modules/nobidBidAdapter_spec.js +++ b/test/spec/modules/nobidBidAdapter_spec.js @@ -120,6 +120,7 @@ describe('Nobid Adapter', function () { const ADMARKUP_300x250 = 'ADMARKUP-300x250'; const PRICE_300x250 = 0.51; const REQUEST_ID = '3db3773286ee59'; + const DEAL_ID = 'deal123'; let response = { country: 'US', ip: '68.83.15.75', @@ -129,6 +130,7 @@ describe('Nobid Adapter', function () { {id: 1, bdrid: 101, divid: ADUNIT_300x250, + dealid: DEAL_ID, creativeid: CREATIVE_ID_300x250, size: {'w': 300, 'h': 250}, adm: ADMARKUP_300x250, @@ -145,7 +147,7 @@ describe('Nobid Adapter', function () { width: 300, height: 250, creativeId: CREATIVE_ID_300x250, - dealId: '', + dealId: DEAL_ID, currency: 'USD', netRevenue: true, ttl: 300, @@ -161,7 +163,96 @@ describe('Nobid Adapter', function () { }] } let result = spec.interpretResponse({ body: response }, {bidderRequest: bidderRequest}); - expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); ; + expect(result.length).to.equal(expectedResponse.length); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + expect(result[0].requestId).to.equal(expectedResponse[0].requestId); + expect(result[0].cpm).to.equal(expectedResponse[0].cpm); }); + + it('should get correct empty response', function () { + let bidderRequest = { + bids: [{ + bidId: REQUEST_ID, + adUnitCode: ADUNIT_300x250+'1' + }] + } + let result = spec.interpretResponse({ body: response }, {bidderRequest: bidderRequest}); + expect(result.length).to.equal(0); + }); + + it('should get correct deal id', function () { + let expectedResponse = [ + { + requestId: REQUEST_ID, + cpm: PRICE_300x250, + width: 300, + height: 250, + creativeId: CREATIVE_ID_300x250, + dealId: DEAL_ID, + currency: 'USD', + netRevenue: true, + ttl: 300, + ad: ADMARKUP_300x250, + mediaType: 'banner' + } + ]; + + let bidderRequest = { + bids: [{ + bidId: REQUEST_ID, + adUnitCode: ADUNIT_300x250 + }] + } + let result = spec.interpretResponse({ body: response }, {bidderRequest: bidderRequest}); + expect(result.length).to.equal(expectedResponse.length); + expect(result[0].dealId).to.equal(expectedResponse[0].dealId); + }); + }); + + describe('getUserSyncs', function () { + const GDPR_CONSENT_STRING = "GDPR_CONSENT_STRING"; + it('should get correct user sync when iframeEnabled', function () { + let pixel = spec.getUserSyncs({iframeEnabled: true}) + expect(pixel[0].type).to.equal('iframe'); + expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html'); + }); + + it('should get correct user sync when iframeEnabled and pixelEnabled', function () { + let pixel = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}) + expect(pixel[0].type).to.equal('iframe'); + expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html'); + }); + + it('should get correct user sync when iframeEnabled', function () { + let pixel = spec.getUserSyncs({iframeEnabled: true}, {}, {gdprApplies:true, consentString:GDPR_CONSENT_STRING}) + expect(pixel[0].type).to.equal('iframe'); + expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html?gdpr=1&gdpr_consent='+GDPR_CONSENT_STRING); + }); + + it('should get correct user sync when !iframeEnabled', function () { + let pixel = spec.getUserSyncs({iframeEnabled: false}) + expect(pixel.length).to.equal(0); + }); + + it('should get correct user sync when !iframeEnabled', function () { + let pixel = spec.getUserSyncs({}) + expect(pixel.length).to.equal(0); + }); + }); + + describe('onTimeout', function (syncOptions) { + it('should increment timeoutTotal', function () { + let timeoutTotal = spec.onTimeout() + expect(timeoutTotal).to.equal(1); + }); + }); + + describe('onBidWon', function (syncOptions) { + it('should increment bidWonTotal', function () { + let bidWonTotal = spec.onBidWon() + expect(bidWonTotal).to.equal(1); + }); + }); + }); From 2e7216ee0d5874c7f14c67747a07268f6101de76 Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Tue, 3 Sep 2019 15:04:22 -0700 Subject: [PATCH 12/14] Padding issues --- modules/nobidBidAdapter.js | 2 +- test/spec/modules/nobidBidAdapter_spec.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index b10ee3ece3d..94935bf0f8d 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -276,7 +276,7 @@ export const spec = { } else { params += `?gdpr_consent=${gdprConsent.consentString}`; } - } + } return [{ type: 'iframe', url: 'https://s3.amazonaws.com/nobid-public/sync.html'+params diff --git a/test/spec/modules/nobidBidAdapter_spec.js b/test/spec/modules/nobidBidAdapter_spec.js index 8973461bf9a..3f849cca40d 100644 --- a/test/spec/modules/nobidBidAdapter_spec.js +++ b/test/spec/modules/nobidBidAdapter_spec.js @@ -168,7 +168,7 @@ describe('Nobid Adapter', function () { expect(result[0].requestId).to.equal(expectedResponse[0].requestId); expect(result[0].cpm).to.equal(expectedResponse[0].cpm); }); - + it('should get correct empty response', function () { let bidderRequest = { bids: [{ @@ -179,7 +179,7 @@ describe('Nobid Adapter', function () { let result = spec.interpretResponse({ body: response }, {bidderRequest: bidderRequest}); expect(result.length).to.equal(0); }); - + it('should get correct deal id', function () { let expectedResponse = [ { @@ -209,7 +209,7 @@ describe('Nobid Adapter', function () { }); }); - + describe('getUserSyncs', function () { const GDPR_CONSENT_STRING = "GDPR_CONSENT_STRING"; it('should get correct user sync when iframeEnabled', function () { @@ -240,7 +240,7 @@ describe('Nobid Adapter', function () { expect(pixel.length).to.equal(0); }); }); - + describe('onTimeout', function (syncOptions) { it('should increment timeoutTotal', function () { let timeoutTotal = spec.onTimeout() From 491843ae46b9cbc58e4e792f216e245e96ea220b Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Tue, 3 Sep 2019 15:32:42 -0700 Subject: [PATCH 13/14] Fix padding issues --- modules/nobidBidAdapter.js | 6 ++--- test/spec/modules/nobidBidAdapter_spec.js | 28 +++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/modules/nobidBidAdapter.js b/modules/nobidBidAdapter.js index 94935bf0f8d..ce4c25d75fa 100644 --- a/modules/nobidBidAdapter.js +++ b/modules/nobidBidAdapter.js @@ -279,7 +279,7 @@ export const spec = { } return [{ type: 'iframe', - url: 'https://s3.amazonaws.com/nobid-public/sync.html'+params + url: 'https://s3.amazonaws.com/nobid-public/sync.html' + params }]; } else { utils.logWarn('-NoBid- Please enable iframe based user sync.', syncOptions); @@ -293,12 +293,12 @@ export const spec = { */ onTimeout: function(data) { nobid.timeoutTotal++; - log('Timeout total: '+nobid.timeoutTotal, data); + log('Timeout total: ' + nobid.timeoutTotal, data); return nobid.timeoutTotal; }, onBidWon: function(data) { nobid.bidWonTotal++; - log('BidWon total: '+nobid.bidWonTotal, data); + log('BidWon total: ' + nobid.bidWonTotal, data); return nobid.bidWonTotal; } } diff --git a/test/spec/modules/nobidBidAdapter_spec.js b/test/spec/modules/nobidBidAdapter_spec.js index 3f849cca40d..adf809626bf 100644 --- a/test/spec/modules/nobidBidAdapter_spec.js +++ b/test/spec/modules/nobidBidAdapter_spec.js @@ -172,8 +172,8 @@ describe('Nobid Adapter', function () { it('should get correct empty response', function () { let bidderRequest = { bids: [{ - bidId: REQUEST_ID, - adUnitCode: ADUNIT_300x250+'1' + bidId: REQUEST_ID, + adUnitCode: ADUNIT_300x250 + '1' }] } let result = spec.interpretResponse({ body: response }, {bidderRequest: bidderRequest}); @@ -207,7 +207,7 @@ describe('Nobid Adapter', function () { expect(result.length).to.equal(expectedResponse.length); expect(result[0].dealId).to.equal(expectedResponse[0].dealId); }); - + }); describe('getUserSyncs', function () { @@ -217,24 +217,24 @@ describe('Nobid Adapter', function () { expect(pixel[0].type).to.equal('iframe'); expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html'); }); - + it('should get correct user sync when iframeEnabled and pixelEnabled', function () { - let pixel = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}) - expect(pixel[0].type).to.equal('iframe'); - expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html'); - }); - + let pixel = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}) + expect(pixel[0].type).to.equal('iframe'); + expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html'); + }); + it('should get correct user sync when iframeEnabled', function () { - let pixel = spec.getUserSyncs({iframeEnabled: true}, {}, {gdprApplies:true, consentString:GDPR_CONSENT_STRING}) + let pixel = spec.getUserSyncs({iframeEnabled: true}, {}, {gdprApplies: true, consentString: GDPR_CONSENT_STRING}) expect(pixel[0].type).to.equal('iframe'); - expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html?gdpr=1&gdpr_consent='+GDPR_CONSENT_STRING); + expect(pixel[0].url).to.equal('https://s3.amazonaws.com/nobid-public/sync.html?gdpr=1&gdpr_consent=' + GDPR_CONSENT_STRING); }); - + it('should get correct user sync when !iframeEnabled', function () { let pixel = spec.getUserSyncs({iframeEnabled: false}) expect(pixel.length).to.equal(0); }); - + it('should get correct user sync when !iframeEnabled', function () { let pixel = spec.getUserSyncs({}) expect(pixel.length).to.equal(0); @@ -255,4 +255,4 @@ describe('Nobid Adapter', function () { }); }); -}); +}); \ No newline at end of file From 8060de845b794330c29fe0b3952c8bb7762d55f8 Mon Sep 17 00:00:00 2001 From: Reda Guermas Date: Tue, 3 Sep 2019 15:52:33 -0700 Subject: [PATCH 14/14] Fix padding --- test/spec/modules/nobidBidAdapter_spec.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/spec/modules/nobidBidAdapter_spec.js b/test/spec/modules/nobidBidAdapter_spec.js index adf809626bf..5134958d218 100644 --- a/test/spec/modules/nobidBidAdapter_spec.js +++ b/test/spec/modules/nobidBidAdapter_spec.js @@ -207,11 +207,10 @@ describe('Nobid Adapter', function () { expect(result.length).to.equal(expectedResponse.length); expect(result[0].dealId).to.equal(expectedResponse[0].dealId); }); - }); describe('getUserSyncs', function () { - const GDPR_CONSENT_STRING = "GDPR_CONSENT_STRING"; + const GDPR_CONSENT_STRING = 'GDPR_CONSENT_STRING'; it('should get correct user sync when iframeEnabled', function () { let pixel = spec.getUserSyncs({iframeEnabled: true}) expect(pixel[0].type).to.equal('iframe'); @@ -238,7 +237,7 @@ describe('Nobid Adapter', function () { it('should get correct user sync when !iframeEnabled', function () { let pixel = spec.getUserSyncs({}) expect(pixel.length).to.equal(0); - }); + }); }); describe('onTimeout', function (syncOptions) { @@ -254,5 +253,4 @@ describe('Nobid Adapter', function () { expect(bidWonTotal).to.equal(1); }); }); - -}); \ No newline at end of file +});