From 302560ffdb1f2849be8c1a3a3be3103fa7be04df Mon Sep 17 00:00:00 2001 From: Pollux <30473914+polluxnetwork@users.noreply.github.com> Date: Tue, 15 Aug 2017 18:00:48 +0100 Subject: [PATCH] Add Pollux Adapter (#1431) * Added PolluxNetwork Bid Adapter Added module, test spec and integration example for Pollux Network Bid Adapter * Update Pollux domain Update Pollux default domain on prebid adapter * Export getParameterByName method On Utils.js make getParameterByName method public * Executed changes requested by @jaiminpanchal27 on 2017-08-01 Moved zone_728x90.html to integrationExamples/gpt/pollux_zone_728x90.html; Added bidRequest as second parameter to bidfactory.createBid() on Pollux Bid Adapter; Added more test cases to increase test coverage (at least 85%); Review Ref: - https://github.com/prebid/Prebid.js/pull/1431#pullrequestreview-53608436 * Fixed Eslint errors on commit f745fe1 * Executed changes requested on PR#1431 review #54993573 - Removed $$PREBID_GLOBAL$$ public vars in unit test; - Moved stubs creation and its restoration to beforeEach and afterEach hooks in unit test; - Exposed polluxHandler method on polluxBidAdapter. * Remove redundant export This line was added in #1409, removing this then I'll merge --- .../gpt/pollux_zone_728x90.html | 104 +++++++++++ modules/polluxBidAdapter.js | 97 ++++++++++ test/spec/modules/polluxBidAdapter_spec.js | 172 ++++++++++++++++++ 3 files changed, 373 insertions(+) create mode 100644 integrationExamples/gpt/pollux_zone_728x90.html create mode 100644 modules/polluxBidAdapter.js create mode 100644 test/spec/modules/polluxBidAdapter_spec.js diff --git a/integrationExamples/gpt/pollux_zone_728x90.html b/integrationExamples/gpt/pollux_zone_728x90.html new file mode 100644 index 00000000000..ecede9b5db2 --- /dev/null +++ b/integrationExamples/gpt/pollux_zone_728x90.html @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + test + + + +
+ +
+ + \ No newline at end of file diff --git a/modules/polluxBidAdapter.js b/modules/polluxBidAdapter.js new file mode 100644 index 00000000000..54c2122ec36 --- /dev/null +++ b/modules/polluxBidAdapter.js @@ -0,0 +1,97 @@ +import bidfactory from 'src/bidfactory'; +import bidmanager from 'src/bidmanager'; +import * as utils from 'src/utils'; +import adloader from 'src/adloader'; +import adaptermanager from 'src/adaptermanager'; +import { STATUS } from 'src/constants'; + +// Prebid adapter for Pollux header bidding client +function PolluxBidAdapter() { + function _callBids(params) { + var bidderUrl = (window.location.protocol) + '//adn.plxnt.com/prebid'; + var bids = params.bids || []; + for (var i = 0; i < bids.length; i++) { + var request_obj = {}; + var bid = bids[i]; + // check params + if (bid.params.zone) { + var domain = utils.getParameterByName('domain'); + var tracker2 = utils.getParameterByName('tracker2'); + if (domain) { + request_obj.domain = domain; + } else { + request_obj.domain = window.location.host; + } + if (tracker2) { + request_obj.tracker2 = tracker2; + } + request_obj.zone = bid.params.zone; + } else { + utils.logError('required param "zone" is missing', 'polluxHandler'); + continue; + } + var parsedSizes = utils.parseSizesInput(bid.sizes); + var parsedSizesLength = parsedSizes.length; + if (parsedSizesLength > 0) { + // first value should be "size" + request_obj.size = parsedSizes[0]; + if (parsedSizesLength > 1) { + // any subsequent values should be "promo_sizes" + var promo_sizes = []; + for (var j = 1; j < parsedSizesLength; j++) { + promo_sizes.push(parsedSizes[j]); + } + request_obj.promo_sizes = promo_sizes.join(','); + } + } + // detect urls + request_obj.callback_id = bid.bidId; + // set a different url bidder + if (bid.bidderUrl) { + bidderUrl = bid.bidderUrl; + } + var prebidUrl = bidderUrl + '?' + utils.parseQueryStringParameters(request_obj); + utils.logMessage('Pollux request built: ' + prebidUrl); + adloader.loadScript(prebidUrl, null, true); + } + } + + // expose the callback to global object + function _polluxHandler (response) { + // pollux handler + var bidObject = {}; + var callback_id = response.callback_id; + var placementCode = ''; + var bidObj = utils.getBidRequest(callback_id); + if (bidObj) { + placementCode = bidObj.placementCode; + } + if (bidObj && response.cpm > 0 && !!response.ad) { + bidObject = bidfactory.createBid(STATUS.GOOD, bidObj); + bidObject.bidderCode = bidObj.bidder; + bidObject.mediaType = response.mediaType; + bidObject.cpm = parseFloat(response.cpm); + if (response.ad_type === 'url') { + bidObject.adUrl = response.ad; + } else { + bidObject.ad = response.ad; + } + bidObject.width = response.width; + bidObject.height = response.height; + } else { + bidObject = bidfactory.createBid(STATUS.NO_BID, bidObj); + bidObject.bidderCode = 'pollux'; + utils.logMessage('No prebid response from polluxHandler for placement code ' + placementCode); + } + bidmanager.addBidResponse(placementCode, bidObject); + }; + $$PREBID_GLOBAL$$.polluxHandler = _polluxHandler; + // Export the `callBids` function, so that Prebid.js can execute + // this function when the page asks to send out bid requests. + return { + callBids: _callBids, + polluxHandler: _polluxHandler + }; +}; +adaptermanager.registerBidAdapter(new PolluxBidAdapter(), 'pollux'); +module.exports = PolluxBidAdapter; diff --git a/test/spec/modules/polluxBidAdapter_spec.js b/test/spec/modules/polluxBidAdapter_spec.js new file mode 100644 index 00000000000..1bcfe28124d --- /dev/null +++ b/test/spec/modules/polluxBidAdapter_spec.js @@ -0,0 +1,172 @@ +describe('Pollux Bid Adapter tests', function () { + var expect = require('chai').expect; + var urlParse = require('url-parse'); + var querystringify = require('querystringify'); + var Adapter = require('modules/polluxBidAdapter'); + var adLoader = require('src/adloader'); + var bidmanager = require('src/bidmanager'); + var utils = require('src/utils'); + + var stubLoadScript; + var stubAddBidResponse; + var polluxAdapter; + + // mock golbal _bidsRequested var + var bidsRequested = []; + utils.getBidRequest = function (id) { + return bidsRequested.map(bidSet => bidSet.bids.find(bid => bid.bidId === id)).find(bid => bid); + }; + + beforeEach(function () { + polluxAdapter = new Adapter(); + bidsRequested = []; + stubLoadScript = sinon.stub(adLoader, 'loadScript'); + stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); + }); + + afterEach(function () { + stubLoadScript.restore(); + stubAddBidResponse.restore(); + }); + + describe('creation of bid url', function () { + it('bid request for single placement', function () { + var params = { + bidderCode: 'pollux', + bids: [{ + placementCode: 'div-gpt-ad-1460505661639-0', + bidId: '21fe992ca48d55', + bidder: 'pollux', + sizes: [[300, 250]], + params: { zone: '1806' } + }] + }; + + polluxAdapter.callBids(params); + + var bidUrl = stubLoadScript.getCall(0).args[0]; + + sinon.assert.calledOnce(stubLoadScript); + + var parsedBidUrl = urlParse(bidUrl); + var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); + + expect(parsedBidUrlQueryString).to.have.property('zone').and.to.equal('1806'); + expect(parsedBidUrlQueryString).to.have.property('domain').and.to.have.length.above(1); + }); + }); + + describe('handling bid response', function () { + it('should return complete bid response adUrl', function() { + var params = { + bidderCode: 'pollux', + bids: [{ + placementCode: 'div-gpt-ad-1460505661639-0', + sizes: [[300, 250]], + bidId: '21fe992ca48d55', + bidder: 'pollux', + params: { zone: '1806' } + }] + }; + + var response = { + cpm: 0.5, + width: 300, + height: 250, + callback_id: '21fe992ca48d55', + ad: 'some.ad.url', + ad_type: 'url', + zone: 1806 + }; + + polluxAdapter.callBids(params); + bidsRequested.push(params); + polluxAdapter.polluxHandler(response); + + sinon.assert.calledOnce(stubAddBidResponse); + + var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; + var bidObject1 = stubAddBidResponse.getCall(0).args[1]; + + expect(bidPlacementCode1).to.equal('div-gpt-ad-1460505661639-0'); + expect(bidObject1.bidderCode).to.equal('pollux'); + expect(bidObject1.cpm).to.equal(0.5); + expect(bidObject1.width).to.equal(300); + expect(bidObject1.height).to.equal(250); + expect(bidObject1.adUrl).to.have.length.above(1); + }); + + it('should return complete bid response ad (html)', function() { + var params = { + bidderCode: 'pollux', + bids: [{ + placementCode: 'div-gpt-ad-1460505661639-0', + sizes: [[300, 250]], + bidId: '21fe992ca48d55', + bidder: 'pollux', + params: { zone: '1806' } + }] + }; + + var response = { + cpm: 0.5, + width: 300, + height: 250, + callback_id: '21fe992ca48d55', + ad: '', + ad_type: 'html', + zone: 1806 + }; + + polluxAdapter.callBids(params); + bidsRequested.push(params); + polluxAdapter.polluxHandler(response); + + sinon.assert.calledOnce(stubAddBidResponse); + + var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; + var bidObject1 = stubAddBidResponse.getCall(0).args[1]; + + expect(bidPlacementCode1).to.equal('div-gpt-ad-1460505661639-0'); + expect(bidObject1.bidderCode).to.equal('pollux'); + expect(bidObject1.cpm).to.equal(0.5); + expect(bidObject1.width).to.equal(300); + expect(bidObject1.height).to.equal(250); + expect(bidObject1.ad).to.have.length.above(1); + }); + + it('should return no bid response', function() { + var params = { + bidderCode: 'pollux', + bids: [{ + placementCode: 'div-gpt-ad-1460505661639-0', + sizes: [[300, 250]], + bidId: '21fe992ca48d55', + bidder: 'pollux', + params: { zone: '276' } + }] + }; + + var response = { + cpm: null, + width: null, + height: null, + callback_id: null, + ad: null, + zone: null + }; + + polluxAdapter.callBids(params); + bidsRequested.push(params); + polluxAdapter.polluxHandler(response); + + sinon.assert.calledOnce(stubAddBidResponse); + + var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; + var bidObject1 = stubAddBidResponse.getCall(0).args[1]; + + expect(bidPlacementCode1).to.equal(''); + expect(bidObject1.bidderCode).to.equal('pollux'); + }); + }); +});