From b87dc31bd3087e0785bb9a822bcc64b7db44d5f0 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Sun, 15 Oct 2017 18:18:31 +0800 Subject: [PATCH 01/24] Add v1.0 adapter skeleton --- modules/quantcastBidAdapter.js | 251 ++++++++++++++++++--------------- modules/quantcastBidAdapter.md | 15 ++ 2 files changed, 154 insertions(+), 112 deletions(-) create mode 100644 modules/quantcastBidAdapter.md diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index f199e9fad30..75bd32a965c 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,128 +1,155 @@ -const utils = require('src/utils.js'); -const bidfactory = require('src/bidfactory.js'); -const bidmanager = require('src/bidmanager.js'); -const ajax = require('src/ajax.js'); -const CONSTANTS = require('src/constants.json'); -const adaptermanager = require('src/adaptermanager'); -const QUANTCAST_CALLBACK_URL = 'http://global.qc.rtb.quantserve.com:8080/qchb'; - -var QuantcastAdapter = function QuantcastAdapter() { - const BIDDER_CODE = 'quantcast'; - - const DEFAULT_BID_FLOOR = 0.0000000001; - let bidRequests = {}; - - let returnEmptyBid = function(bidId) { - var bidRequested = utils.getBidRequest(bidId); - if (!utils.isEmpty(bidRequested)) { - let bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bidRequested); - bid.bidderCode = BIDDER_CODE; - bidmanager.addBidResponse(bidRequested.placementCode, bid); - } - }; +import adapterManager from "src/adaptermanager"; +import * as utils from "src/utils"; +import { registerBidder } from "src/adapters/bidderFactory"; + +const BIDDER_CODE = "quantcast"; +const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; +const DEFAULT_BID_FLOOR = 0.0000000001; + +let publisherTagURL; +switch (window.location.protocol) { + case "https:": + _publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8080/qchb`; + break; + default: + _publisherTagURL = `http://${QUANTCAST_CALLBACK_URL}:8443/qchb`; +} + +/** + * The documentation for Prebid.js Adapter 1.0 can be found at link below, + * http://prebid.org/dev-docs/bidder-adapter-1.html + */ +export const spec = { + code: BIDDER_CODE, + + // `BaseAdapter` model saves adapter from having to make the AJAX call + // provides consistency adapter structure. + // `BaseAdapter` defines 4 entry points, + // - `isBidRequestValid` + // - `buildRequests` + // - `interpretResponse` + // - `getUserSyncs` + + /** + * Verify the `AdUnits.bids` response with `true` for valid request and `false` + * for invalid request. + * + * @param {object} bid + * @return boolean `true` is this is a valid bid, and `false` otherwise + */ + isBidRequestValid(bid) { + // TODO: How to validate a bid request? @tmax + }, + + /** + * Make a server request when the page asks Prebid.js for bids from a list of + * `BidRequests`. + * + * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be send to Quantcast server + * @return ServerRequest information describing the request to the server. + */ + buildRequests(bidRequests) { + const bids = bidRequests || []; + + const referrer = utils.getTopWindowUrl(); + const loc = utils.getTopWindowLocation(); + const domain = loc.hostname; + + const bidRequests = bids.map(bid => { + const bidSizes = []; + + bid.sizes.forEach(size => { + bidSizes.push({ + width: size[0], + height: size[1] + }); + }); - // expose the callback to the global object: - $$PREBID_GLOBAL$$.handleQuantcastCB = function (responseText) { - if (utils.isEmpty(responseText)) { - return; - } - let response = null; - try { - response = JSON.parse(responseText); - } catch (e) { - // Malformed JSON - utils.logError("Malformed JSON received from server - can't do anything here"); - return; - } + // Request Data Format can be found at https://wiki.corp.qc/display/adinf/QCX + const requestData = { + publisherId: bid.params.publisherId, + requestId: bid.bidId, + imp: [ + { + banner: { + batter: bid.params.battr, + size: bidSizes + }, + placementCode: bid.placementCode, + bidFloor: bid.params.bidFloor || DEFAULT_BID_FLOOR + } + ], + site: { + page: loc.href, + referrer, + domain + }, + bidId: bid.bidId + }; - if (response === null || !response.hasOwnProperty('bids') || utils.isEmpty(response.bids)) { - utils.logError("Sub-optimal JSON received from server - can't do anything here"); - return; + return { + method: "POST", + url: publisherTagURL, + data: JSON.stringify(requestData), + withCredentials: true + }; + }); + + return bidRequests; + }, + + /** + * Function get called when the browser has received the response from Quantcast server. + * The function parse the response and create a `bidResponse` object containing one/more bids. + * Returns an empty array if no valid bids + * + * Response Data Format can be found at https://wiki.corp.qc/display/adinf/QCX + * + * @param {*} serverResponse A successful response from Quantcast server. + * @return {Bid[]} An array of bids which were nested inside the server. + * + */ + interpretResponse(serverResponse) { + if (utils.isEmpty(serverResponse)) { + return []; } - for (let i = 0; i < response.bids.length; i++) { - let seatbid = response.bids[i]; - let key = seatbid.placementCode; - var request = bidRequests[key]; - if (request === null || request === undefined) { - return returnEmptyBid(seatbid.placementCode); - } - // This line is required since this is the field - // that bidfactory.createBid looks for - request.bidId = request.imp[0].placementCode; - let responseBid = bidfactory.createBid(CONSTANTS.STATUS.GOOD, request); - - responseBid.cpm = seatbid.cpm; - responseBid.ad = seatbid.ad; - responseBid.height = seatbid.height; - responseBid.width = seatbid.width; - responseBid.bidderCode = response.bidderCode; - responseBid.requestId = request.requestId; - responseBid.bidderCode = BIDDER_CODE; - - bidmanager.addBidResponse(request.bidId, responseBid); + let response; + try { + response = JSON.parse(serverResponse); + } catch (error) { + utils.logError("Malformed JSON received from Quantcast server"); + return []; } - }; - function callBids(params) { - let bids = params.bids || []; - if (bids.length === 0) { + if ( + response === null || + !response.hasOwnProperty("bids") || + utils.isEmpty(response.bids) + ) { + utils.logError("Sub-optimal JSON received from Quantcast server"); return; } - let referrer = utils.getTopWindowUrl(); - let loc = utils.getTopWindowLocation(); - let domain = loc.hostname; - let publisherId = 0; - - publisherId = '' + bids[0].params.publisherId; - utils._each(bids, function(bid) { - let key = bid.placementCode; - var bidSizes = []; - utils._each(bid.sizes, function (size) { - bidSizes.push({ - 'width': size[0], - 'height': size[1] - }); - }); + const bidResponses = response.bids.map(bid => { + const { ad, cpm, width, height } = bid; - bidRequests[key] = bidRequests[key] || { - 'publisherId': publisherId, - 'requestId': bid.bidId, - 'bidId': bid.bidId, - 'site': { - 'page': loc.href, - 'referrer': referrer, - 'domain': domain, - }, - 'imp': [{ - - 'banner': { - 'battr': bid.params.battr, - 'sizes': bidSizes, - }, - 'placementCode': bid.placementCode, - 'bidFloor': bid.params.bidFloor || DEFAULT_BID_FLOOR, - }] + return { + ad, + cpm, + width, + height, + requestId: response.requestId, + bidderCode: response.bidderCode || BIDDER_CODE }; }); - utils._each(bidRequests, function (bidRequest) { - ajax.ajax(QUANTCAST_CALLBACK_URL, $$PREBID_GLOBAL$$.handleQuantcastCB, JSON.stringify(bidRequest), { - method: 'POST', - withCredentials: true - }); - }); - } + return bidResponses; + }, - // Export the `callBids` function, so that Prebid.js can execute - // this function when the page asks to send out bid requests. - return { - callBids: callBids, - QUANTCAST_CALLBACK_URL: QUANTCAST_CALLBACK_URL - }; + getUserSyncs(syncOptions) { + // TODO: What does user syncs do? @tmax + } }; -adaptermanager.registerBidAdapter(new QuantcastAdapter(), 'quantcast'); - -module.exports = QuantcastAdapter; +registerBidder(spec); diff --git a/modules/quantcastBidAdapter.md b/modules/quantcastBidAdapter.md new file mode 100644 index 00000000000..0537578dab4 --- /dev/null +++ b/modules/quantcastBidAdapter.md @@ -0,0 +1,15 @@ +# Overview + +Module Name: Quantcast Bidder Adapter +Module Type: Bidder Adapter +Maintainer: xli@quantcast.com + +# Description + +Module that connects to Quantcast demand sources to fetch bids. + +# Test Parameters + +```js +const adUnits = [{}]; +``` \ No newline at end of file From 275b7728e5bb0ee97c249aceda3b53997a8de765 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Sun, 15 Oct 2017 18:23:10 +0800 Subject: [PATCH 02/24] Fix a typo in variable name declaration --- modules/quantcastBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 75bd32a965c..2ed6c59e549 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -9,10 +9,10 @@ const DEFAULT_BID_FLOOR = 0.0000000001; let publisherTagURL; switch (window.location.protocol) { case "https:": - _publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8080/qchb`; + publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8080/qchb`; break; default: - _publisherTagURL = `http://${QUANTCAST_CALLBACK_URL}:8443/qchb`; + publisherTagURL = `http://${QUANTCAST_CALLBACK_URL}:8443/qchb`; } /** From 017c89c87c5fdbd21f526dc72fdd0d935ccf1428 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Thu, 19 Oct 2017 09:58:12 +0800 Subject: [PATCH 03/24] Change spec dependencies --- test/spec/modules/quantcastBidAdapter_spec.js | 195 ++++++++++-------- 1 file changed, 109 insertions(+), 86 deletions(-) diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 05748d85845..6f13ece523f 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,28 +1,27 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/quantcastBidAdapter'; -import * as ajax from 'src/ajax'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; +import { expect } from "chai"; +import Adapter from "../../../modules/quantcastBidAdapter"; +import bidManager from "../../../src/bidmanager"; +import adLoader from "../../../src/adloader"; -describe('quantcast adapter', () => { +describe("Quantcast adapter", () => { let bidsRequestedOriginal; let adapter; let sandbox; let ajaxStub; const bidderRequest = { - bidderCode: 'quantcast', - requestId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', - bidderRequestId: '1cc026909c24c8', + bidderCode: "quantcast", + requestId: "595ffa73-d78a-46c9-b18e-f99548a5be6b", + bidderRequestId: "1cc026909c24c8", bids: [ { - bidId: '2f7b179d443f14', - bidder: 'quantcast', - placementCode: 'div-gpt-ad-1438287399331-0', + bidId: "2f7b179d443f14", + bidder: "quantcast", + placementCode: "div-gpt-ad-1438287399331-0", sizes: [[300, 250], [300, 600]], params: { - publisherId: 'test-publisher', - battr: [1, 2], + publisherId: "test-publisher", + battr: [1, 2] } } ] @@ -34,7 +33,7 @@ describe('quantcast adapter', () => { adapter = new Adapter(); sandbox = sinon.sandbox.create(); - ajaxStub = sandbox.stub(ajax, 'ajax'); + ajaxStub = sandbox.stub(ajax, "ajax"); }); afterEach(() => { @@ -43,138 +42,158 @@ describe('quantcast adapter', () => { $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; }); - describe('sizes', () => { + describe("sizes", () => { let bidderRequest = { - bidderCode: 'quantcast', - requestId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', - bidderRequestId: '1cc026909c24c8', + bidderCode: "quantcast", + requestId: "595ffa73-d78a-46c9-b18e-f99548a5be6b", + bidderRequestId: "1cc026909c24c8", bids: [ { - bidId: '2f7b179d443f14', - bidder: 'quantcast', - placementCode: 'div-gpt-ad-1438287399331-0', + bidId: "2f7b179d443f14", + bidder: "quantcast", + placementCode: "div-gpt-ad-1438287399331-0", sizes: [[300, 250], [300, 600]], params: { - publisherId: 'test-publisher', - battr: [1, 2], + publisherId: "test-publisher", + battr: [1, 2] } } ] }; - it('should not call server when empty input is provided', () => { + it("should not call server when empty input is provided", () => { adapter.callBids({}); sinon.assert.notCalled(ajaxStub); }); - it('should call server once even when multiple sizes are passed', () => { + it("should call server once even when multiple sizes are passed", () => { adapter.callBids(bidderRequest); sinon.assert.calledOnce(ajaxStub); expect(ajaxStub.firstCall.args[0]).to.eql(adapter.QUANTCAST_CALLBACK_URL); - expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a('function'); - expect(ajaxStub.firstCall.args[2]).to.include('div-gpt-ad-1438287399331-0'); - expect(ajaxStub.firstCall.args[2]).to.include('test-publisher'); - expect(ajaxStub.firstCall.args[2]).to.include('2f7b179d443f14'); - expect(ajaxStub.firstCall.args[3]).to.eql({method: 'POST', withCredentials: true}); + expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a("function"); + expect(ajaxStub.firstCall.args[2]).to.include( + "div-gpt-ad-1438287399331-0" + ); + expect(ajaxStub.firstCall.args[2]).to.include("test-publisher"); + expect(ajaxStub.firstCall.args[2]).to.include("2f7b179d443f14"); + expect(ajaxStub.firstCall.args[3]).to.eql({ + method: "POST", + withCredentials: true + }); }); - it('should call server once when one size is passed', () => { + it("should call server once when one size is passed", () => { bidderRequest.bids[0].sizes = [728, 90]; adapter.callBids(bidderRequest); sinon.assert.calledOnce(ajaxStub); expect(ajaxStub.firstCall.args[0]).to.eql(adapter.QUANTCAST_CALLBACK_URL); - expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a('function'); - expect(ajaxStub.firstCall.args[3]).to.eql({method: 'POST', withCredentials: true}); + expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a("function"); + expect(ajaxStub.firstCall.args[3]).to.eql({ + method: "POST", + withCredentials: true + }); }); - it('should call server once when size is passed as string', () => { - bidderRequest.bids[0].sizes = '728x90'; + it("should call server once when size is passed as string", () => { + bidderRequest.bids[0].sizes = "728x90"; adapter.callBids(bidderRequest); sinon.assert.calledOnce(ajaxStub); expect(ajaxStub.firstCall.args[0]).to.eql(adapter.QUANTCAST_CALLBACK_URL); - expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a('function'); - expect(ajaxStub.firstCall.args[3]).to.eql({method: 'POST', withCredentials: true}); + expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a("function"); + expect(ajaxStub.firstCall.args[3]).to.eql({ + method: "POST", + withCredentials: true + }); }); - it('should call server once when sizes are passed as a comma-separated string', () => { - bidderRequest.bids[0].sizes = '728x90,360x240'; + it("should call server once when sizes are passed as a comma-separated string", () => { + bidderRequest.bids[0].sizes = "728x90,360x240"; adapter.callBids(bidderRequest); sinon.assert.calledOnce(ajaxStub); expect(ajaxStub.firstCall.args[0]).to.eql(adapter.QUANTCAST_CALLBACK_URL); - expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a('function'); - expect(ajaxStub.firstCall.args[3]).to.eql({method: 'POST', withCredentials: true}); + expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a("function"); + expect(ajaxStub.firstCall.args[3]).to.eql({ + method: "POST", + withCredentials: true + }); }); }); - describe('multiple requests', () => { + describe("multiple requests", () => { let bidderRequest = { - bidderCode: 'quantcast', - requestId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', - bidderRequestId: '1cc026909c24c8', + bidderCode: "quantcast", + requestId: "595ffa73-d78a-46c9-b18e-f99548a5be6b", + bidderRequestId: "1cc026909c24c8", bids: [ { - bidId: '2f7b179d443f14', - bidder: 'quantcast', - placementCode: 'div-gpt-ad-1438287399331-0', + bidId: "2f7b179d443f14", + bidder: "quantcast", + placementCode: "div-gpt-ad-1438287399331-0", sizes: [[300, 250]], params: { - publisherId: 'test-publisher', - battr: [1, 2], + publisherId: "test-publisher", + battr: [1, 2] } - }, { - bidId: '2f7b179d443f15', - bidder: 'quantcast', - placementCode: 'div-gpt-ad-1438287399331-1', + }, + { + bidId: "2f7b179d443f15", + bidder: "quantcast", + placementCode: "div-gpt-ad-1438287399331-1", sizes: [[300, 600]], params: { - publisherId: 'test-publisher', - battr: [1, 2], + publisherId: "test-publisher", + battr: [1, 2] } } ] }; - it('request is fired twice for two bids', () => { + it("request is fired twice for two bids", () => { adapter.callBids(bidderRequest); sinon.assert.calledTwice(ajaxStub); let firstReq = JSON.parse(ajaxStub.firstCall.args[2]); - expect(firstReq.requestId).to.eql('2f7b179d443f14'); - expect(firstReq.imp[0].placementCode).to.eql('div-gpt-ad-1438287399331-0'); + expect(firstReq.requestId).to.eql("2f7b179d443f14"); + expect(firstReq.imp[0].placementCode).to.eql( + "div-gpt-ad-1438287399331-0" + ); let secondReq = JSON.parse(ajaxStub.secondCall.args[2]); - expect(secondReq.requestId).to.eql('2f7b179d443f15'); - expect(secondReq.imp[0].placementCode).to.eql('div-gpt-ad-1438287399331-1'); + expect(secondReq.requestId).to.eql("2f7b179d443f15"); + expect(secondReq.imp[0].placementCode).to.eql( + "div-gpt-ad-1438287399331-1" + ); }); }); - describe('handleQuantcastCB add bids to the manager', () => { + describe("handleQuantcastCB add bids to the manager", () => { let firstBid; let addBidReponseStub; let bidsRequestedOriginal; // respond let bidderReponse = { - 'bidderCode': 'quantcast', - 'requestId': bidderRequest.requestId, - 'bids': [ + bidderCode: "quantcast", + requestId: bidderRequest.requestId, + bids: [ { - 'statusCode': 1, - 'placementCode': bidderRequest.bids[0].bidId, - 'cpm': 4.5, - 'ad': '\n\n\n
\n
\n\n \n\nQuantcast\n\n
\n
', - 'width': 300, - 'height': 250 + statusCode: 1, + placementCode: bidderRequest.bids[0].bidId, + cpm: 4.5, + ad: + '\n\n\n
\n
\n\n \n\nQuantcast\n\n
\n
', + width: 300, + height: 250 } ] }; beforeEach(() => { bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - addBidReponseStub = sandbox.stub(bidManager, 'addBidResponse'); + addBidReponseStub = sandbox.stub(bidManager, "addBidResponse"); $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); }); @@ -183,40 +202,44 @@ describe('quantcast adapter', () => { $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; }); - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.handleQuantcastCB).to.exist.and.to.be.a('function'); + it("should exist and be a function", () => { + expect($$PREBID_GLOBAL$$.handleQuantcastCB).to.exist.and.to.be.a( + "function" + ); }); - it('should not add bid when empty text response comes', () => { + it("should not add bid when empty text response comes", () => { $$PREBID_GLOBAL$$.handleQuantcastCB(); sinon.assert.notCalled(addBidReponseStub); }); - it('should not add bid when empty json response comes', () => { + it("should not add bid when empty json response comes", () => { $$PREBID_GLOBAL$$.handleQuantcastCB(JSON.stringify({})); sinon.assert.notCalled(addBidReponseStub); }); - it('should not add bid when malformed json response comes', () => { - $$PREBID_GLOBAL$$.handleQuantcastCB('non json text'); + it("should not add bid when malformed json response comes", () => { + $$PREBID_GLOBAL$$.handleQuantcastCB("non json text"); sinon.assert.notCalled(addBidReponseStub); }); - it('should add a bid object for each bid', () => { + it("should add a bid object for each bid", () => { // You need the following call so that the in-memory storage of the bidRequest is carried out. Without this the callback won't work correctly. adapter.callBids(bidderRequest); $$PREBID_GLOBAL$$.handleQuantcastCB(JSON.stringify(bidderReponse)); sinon.assert.calledOnce(addBidReponseStub); - expect(addBidReponseStub.firstCall.args[0]).to.eql('div-gpt-ad-1438287399331-0'); + expect(addBidReponseStub.firstCall.args[0]).to.eql( + "div-gpt-ad-1438287399331-0" + ); }); - it('should return no bid even when requestId and sizes are missing', () => { + it("should return no bid even when requestId and sizes are missing", () => { let bidderReponse = { - 'bidderCode': 'quantcast', - 'bids': [ + bidderCode: "quantcast", + bids: [ { - 'statusCode': 0, - 'placementCode': bidderRequest.bids[0].bidId, + statusCode: 0, + placementCode: bidderRequest.bids[0].bidId } ] }; From e94e79067f304561a4530663f7258a9acc32b86e Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Thu, 19 Oct 2017 16:59:05 +0800 Subject: [PATCH 04/24] Add new describes for test --- modules/quantcastBidAdapter.js | 37 ++- modules/quantcastBidAdapter.md | 18 +- test/spec/modules/quantcastBidAdapter_spec.js | 253 +++--------------- 3 files changed, 76 insertions(+), 232 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 2ed6c59e549..573de6bcfa7 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -3,16 +3,23 @@ import * as utils from "src/utils"; import { registerBidder } from "src/adapters/bidderFactory"; const BIDDER_CODE = "quantcast"; -const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; const DEFAULT_BID_FLOOR = 0.0000000001; +const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; +const QUANTCAST_CALLBACK_URL_TEST = "s2s-canary.quantserve.com"; +const QUANTCAST_TEST_PUBLISHER = "test-publisher"; let publisherTagURL; +let publisherTagURLTest; + +// TODO: Change the callback URL to Canary endpoint if under test switch (window.location.protocol) { case "https:": publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8080/qchb`; + publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb`; break; default: publisherTagURL = `http://${QUANTCAST_CALLBACK_URL}:8443/qchb`; + publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; } /** @@ -38,7 +45,11 @@ export const spec = { * @return boolean `true` is this is a valid bid, and `false` otherwise */ isBidRequestValid(bid) { - // TODO: How to validate a bid request? @tmax + if (bid.mediaType === "video") { + return false; + } + + return true; }, /** @@ -55,7 +66,7 @@ export const spec = { const loc = utils.getTopWindowLocation(); const domain = loc.hostname; - const bidRequests = bids.map(bid => { + const bidRequestsList = bids.map(bid => { const bidSizes = []; bid.sizes.forEach(size => { @@ -72,7 +83,7 @@ export const spec = { imp: [ { banner: { - batter: bid.params.battr, + battr: bid.params.battr, size: bidSizes }, placementCode: bid.placementCode, @@ -87,15 +98,20 @@ export const spec = { bidId: bid.bidId }; + const url = + bid.params.publisherId === QUANTCAST_TEST_PUBLISHER + ? publisherTagURLTest + : publisherTagURL; + return { - method: "POST", - url: publisherTagURL, data: JSON.stringify(requestData), + method: "POST", + url, withCredentials: true }; }); - return bidRequests; + return bidRequestsList; }, /** @@ -131,7 +147,7 @@ export const spec = { return; } - const bidResponses = response.bids.map(bid => { + const bidResponsesList = response.bids.map(bid => { const { ad, cpm, width, height } = bid; return { @@ -144,11 +160,12 @@ export const spec = { }; }); - return bidResponses; + return bidResponsesList; }, getUserSyncs(syncOptions) { - // TODO: What does user syncs do? @tmax + // Quantcast does not do `UserSyncs` at the moment. + // This feature will be supported at a later time. } }; diff --git a/modules/quantcastBidAdapter.md b/modules/quantcastBidAdapter.md index 0537578dab4..20cf25bffbf 100644 --- a/modules/quantcastBidAdapter.md +++ b/modules/quantcastBidAdapter.md @@ -1,8 +1,10 @@ # Overview +``` Module Name: Quantcast Bidder Adapter Module Type: Bidder Adapter Maintainer: xli@quantcast.com +``` # Description @@ -11,5 +13,19 @@ Module that connects to Quantcast demand sources to fetch bids. # Test Parameters ```js -const adUnits = [{}]; +const adUnits = [{ + code: 'banner', + sizes: [ + [300, 250] + ], + bids: [ + { + bidder: 'quantcast', + params: { + publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast + battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 + } + } + ] +}]; ``` \ No newline at end of file diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 6f13ece523f..33418b8325e 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,187 +1,39 @@ import { expect } from "chai"; -import Adapter from "../../../modules/quantcastBidAdapter"; -import bidManager from "../../../src/bidmanager"; -import adLoader from "../../../src/adloader"; +import { spec as qcSpec } from "../../../modules/quantcastBidAdapter"; +import { newBidder } from "../../../src/adapters/bidderFactory"; describe("Quantcast adapter", () => { - let bidsRequestedOriginal; - let adapter; - let sandbox; - let ajaxStub; + const quantcastAdapter = newBidder(qcSpec); - const bidderRequest = { - bidderCode: "quantcast", - requestId: "595ffa73-d78a-46c9-b18e-f99548a5be6b", - bidderRequestId: "1cc026909c24c8", - bids: [ - { - bidId: "2f7b179d443f14", - bidder: "quantcast", - placementCode: "div-gpt-ad-1438287399331-0", - sizes: [[300, 250], [300, 600]], - params: { - publisherId: "test-publisher", - battr: [1, 2] - } - } - ] - }; - - beforeEach(() => { - bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - ajaxStub = sandbox.stub(ajax, "ajax"); - }); - - afterEach(() => { - sandbox.restore(); - - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; - }); - - describe("sizes", () => { - let bidderRequest = { - bidderCode: "quantcast", - requestId: "595ffa73-d78a-46c9-b18e-f99548a5be6b", - bidderRequestId: "1cc026909c24c8", - bids: [ - { - bidId: "2f7b179d443f14", - bidder: "quantcast", - placementCode: "div-gpt-ad-1438287399331-0", - sizes: [[300, 250], [300, 600]], - params: { - publisherId: "test-publisher", - battr: [1, 2] - } - } - ] - }; - - it("should not call server when empty input is provided", () => { - adapter.callBids({}); - sinon.assert.notCalled(ajaxStub); - }); - - it("should call server once even when multiple sizes are passed", () => { - adapter.callBids(bidderRequest); - sinon.assert.calledOnce(ajaxStub); - - expect(ajaxStub.firstCall.args[0]).to.eql(adapter.QUANTCAST_CALLBACK_URL); - expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a("function"); - expect(ajaxStub.firstCall.args[2]).to.include( - "div-gpt-ad-1438287399331-0" - ); - expect(ajaxStub.firstCall.args[2]).to.include("test-publisher"); - expect(ajaxStub.firstCall.args[2]).to.include("2f7b179d443f14"); - expect(ajaxStub.firstCall.args[3]).to.eql({ - method: "POST", - withCredentials: true - }); + describe("inherited functions", () => { + it("exists and is a function", () => { + expect(quantcastAdapter.callBids).to.exist.and.to.be.a("function"); }); + }); - it("should call server once when one size is passed", () => { - bidderRequest.bids[0].sizes = [728, 90]; - adapter.callBids(bidderRequest); - sinon.assert.calledOnce(ajaxStub); - - expect(ajaxStub.firstCall.args[0]).to.eql(adapter.QUANTCAST_CALLBACK_URL); - expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a("function"); - expect(ajaxStub.firstCall.args[3]).to.eql({ - method: "POST", - withCredentials: true - }); - }); - - it("should call server once when size is passed as string", () => { - bidderRequest.bids[0].sizes = "728x90"; - adapter.callBids(bidderRequest); - sinon.assert.calledOnce(ajaxStub); - - expect(ajaxStub.firstCall.args[0]).to.eql(adapter.QUANTCAST_CALLBACK_URL); - expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a("function"); - expect(ajaxStub.firstCall.args[3]).to.eql({ - method: "POST", - withCredentials: true - }); - }); + describe("`isBidRequestValid`", () => { + let bid = {}; - it("should call server once when sizes are passed as a comma-separated string", () => { - bidderRequest.bids[0].sizes = "728x90,360x240"; - adapter.callBids(bidderRequest); - sinon.assert.calledOnce(ajaxStub); + it("should return true when bid contains required params", () => {}); - expect(ajaxStub.firstCall.args[0]).to.eql(adapter.QUANTCAST_CALLBACK_URL); - expect(ajaxStub.firstCall.args[1]).to.exist.and.to.be.a("function"); - expect(ajaxStub.firstCall.args[3]).to.eql({ - method: "POST", - withCredentials: true - }); - }); + it("should return `false` when bid does NOT contains required params", () => {}); }); - describe("multiple requests", () => { - let bidderRequest = { - bidderCode: "quantcast", - requestId: "595ffa73-d78a-46c9-b18e-f99548a5be6b", - bidderRequestId: "1cc026909c24c8", - bids: [ - { - bidId: "2f7b179d443f14", - bidder: "quantcast", - placementCode: "div-gpt-ad-1438287399331-0", - sizes: [[300, 250]], - params: { - publisherId: "test-publisher", - battr: [1, 2] - } - }, - { - bidId: "2f7b179d443f15", - bidder: "quantcast", - placementCode: "div-gpt-ad-1438287399331-1", - sizes: [[300, 600]], - params: { - publisherId: "test-publisher", - battr: [1, 2] - } - } - ] - }; - - it("request is fired twice for two bids", () => { - adapter.callBids(bidderRequest); - sinon.assert.calledTwice(ajaxStub); + describe("`buildRequests`", () => { + it("sends bid requests to Quantcast Header Bidding Endpoints via POST", () => {}); - let firstReq = JSON.parse(ajaxStub.firstCall.args[2]); - expect(firstReq.requestId).to.eql("2f7b179d443f14"); - expect(firstReq.imp[0].placementCode).to.eql( - "div-gpt-ad-1438287399331-0" - ); - - let secondReq = JSON.parse(ajaxStub.secondCall.args[2]); - expect(secondReq.requestId).to.eql("2f7b179d443f15"); - expect(secondReq.imp[0].placementCode).to.eql( - "div-gpt-ad-1438287399331-1" - ); - }); + it("sends bid requests with `withCredentials` enabled", () => {}); }); - describe("handleQuantcastCB add bids to the manager", () => { - let firstBid; - let addBidReponseStub; - let bidsRequestedOriginal; - // respond - let bidderReponse = { - bidderCode: "quantcast", - requestId: bidderRequest.requestId, + describe("`interpretResponse`", () => { + // The sample response is from https://wiki.corp.qc/display/adinf/QCX + const response = { + bidderCode: "qcx", // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name + requestId: "erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458", // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames bids: [ { statusCode: 1, - placementCode: bidderRequest.bids[0].bidId, + placementCode: "imp1", // Changing this to placementCode to be reflective cpm: 4.5, ad: '\n\n\n
\n
\n\n \n\nQuantcast\n\n
\n
', @@ -191,64 +43,23 @@ describe("Quantcast adapter", () => { ] }; - beforeEach(() => { - bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - addBidReponseStub = sandbox.stub(bidManager, "addBidResponse"); - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - }); - - afterEach(() => { - sandbox.restore(); - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; - }); - - it("should exist and be a function", () => { - expect($$PREBID_GLOBAL$$.handleQuantcastCB).to.exist.and.to.be.a( - "function" - ); - }); - - it("should not add bid when empty text response comes", () => { - $$PREBID_GLOBAL$$.handleQuantcastCB(); - sinon.assert.notCalled(addBidReponseStub); - }); - - it("should not add bid when empty json response comes", () => { - $$PREBID_GLOBAL$$.handleQuantcastCB(JSON.stringify({})); - sinon.assert.notCalled(addBidReponseStub); - }); - - it("should not add bid when malformed json response comes", () => { - $$PREBID_GLOBAL$$.handleQuantcastCB("non json text"); - sinon.assert.notCalled(addBidReponseStub); - }); + it("should get correct bid response", () => { + const expectedResponse = []; + const interpretedResponse = qcSpec.interpretResponse(response); - it("should add a bid object for each bid", () => { - // You need the following call so that the in-memory storage of the bidRequest is carried out. Without this the callback won't work correctly. - adapter.callBids(bidderRequest); - $$PREBID_GLOBAL$$.handleQuantcastCB(JSON.stringify(bidderReponse)); - sinon.assert.calledOnce(addBidReponseStub); - expect(addBidReponseStub.firstCall.args[0]).to.eql( - "div-gpt-ad-1438287399331-0" - ); + expect(interpretedResponse).to.deep.equal(expectedResponse); }); - it("should return no bid even when requestId and sizes are missing", () => { - let bidderReponse = { - bidderCode: "quantcast", - bids: [ - { - statusCode: 0, - placementCode: bidderRequest.bids[0].bidId - } - ] + it("handles no bid response", () => { + const response = { + bidderCode: "qcx", // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name + requestId: "erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458", // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames + bids: [] }; + const expectedResponse = []; + const interpretedResponse = qcSpec.interpretResponse(response); - // You need the following call so that the in-memory storage of the bidRequest is carried out. Without this the callback won't work correctly. - adapter.callBids(bidderRequest); - $$PREBID_GLOBAL$$.handleQuantcastCB(JSON.stringify(bidderReponse)); - // sinon.assert.calledOnce(addBidReponseStub); - // expect(addBidReponseStub.firstCall.args[0]).to.eql("div-gpt-ad-1438287399331-0"); + expect(interpretedResponse.length).to.equal(0); }); }); }); From 08c4300f91b704e49a113cd8e9f9b28b97aec1ea Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Thu, 19 Oct 2017 21:29:06 +0800 Subject: [PATCH 05/24] Move URL detechtion inside buildRequests method --- modules/quantcastBidAdapter.js | 44 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 573de6bcfa7..87da38a84b1 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -8,20 +8,6 @@ const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; const QUANTCAST_CALLBACK_URL_TEST = "s2s-canary.quantserve.com"; const QUANTCAST_TEST_PUBLISHER = "test-publisher"; -let publisherTagURL; -let publisherTagURLTest; - -// TODO: Change the callback URL to Canary endpoint if under test -switch (window.location.protocol) { - case "https:": - publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8080/qchb`; - publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb`; - break; - default: - publisherTagURL = `http://${QUANTCAST_CALLBACK_URL}:8443/qchb`; - publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; -} - /** * The documentation for Prebid.js Adapter 1.0 can be found at link below, * http://prebid.org/dev-docs/bidder-adapter-1.html @@ -66,7 +52,27 @@ export const spec = { const loc = utils.getTopWindowLocation(); const domain = loc.hostname; + let publisherTagURL; + let publisherTagURLTest; + + // Switch the callback URL to Quantcast Canary Endpoint for testing purpose + // `//` is not used because we have different port setting at our end + switch (window.location.protocol) { + case "https:": + publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8080/qchb`; + publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb`; + break; + default: + publisherTagURL = `http://${QUANTCAST_CALLBACK_URL}:8443/qchb`; + publisherTagURLTest = `http://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; + } + const bidRequestsList = bids.map(bid => { + const url = + bid.params.publisherId === QUANTCAST_TEST_PUBLISHER + ? publisherTagURLTest + : publisherTagURL; + const bidSizes = []; bid.sizes.forEach(size => { @@ -98,13 +104,10 @@ export const spec = { bidId: bid.bidId }; - const url = - bid.params.publisherId === QUANTCAST_TEST_PUBLISHER - ? publisherTagURLTest - : publisherTagURL; + const data = JSON.stringify(requestData); return { - data: JSON.stringify(requestData), + data, method: "POST", url, withCredentials: true @@ -144,7 +147,7 @@ export const spec = { utils.isEmpty(response.bids) ) { utils.logError("Sub-optimal JSON received from Quantcast server"); - return; + return []; } const bidResponsesList = response.bids.map(bid => { @@ -166,6 +169,7 @@ export const spec = { getUserSyncs(syncOptions) { // Quantcast does not do `UserSyncs` at the moment. // This feature will be supported at a later time. + return; } }; From d276ad1ef78d5cc54d656011f52b92f1d98a806f Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Thu, 19 Oct 2017 21:29:24 +0800 Subject: [PATCH 06/24] Add necessary cases --- test/spec/modules/quantcastBidAdapter_spec.js | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 33418b8325e..de7a8c13530 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -12,17 +12,27 @@ describe("Quantcast adapter", () => { }); describe("`isBidRequestValid`", () => { - let bid = {}; + it("should return `false` when bid `mediaType` is `video`", () => { + const bidRequest = { mediaType: "video" }; - it("should return true when bid contains required params", () => {}); + expect(qcSpec.isBidRequestValid(bidRequest)).to.be(false); + }); + + it("should return `true` when bid contains required params", () => { + const bidRequest = { mediaType: "banner" }; - it("should return `false` when bid does NOT contains required params", () => {}); + expect(qcSpec.isBidRequestValid(bidRequest)).to.be(true); + }); }); describe("`buildRequests`", () => { + it("sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`", () => {}); + it("sends bid requests to Quantcast Header Bidding Endpoints via POST", () => {}); it("sends bid requests with `withCredentials` enabled", () => {}); + + it("sends bid requests contains all the required parameters", () => {}); }); describe("`interpretResponse`", () => { @@ -43,6 +53,16 @@ describe("Quantcast adapter", () => { ] }; + it("should return an empty array if `serverResponse` is empty", () => {}); + + it("should return an empty array if there is an error to parse the `serverResponse`", () => {}); + + it("should return an empty array if the parsed response does NOT include `bids`", () => {}); + + it("should return an empty array if the parsed response has an empty `bids`", () => {}); + + it("should return an empty array if the parsed response is `null`", () => {}); + it("should get correct bid response", () => { const expectedResponse = []; const interpretedResponse = qcSpec.interpretResponse(response); From 642115d40e42f73c31ee88a9a88a49364ad17c20 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Thu, 19 Oct 2017 21:54:38 +0800 Subject: [PATCH 07/24] Clean test cases --- test/spec/modules/quantcastBidAdapter_spec.js | 31 +++---------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index de7a8c13530..5993bbbfa45 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -12,17 +12,9 @@ describe("Quantcast adapter", () => { }); describe("`isBidRequestValid`", () => { - it("should return `false` when bid `mediaType` is `video`", () => { - const bidRequest = { mediaType: "video" }; + it("should return `false` when bid `mediaType` is `video`", () => {}); - expect(qcSpec.isBidRequestValid(bidRequest)).to.be(false); - }); - - it("should return `true` when bid contains required params", () => { - const bidRequest = { mediaType: "banner" }; - - expect(qcSpec.isBidRequestValid(bidRequest)).to.be(true); - }); + it("should return `true` when bid contains required params", () => {}); }); describe("`buildRequests`", () => { @@ -63,23 +55,8 @@ describe("Quantcast adapter", () => { it("should return an empty array if the parsed response is `null`", () => {}); - it("should get correct bid response", () => { - const expectedResponse = []; - const interpretedResponse = qcSpec.interpretResponse(response); + it("should get correct bid response", () => {}); - expect(interpretedResponse).to.deep.equal(expectedResponse); - }); - - it("handles no bid response", () => { - const response = { - bidderCode: "qcx", // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name - requestId: "erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458", // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames - bids: [] - }; - const expectedResponse = []; - const interpretedResponse = qcSpec.interpretResponse(response); - - expect(interpretedResponse.length).to.equal(0); - }); + it("handles no bid response", () => {}); }); }); From 444a2bf4baa52e10b54dc39307f82fa8b07eb261 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Fri, 20 Oct 2017 08:53:30 +0800 Subject: [PATCH 08/24] Export Quantcast adapter constants --- modules/quantcastBidAdapter.js | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 87da38a84b1..972d02dd9b7 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -4,9 +4,9 @@ import { registerBidder } from "src/adapters/bidderFactory"; const BIDDER_CODE = "quantcast"; const DEFAULT_BID_FLOOR = 0.0000000001; -const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; -const QUANTCAST_CALLBACK_URL_TEST = "s2s-canary.quantserve.com"; -const QUANTCAST_TEST_PUBLISHER = "test-publisher"; +export const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; +export const QUANTCAST_CALLBACK_URL_TEST = "s2s-canary.quantserve.com"; +export const QUANTCAST_TEST_PUBLISHER = "test-publisher"; /** * The documentation for Prebid.js Adapter 1.0 can be found at link below, @@ -31,6 +31,10 @@ export const spec = { * @return boolean `true` is this is a valid bid, and `false` otherwise */ isBidRequestValid(bid) { + if (!bid) { + return false; + } + if (bid.mediaType === "video") { return false; } @@ -68,11 +72,6 @@ export const spec = { } const bidRequestsList = bids.map(bid => { - const url = - bid.params.publisherId === QUANTCAST_TEST_PUBLISHER - ? publisherTagURLTest - : publisherTagURL; - const bidSizes = []; bid.sizes.forEach(size => { @@ -106,6 +105,11 @@ export const spec = { const data = JSON.stringify(requestData); + const url = + bid.params.publisherId === QUANTCAST_TEST_PUBLISHER + ? publisherTagURLTest + : publisherTagURL; + return { data, method: "POST", @@ -129,20 +133,10 @@ export const spec = { * */ interpretResponse(serverResponse) { - if (utils.isEmpty(serverResponse)) { - return []; - } - - let response; - try { - response = JSON.parse(serverResponse); - } catch (error) { - utils.logError("Malformed JSON received from Quantcast server"); - return []; - } + const response = serverResponse; if ( - response === null || + response === undefined || !response.hasOwnProperty("bids") || utils.isEmpty(response.bids) ) { From d99851e2c75740d7bd8ac5ed3291af80275898ab Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Fri, 20 Oct 2017 08:53:53 +0800 Subject: [PATCH 09/24] Implemenent test cases --- test/spec/modules/quantcastBidAdapter_spec.js | 159 ++++++++++++++++-- 1 file changed, 145 insertions(+), 14 deletions(-) diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 5993bbbfa45..316627bcabd 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,9 +1,30 @@ +import * as utils from "src/utils"; import { expect } from "chai"; -import { spec as qcSpec } from "../../../modules/quantcastBidAdapter"; +import { + spec as qcSpec, + QUANTCAST_CALLBACK_URL, + QUANTCAST_CALLBACK_URL_TEST +} from "../../../modules/quantcastBidAdapter"; import { newBidder } from "../../../src/adapters/bidderFactory"; describe("Quantcast adapter", () => { const quantcastAdapter = newBidder(qcSpec); + let bidRequest; + + beforeEach(() => { + bidRequest = { + bidder: "quantcast", + bidId: "2f7b179d443f14", + requestId: "595ffa73-d78a-46c9-b18e-f99548a5be6b", + bidderRequestId: "1cc026909c24c8", + placementCode: "div-gpt-ad-1438287399331-0", + params: { + publisherId: "test-publisher", // REQUIRED - Publisher ID provided by Quantcast + battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 + }, + sizes: [[300, 250]] + }; + }); describe("inherited functions", () => { it("exists and is a function", () => { @@ -12,19 +33,94 @@ describe("Quantcast adapter", () => { }); describe("`isBidRequestValid`", () => { - it("should return `false` when bid `mediaType` is `video`", () => {}); + it("should return `false` when bid is not passed", () => { + expect(qcSpec.isBidRequestValid()).to.equal(false); + }); - it("should return `true` when bid contains required params", () => {}); + it("should return `false` when bid `mediaType` is `video`", () => { + const bidRequest = { mediaType: "video" }; + + expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); + }); + + it("should return `true` when bid contains required params", () => { + const bidRequest = { mediaType: "banner" }; + + expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); + }); }); describe("`buildRequests`", () => { - it("sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`", () => {}); + // it("sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`", () => { + // const requests = qcSpec.buildRequests([bidRequest]); + + // expect(requests[0]["url"]).to.satisfy(URl => { + // switch (URL) { + // case `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`: + // case `http://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb`: + // return true; + // default: + // return false; + // } + // }); + // }); + + // it("sends bid requests to Quantcast Global Endpoint for regular `publisherId`", () => { + // const bidRequest = { publisherId: "regular-publisher" }; + // const requests = qcSpec.buildRequests([bidRequest]); + + // expect(requests[0].url).to.satisfy(URL => { + // switch (URL) { + // case `https://${QUANTCAST_CALLBACK_URL}:8443/qchb`: + // case `http://${QUANTCAST_CALLBACK_URL}:8080/qchb`: + // return true; + // default: + // return false; + // } + // }); + // }); + + it("sends bid requests to Quantcast Header Bidding Endpoints via POST", () => { + const requests = qcSpec.buildRequests([bidRequest]); + + expect(requests[0].method).to.equal("POST"); + }); - it("sends bid requests to Quantcast Header Bidding Endpoints via POST", () => {}); + it("sends bid requests with `withCredentials` enabled", () => { + const requests = qcSpec.buildRequests([bidRequest]); - it("sends bid requests with `withCredentials` enabled", () => {}); + expect(requests[0].withCredentials).to.equal(true); + }); - it("sends bid requests contains all the required parameters", () => {}); + it("sends bid requests contains all the required parameters", () => { + const referrer = utils.getTopWindowUrl(); + const loc = utils.getTopWindowLocation(); + const domain = loc.hostname; + + const requests = qcSpec.buildRequests([bidRequest]); + const expectedBidRequest = { + publisherId: "test-publisher", + requestId: "2f7b179d443f14", + imp: [ + { + banner: { + battr: [1, 2], + size: [{ width: 300, height: 250 }] + }, + placementCode: "div-gpt-ad-1438287399331-0", + bidFloor: 1e-10 + } + ], + site: { + page: loc.href, + referrer, + domain + }, + bidId: "2f7b179d443f14" + }; + + expect(requests[0].data).to.equal(JSON.stringify(expectedBidRequest)); + }); }); describe("`interpretResponse`", () => { @@ -45,18 +141,53 @@ describe("Quantcast adapter", () => { ] }; - it("should return an empty array if `serverResponse` is empty", () => {}); + it("should return an empty array if `serverResponse` is `undefined`", () => { + const interpretedResponse = qcSpec.interpretResponse(); - it("should return an empty array if there is an error to parse the `serverResponse`", () => {}); + expect(interpretedResponse.length).to.equal(0); + }); - it("should return an empty array if the parsed response does NOT include `bids`", () => {}); + it("should return an empty array if the parsed response does NOT include `bids`", () => { + const interpretedResponse = qcSpec.interpretResponse({}); - it("should return an empty array if the parsed response has an empty `bids`", () => {}); + expect(interpretedResponse.length).to.equal(0); + }); - it("should return an empty array if the parsed response is `null`", () => {}); + it("should return an empty array if the parsed response has an empty `bids`", () => { + const interpretedResponse = qcSpec.interpretResponse({ bids: [] }); - it("should get correct bid response", () => {}); + expect(interpretedResponse.length).to.equal(0); + }); - it("handles no bid response", () => {}); + it("should get correct bid response", () => { + const expectedResponse = { + ad: + '
Quantcast
', + cpm: 4.5, + width: 300, + height: 250, + requestId: "erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458", + bidderCode: "qcx" + }; + const expectedResponse0 = + '{"ad":"\\n\\n\\n
\\n
\\n\\n \\n\\n\\"Quantcast\\"/\\n\\n
\\n
","cpm":4.5,"width":300,"height":250,"requestId":"erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458","bidderCode":"qcx"}'; + const interpretedResponse = qcSpec.interpretResponse(response); + + expect(JSON.stringify(interpretedResponse[0])).to.equal( + expectedResponse0 + ); + }); + + it("handles no bid response", () => { + const response = { + bidderCode: "qcx", // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name + requestId: "erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458", // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames + bids: [] + }; + const expectedResponse = []; + const interpretedResponse = qcSpec.interpretResponse(response); + + expect(interpretedResponse.length).to.equal(0); + }); }); }); From 5a7809e8cafcb6f01371ab71f7616c3e8546a903 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Fri, 20 Oct 2017 11:17:51 +0800 Subject: [PATCH 10/24] Fix wrong ports number --- modules/quantcastBidAdapter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 972d02dd9b7..cfeb1589aa9 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -63,12 +63,12 @@ export const spec = { // `//` is not used because we have different port setting at our end switch (window.location.protocol) { case "https:": - publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8080/qchb`; - publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb`; + publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8443/qchb`; + publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; break; default: - publisherTagURL = `http://${QUANTCAST_CALLBACK_URL}:8443/qchb`; - publisherTagURLTest = `http://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; + publisherTagURL = `http://${QUANTCAST_CALLBACK_URL}:8080/qchb`; + publisherTagURLTest = `http://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb`; } const bidRequestsList = bids.map(bid => { From 553b34dea1a0652c50a74bdfaab1ae7d07b7ecb8 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Fri, 20 Oct 2017 11:18:12 +0800 Subject: [PATCH 11/24] Correct test cases --- test/spec/modules/quantcastBidAdapter_spec.js | 83 +++++++++++-------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 316627bcabd..67f8822a617 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -51,34 +51,51 @@ describe("Quantcast adapter", () => { }); describe("`buildRequests`", () => { - // it("sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`", () => { - // const requests = qcSpec.buildRequests([bidRequest]); - - // expect(requests[0]["url"]).to.satisfy(URl => { - // switch (URL) { - // case `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`: - // case `http://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb`: - // return true; - // default: - // return false; - // } - // }); - // }); - - // it("sends bid requests to Quantcast Global Endpoint for regular `publisherId`", () => { - // const bidRequest = { publisherId: "regular-publisher" }; - // const requests = qcSpec.buildRequests([bidRequest]); - - // expect(requests[0].url).to.satisfy(URL => { - // switch (URL) { - // case `https://${QUANTCAST_CALLBACK_URL}:8443/qchb`: - // case `http://${QUANTCAST_CALLBACK_URL}:8080/qchb`: - // return true; - // default: - // return false; - // } - // }); - // }); + it("sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`", () => { + const requests = qcSpec.buildRequests([bidRequest]); + + switch (window.location.protocol) { + case "https:": + expect(requests[0]["url"]).to.equal( + `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb` + ); + break; + default: + expect(requests[0]["url"]).to.equal( + `http://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb` + ); + break; + } + }); + + it("sends bid requests to Quantcast Global Endpoint for regular `publisherId`", () => { + const bidRequest = { + bidder: "quantcast", + bidId: "2f7b179d443f14", + requestId: "595ffa73-d78a-46c9-b18e-f99548a5be6b", + bidderRequestId: "1cc026909c24c8", + placementCode: "div-gpt-ad-1438287399331-0", + params: { + publisherId: "regular-publisher", // REQUIRED - Publisher ID provided by Quantcast + battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 + }, + sizes: [[300, 250]] + }; + const requests = qcSpec.buildRequests([bidRequest]); + + switch (window.location.protocol) { + case "https:": + expect(requests[0]["url"]).to.equal( + `https://${QUANTCAST_CALLBACK_URL}:8443/qchb` + ); + break; + default: + expect(requests[0]["url"]).to.equal( + `http://${QUANTCAST_CALLBACK_URL}:8080/qchb` + ); + break; + } + }); it("sends bid requests to Quantcast Header Bidding Endpoints via POST", () => { const requests = qcSpec.buildRequests([bidRequest]); @@ -134,7 +151,7 @@ describe("Quantcast adapter", () => { placementCode: "imp1", // Changing this to placementCode to be reflective cpm: 4.5, ad: - '\n\n\n
\n
\n\n \n\nQuantcast\n\n
\n
', + '
Quantcast
', width: 300, height: 250 } @@ -162,20 +179,16 @@ describe("Quantcast adapter", () => { it("should get correct bid response", () => { const expectedResponse = { ad: - '
Quantcast
', + '
Quantcast
', cpm: 4.5, width: 300, height: 250, requestId: "erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458", bidderCode: "qcx" }; - const expectedResponse0 = - '{"ad":"\\n\\n\\n
\\n
\\n\\n \\n\\n\\"Quantcast\\"/\\n\\n
\\n
","cpm":4.5,"width":300,"height":250,"requestId":"erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458","bidderCode":"qcx"}'; const interpretedResponse = qcSpec.interpretResponse(response); - expect(JSON.stringify(interpretedResponse[0])).to.equal( - expectedResponse0 - ); + expect(interpretedResponse[0]).to.deep.equal(expectedResponse); }); it("handles no bid response", () => { From abf387af1ff28cf0875da9239dff85648d55e21b Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Fri, 20 Oct 2017 16:11:39 +0800 Subject: [PATCH 12/24] Make string with single quote --- modules/quantcastBidAdapter.js | 24 ++-- test/spec/modules/quantcastBidAdapter_spec.js | 112 +++++++++--------- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index cfeb1589aa9..0855de7a911 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,12 +1,12 @@ -import adapterManager from "src/adaptermanager"; -import * as utils from "src/utils"; -import { registerBidder } from "src/adapters/bidderFactory"; +import adapterManager from 'src/adaptermanager'; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; -const BIDDER_CODE = "quantcast"; +const BIDDER_CODE = 'quantcast'; const DEFAULT_BID_FLOOR = 0.0000000001; -export const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; -export const QUANTCAST_CALLBACK_URL_TEST = "s2s-canary.quantserve.com"; -export const QUANTCAST_TEST_PUBLISHER = "test-publisher"; +export const QUANTCAST_CALLBACK_URL = 'global.qc.rtb.quantserve.com'; +export const QUANTCAST_CALLBACK_URL_TEST = 's2s-canary.quantserve.com'; +export const QUANTCAST_TEST_PUBLISHER = 'test-publisher'; /** * The documentation for Prebid.js Adapter 1.0 can be found at link below, @@ -35,7 +35,7 @@ export const spec = { return false; } - if (bid.mediaType === "video") { + if (bid.mediaType === 'video') { return false; } @@ -62,7 +62,7 @@ export const spec = { // Switch the callback URL to Quantcast Canary Endpoint for testing purpose // `//` is not used because we have different port setting at our end switch (window.location.protocol) { - case "https:": + case 'https:': publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8443/qchb`; publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; break; @@ -112,7 +112,7 @@ export const spec = { return { data, - method: "POST", + method: 'POST', url, withCredentials: true }; @@ -137,10 +137,10 @@ export const spec = { if ( response === undefined || - !response.hasOwnProperty("bids") || + !response.hasOwnProperty('bids') || utils.isEmpty(response.bids) ) { - utils.logError("Sub-optimal JSON received from Quantcast server"); + utils.logError('Sub-optimal JSON received from Quantcast server'); return []; } diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 67f8822a617..20f4e09983e 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,82 +1,82 @@ -import * as utils from "src/utils"; -import { expect } from "chai"; +import * as utils from 'src/utils'; +import { expect } from 'chai'; import { spec as qcSpec, QUANTCAST_CALLBACK_URL, QUANTCAST_CALLBACK_URL_TEST -} from "../../../modules/quantcastBidAdapter"; -import { newBidder } from "../../../src/adapters/bidderFactory"; +} from '../../../modules/quantcastBidAdapter'; +import { newBidder } from '../../../src/adapters/bidderFactory'; -describe("Quantcast adapter", () => { +describe('Quantcast adapter', () => { const quantcastAdapter = newBidder(qcSpec); let bidRequest; beforeEach(() => { bidRequest = { - bidder: "quantcast", - bidId: "2f7b179d443f14", - requestId: "595ffa73-d78a-46c9-b18e-f99548a5be6b", - bidderRequestId: "1cc026909c24c8", - placementCode: "div-gpt-ad-1438287399331-0", + bidder: 'quantcast', + bidId: '2f7b179d443f14', + requestId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', + bidderRequestId: '1cc026909c24c8', + placementCode: 'div-gpt-ad-1438287399331-0', params: { - publisherId: "test-publisher", // REQUIRED - Publisher ID provided by Quantcast + publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 }, sizes: [[300, 250]] }; }); - describe("inherited functions", () => { - it("exists and is a function", () => { - expect(quantcastAdapter.callBids).to.exist.and.to.be.a("function"); + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(quantcastAdapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe("`isBidRequestValid`", () => { - it("should return `false` when bid is not passed", () => { + describe('`isBidRequestValid`', () => { + it('should return `false` when bid is not passed', () => { expect(qcSpec.isBidRequestValid()).to.equal(false); }); - it("should return `false` when bid `mediaType` is `video`", () => { - const bidRequest = { mediaType: "video" }; + it('should return `false` when bid `mediaType` is `video`', () => { + const bidRequest = { mediaType: 'video' }; expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); }); - it("should return `true` when bid contains required params", () => { - const bidRequest = { mediaType: "banner" }; + it('should return `true` when bid contains required params', () => { + const bidRequest = { mediaType: 'banner' }; expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); }); }); - describe("`buildRequests`", () => { - it("sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`", () => { + describe('`buildRequests`', () => { + it('sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`', () => { const requests = qcSpec.buildRequests([bidRequest]); switch (window.location.protocol) { - case "https:": - expect(requests[0]["url"]).to.equal( + case 'https:': + expect(requests[0]['url']).to.equal( `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb` ); break; default: - expect(requests[0]["url"]).to.equal( + expect(requests[0]['url']).to.equal( `http://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb` ); break; } }); - it("sends bid requests to Quantcast Global Endpoint for regular `publisherId`", () => { + it('sends bid requests to Quantcast Global Endpoint for regular `publisherId`', () => { const bidRequest = { - bidder: "quantcast", - bidId: "2f7b179d443f14", - requestId: "595ffa73-d78a-46c9-b18e-f99548a5be6b", - bidderRequestId: "1cc026909c24c8", - placementCode: "div-gpt-ad-1438287399331-0", + bidder: 'quantcast', + bidId: '2f7b179d443f14', + requestId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', + bidderRequestId: '1cc026909c24c8', + placementCode: 'div-gpt-ad-1438287399331-0', params: { - publisherId: "regular-publisher", // REQUIRED - Publisher ID provided by Quantcast + publisherId: 'regular-publisher', // REQUIRED - Publisher ID provided by Quantcast battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 }, sizes: [[300, 250]] @@ -84,47 +84,47 @@ describe("Quantcast adapter", () => { const requests = qcSpec.buildRequests([bidRequest]); switch (window.location.protocol) { - case "https:": - expect(requests[0]["url"]).to.equal( + case 'https:': + expect(requests[0]['url']).to.equal( `https://${QUANTCAST_CALLBACK_URL}:8443/qchb` ); break; default: - expect(requests[0]["url"]).to.equal( + expect(requests[0]['url']).to.equal( `http://${QUANTCAST_CALLBACK_URL}:8080/qchb` ); break; } }); - it("sends bid requests to Quantcast Header Bidding Endpoints via POST", () => { + it('sends bid requests to Quantcast Header Bidding Endpoints via POST', () => { const requests = qcSpec.buildRequests([bidRequest]); - expect(requests[0].method).to.equal("POST"); + expect(requests[0].method).to.equal('POST'); }); - it("sends bid requests with `withCredentials` enabled", () => { + it('sends bid requests with `withCredentials` enabled', () => { const requests = qcSpec.buildRequests([bidRequest]); expect(requests[0].withCredentials).to.equal(true); }); - it("sends bid requests contains all the required parameters", () => { + it('sends bid requests contains all the required parameters', () => { const referrer = utils.getTopWindowUrl(); const loc = utils.getTopWindowLocation(); const domain = loc.hostname; const requests = qcSpec.buildRequests([bidRequest]); const expectedBidRequest = { - publisherId: "test-publisher", - requestId: "2f7b179d443f14", + publisherId: 'test-publisher', + requestId: '2f7b179d443f14', imp: [ { banner: { battr: [1, 2], size: [{ width: 300, height: 250 }] }, - placementCode: "div-gpt-ad-1438287399331-0", + placementCode: 'div-gpt-ad-1438287399331-0', bidFloor: 1e-10 } ], @@ -133,22 +133,22 @@ describe("Quantcast adapter", () => { referrer, domain }, - bidId: "2f7b179d443f14" + bidId: '2f7b179d443f14' }; expect(requests[0].data).to.equal(JSON.stringify(expectedBidRequest)); }); }); - describe("`interpretResponse`", () => { + describe('`interpretResponse`', () => { // The sample response is from https://wiki.corp.qc/display/adinf/QCX const response = { - bidderCode: "qcx", // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name - requestId: "erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458", // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames + bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name + requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames bids: [ { statusCode: 1, - placementCode: "imp1", // Changing this to placementCode to be reflective + placementCode: 'imp1', // Changing this to placementCode to be reflective cpm: 4.5, ad: '
Quantcast
', @@ -158,43 +158,43 @@ describe("Quantcast adapter", () => { ] }; - it("should return an empty array if `serverResponse` is `undefined`", () => { + it('should return an empty array if `serverResponse` is `undefined`', () => { const interpretedResponse = qcSpec.interpretResponse(); expect(interpretedResponse.length).to.equal(0); }); - it("should return an empty array if the parsed response does NOT include `bids`", () => { + it('should return an empty array if the parsed response does NOT include `bids`', () => { const interpretedResponse = qcSpec.interpretResponse({}); expect(interpretedResponse.length).to.equal(0); }); - it("should return an empty array if the parsed response has an empty `bids`", () => { + it('should return an empty array if the parsed response has an empty `bids`', () => { const interpretedResponse = qcSpec.interpretResponse({ bids: [] }); expect(interpretedResponse.length).to.equal(0); }); - it("should get correct bid response", () => { + it('should get correct bid response', () => { const expectedResponse = { ad: '
Quantcast
', cpm: 4.5, width: 300, height: 250, - requestId: "erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458", - bidderCode: "qcx" + requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', + bidderCode: 'qcx' }; const interpretedResponse = qcSpec.interpretResponse(response); expect(interpretedResponse[0]).to.deep.equal(expectedResponse); }); - it("handles no bid response", () => { + it('handles no bid response', () => { const response = { - bidderCode: "qcx", // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name - requestId: "erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458", // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames + bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name + requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames bids: [] }; const expectedResponse = []; From 459ca31ef8ac501311b738e61634cac216aaf7cf Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Fri, 20 Oct 2017 16:18:21 +0800 Subject: [PATCH 13/24] Remove unused statements --- .vscode/settings.json | 3 +++ modules/quantcastBidAdapter.js | 2 -- package.json | 9 ++------- yarn.lock | 6 +++++- 4 files changed, 10 insertions(+), 10 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..8b54f915c7c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "prettier.singleQuote": true +} diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 0855de7a911..383b5a1443c 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,4 +1,3 @@ -import adapterManager from 'src/adaptermanager'; import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; @@ -163,7 +162,6 @@ export const spec = { getUserSyncs(syncOptions) { // Quantcast does not do `UserSyncs` at the moment. // This feature will be supported at a later time. - return; } }; diff --git a/package.json b/package.json index d8294788ee3..5e3d9d797a8 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,7 @@ "type": "git", "url": "https://github.com/prebid/Prebid.js.git" }, - "keywords": [ - "advertising", - "auction", - "header bidding", - "prebid" - ], + "keywords": ["advertising", "auction", "header bidding", "prebid"], "globalVarName": "pbjs", "author": "the prebid.js contributors", "license": "Apache-2.0", @@ -43,7 +38,7 @@ "eslint-plugin-standard": "^3.0.1", "faker": "^3.1.0", "fs.extra": "^1.3.2", - "gulp": "^3.8.7", + "gulp": "^3.9.1", "gulp-babel": "^6.1.2", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", diff --git a/yarn.lock b/yarn.lock index f6efe31c6a5..d184927bcff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3940,7 +3940,7 @@ gulp-webdriver@^1.0.1: through2 "^0.6.5" webdriverio "^3.4.0" -gulp@^3.8.7: +gulp@^3.9.1: version "3.9.1" resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.9.1.tgz#571ce45928dd40af6514fc4011866016c13845b4" dependencies: @@ -4249,6 +4249,10 @@ ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" +ignore-loader@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463" + ignore@^3.3.3: version "3.3.5" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.5.tgz#c4e715455f6073a8d7e5dae72d2fc9d71663dba6" From 83a4de0abaf7a4345848039a46582adaa1d94489 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Fri, 20 Oct 2017 16:18:21 +0800 Subject: [PATCH 14/24] Revert "Remove unused statements" This reverts commit 459ca31ef8ac501311b738e61634cac216aaf7cf. --- .vscode/settings.json | 3 --- modules/quantcastBidAdapter.js | 2 ++ package.json | 9 +++++++-- yarn.lock | 6 +----- 4 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 8b54f915c7c..00000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "prettier.singleQuote": true -} diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 383b5a1443c..0855de7a911 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,3 +1,4 @@ +import adapterManager from 'src/adaptermanager'; import * as utils from 'src/utils'; import { registerBidder } from 'src/adapters/bidderFactory'; @@ -162,6 +163,7 @@ export const spec = { getUserSyncs(syncOptions) { // Quantcast does not do `UserSyncs` at the moment. // This feature will be supported at a later time. + return; } }; diff --git a/package.json b/package.json index 5e3d9d797a8..d8294788ee3 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,12 @@ "type": "git", "url": "https://github.com/prebid/Prebid.js.git" }, - "keywords": ["advertising", "auction", "header bidding", "prebid"], + "keywords": [ + "advertising", + "auction", + "header bidding", + "prebid" + ], "globalVarName": "pbjs", "author": "the prebid.js contributors", "license": "Apache-2.0", @@ -38,7 +43,7 @@ "eslint-plugin-standard": "^3.0.1", "faker": "^3.1.0", "fs.extra": "^1.3.2", - "gulp": "^3.9.1", + "gulp": "^3.8.7", "gulp-babel": "^6.1.2", "gulp-clean": "^0.3.2", "gulp-concat": "^2.6.0", diff --git a/yarn.lock b/yarn.lock index d184927bcff..f6efe31c6a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3940,7 +3940,7 @@ gulp-webdriver@^1.0.1: through2 "^0.6.5" webdriverio "^3.4.0" -gulp@^3.9.1: +gulp@^3.8.7: version "3.9.1" resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.9.1.tgz#571ce45928dd40af6514fc4011866016c13845b4" dependencies: @@ -4249,10 +4249,6 @@ ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" -ignore-loader@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463" - ignore@^3.3.3: version "3.3.5" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.5.tgz#c4e715455f6073a8d7e5dae72d2fc9d71663dba6" From 6520c69fad3fa1af71e116908f2175e61f668e15 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Fri, 20 Oct 2017 16:20:19 +0800 Subject: [PATCH 15/24] Remove unused statements --- modules/quantcastBidAdapter.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 0855de7a911..a03827959e6 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,12 +1,11 @@ -import adapterManager from 'src/adaptermanager'; -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; +import * as utils from "src/utils"; +import { registerBidder } from "src/adapters/bidderFactory"; -const BIDDER_CODE = 'quantcast'; +const BIDDER_CODE = "quantcast"; const DEFAULT_BID_FLOOR = 0.0000000001; -export const QUANTCAST_CALLBACK_URL = 'global.qc.rtb.quantserve.com'; -export const QUANTCAST_CALLBACK_URL_TEST = 's2s-canary.quantserve.com'; -export const QUANTCAST_TEST_PUBLISHER = 'test-publisher'; +export const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; +export const QUANTCAST_CALLBACK_URL_TEST = "s2s-canary.quantserve.com"; +export const QUANTCAST_TEST_PUBLISHER = "test-publisher"; /** * The documentation for Prebid.js Adapter 1.0 can be found at link below, @@ -35,7 +34,7 @@ export const spec = { return false; } - if (bid.mediaType === 'video') { + if (bid.mediaType === "video") { return false; } @@ -62,7 +61,7 @@ export const spec = { // Switch the callback URL to Quantcast Canary Endpoint for testing purpose // `//` is not used because we have different port setting at our end switch (window.location.protocol) { - case 'https:': + case "https:": publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8443/qchb`; publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; break; @@ -112,7 +111,7 @@ export const spec = { return { data, - method: 'POST', + method: "POST", url, withCredentials: true }; @@ -137,10 +136,10 @@ export const spec = { if ( response === undefined || - !response.hasOwnProperty('bids') || + !response.hasOwnProperty("bids") || utils.isEmpty(response.bids) ) { - utils.logError('Sub-optimal JSON received from Quantcast server'); + utils.logError("Sub-optimal JSON received from Quantcast server"); return []; } @@ -163,7 +162,6 @@ export const spec = { getUserSyncs(syncOptions) { // Quantcast does not do `UserSyncs` at the moment. // This feature will be supported at a later time. - return; } }; From 7ad07a03c365292eaa69840e5ae2e35f23705a97 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Fri, 20 Oct 2017 16:32:12 +0800 Subject: [PATCH 16/24] Change string to single quote --- modules/quantcastBidAdapter.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index a03827959e6..383b5a1443c 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,11 +1,11 @@ -import * as utils from "src/utils"; -import { registerBidder } from "src/adapters/bidderFactory"; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; -const BIDDER_CODE = "quantcast"; +const BIDDER_CODE = 'quantcast'; const DEFAULT_BID_FLOOR = 0.0000000001; -export const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; -export const QUANTCAST_CALLBACK_URL_TEST = "s2s-canary.quantserve.com"; -export const QUANTCAST_TEST_PUBLISHER = "test-publisher"; +export const QUANTCAST_CALLBACK_URL = 'global.qc.rtb.quantserve.com'; +export const QUANTCAST_CALLBACK_URL_TEST = 's2s-canary.quantserve.com'; +export const QUANTCAST_TEST_PUBLISHER = 'test-publisher'; /** * The documentation for Prebid.js Adapter 1.0 can be found at link below, @@ -34,7 +34,7 @@ export const spec = { return false; } - if (bid.mediaType === "video") { + if (bid.mediaType === 'video') { return false; } @@ -61,7 +61,7 @@ export const spec = { // Switch the callback URL to Quantcast Canary Endpoint for testing purpose // `//` is not used because we have different port setting at our end switch (window.location.protocol) { - case "https:": + case 'https:': publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8443/qchb`; publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; break; @@ -111,7 +111,7 @@ export const spec = { return { data, - method: "POST", + method: 'POST', url, withCredentials: true }; @@ -136,10 +136,10 @@ export const spec = { if ( response === undefined || - !response.hasOwnProperty("bids") || + !response.hasOwnProperty('bids') || utils.isEmpty(response.bids) ) { - utils.logError("Sub-optimal JSON received from Quantcast server"); + utils.logError('Sub-optimal JSON received from Quantcast server'); return []; } From c79279f2aef9c74b0ea39b9de929edcfc3509d0e Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Mon, 23 Oct 2017 17:09:57 +0800 Subject: [PATCH 17/24] Fix sizes type --- modules/quantcastBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 383b5a1443c..f7841ea45c4 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -88,7 +88,7 @@ export const spec = { { banner: { battr: bid.params.battr, - size: bidSizes + sizes: bidSizes }, placementCode: bid.placementCode, bidFloor: bid.params.bidFloor || DEFAULT_BID_FLOOR From b95315f95572d9e656e6d8949ba00acb0525158e Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Tue, 24 Oct 2017 14:22:45 +0800 Subject: [PATCH 18/24] Fix the sizes propty name typo in the spec --- test/spec/modules/quantcastBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 20f4e09983e..a0895502033 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -122,7 +122,7 @@ describe('Quantcast adapter', () => { { banner: { battr: [1, 2], - size: [{ width: 300, height: 250 }] + sizes: [{ width: 300, height: 250 }] }, placementCode: 'div-gpt-ad-1438287399331-0', bidFloor: 1e-10 From 1322e005466e88de89e2ac5007bdc4a586f02029 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Wed, 25 Oct 2017 09:44:05 +0800 Subject: [PATCH 19/24] Remove unused method, key value and comments --- modules/quantcastBidAdapter.js | 43 +++++++++++----------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index f7841ea45c4..89e1d0efa5f 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,11 +1,11 @@ -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; +import * as utils from "src/utils"; +import { registerBidder } from "src/adapters/bidderFactory"; -const BIDDER_CODE = 'quantcast'; +const BIDDER_CODE = "quantcast"; const DEFAULT_BID_FLOOR = 0.0000000001; -export const QUANTCAST_CALLBACK_URL = 'global.qc.rtb.quantserve.com'; -export const QUANTCAST_CALLBACK_URL_TEST = 's2s-canary.quantserve.com'; -export const QUANTCAST_TEST_PUBLISHER = 'test-publisher'; +export const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; +export const QUANTCAST_CALLBACK_URL_TEST = "s2s-canary.quantserve.com"; +export const QUANTCAST_TEST_PUBLISHER = "test-publisher"; /** * The documentation for Prebid.js Adapter 1.0 can be found at link below, @@ -14,14 +14,6 @@ export const QUANTCAST_TEST_PUBLISHER = 'test-publisher'; export const spec = { code: BIDDER_CODE, - // `BaseAdapter` model saves adapter from having to make the AJAX call - // provides consistency adapter structure. - // `BaseAdapter` defines 4 entry points, - // - `isBidRequestValid` - // - `buildRequests` - // - `interpretResponse` - // - `getUserSyncs` - /** * Verify the `AdUnits.bids` response with `true` for valid request and `false` * for invalid request. @@ -34,7 +26,7 @@ export const spec = { return false; } - if (bid.mediaType === 'video') { + if (bid.mediaType === "video") { return false; } @@ -61,7 +53,7 @@ export const spec = { // Switch the callback URL to Quantcast Canary Endpoint for testing purpose // `//` is not used because we have different port setting at our end switch (window.location.protocol) { - case 'https:': + case "https:": publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8443/qchb`; publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; break; @@ -111,9 +103,8 @@ export const spec = { return { data, - method: 'POST', - url, - withCredentials: true + method: "POST", + url }; }); @@ -136,10 +127,10 @@ export const spec = { if ( response === undefined || - !response.hasOwnProperty('bids') || + !response.hasOwnProperty("bids") || utils.isEmpty(response.bids) ) { - utils.logError('Sub-optimal JSON received from Quantcast server'); + utils.logError("Sub-optimal JSON received from Quantcast server"); return []; } @@ -147,21 +138,15 @@ export const spec = { const { ad, cpm, width, height } = bid; return { - ad, + requestId: response.requestId, cpm, width, height, - requestId: response.requestId, - bidderCode: response.bidderCode || BIDDER_CODE + ad }; }); return bidResponsesList; - }, - - getUserSyncs(syncOptions) { - // Quantcast does not do `UserSyncs` at the moment. - // This feature will be supported at a later time. } }; From 4b1aef8151fb3f2d54ff8ef46e09cf93967cbd83 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Wed, 25 Oct 2017 09:55:06 +0800 Subject: [PATCH 20/24] Update the spec --- test/spec/modules/quantcastBidAdapter_spec.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index a0895502033..bb10e0682da 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -103,12 +103,6 @@ describe('Quantcast adapter', () => { expect(requests[0].method).to.equal('POST'); }); - it('sends bid requests with `withCredentials` enabled', () => { - const requests = qcSpec.buildRequests([bidRequest]); - - expect(requests[0].withCredentials).to.equal(true); - }); - it('sends bid requests contains all the required parameters', () => { const referrer = utils.getTopWindowUrl(); const loc = utils.getTopWindowLocation(); @@ -183,8 +177,7 @@ describe('Quantcast adapter', () => { cpm: 4.5, width: 300, height: 250, - requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', - bidderCode: 'qcx' + requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458' }; const interpretedResponse = qcSpec.interpretResponse(response); From 2b560226ee147d01a21a221c544e59598d47a0ca Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Wed, 25 Oct 2017 09:56:13 +0800 Subject: [PATCH 21/24] Change code using single quote --- modules/quantcastBidAdapter.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 89e1d0efa5f..cd513111870 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -1,11 +1,11 @@ -import * as utils from "src/utils"; -import { registerBidder } from "src/adapters/bidderFactory"; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; -const BIDDER_CODE = "quantcast"; +const BIDDER_CODE = 'quantcast'; const DEFAULT_BID_FLOOR = 0.0000000001; -export const QUANTCAST_CALLBACK_URL = "global.qc.rtb.quantserve.com"; -export const QUANTCAST_CALLBACK_URL_TEST = "s2s-canary.quantserve.com"; -export const QUANTCAST_TEST_PUBLISHER = "test-publisher"; +export const QUANTCAST_CALLBACK_URL = 'global.qc.rtb.quantserve.com'; +export const QUANTCAST_CALLBACK_URL_TEST = 's2s-canary.quantserve.com'; +export const QUANTCAST_TEST_PUBLISHER = 'test-publisher'; /** * The documentation for Prebid.js Adapter 1.0 can be found at link below, @@ -26,7 +26,7 @@ export const spec = { return false; } - if (bid.mediaType === "video") { + if (bid.mediaType === 'video') { return false; } @@ -53,7 +53,7 @@ export const spec = { // Switch the callback URL to Quantcast Canary Endpoint for testing purpose // `//` is not used because we have different port setting at our end switch (window.location.protocol) { - case "https:": + case 'https:': publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8443/qchb`; publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; break; @@ -103,7 +103,7 @@ export const spec = { return { data, - method: "POST", + method: 'POST', url }; }); @@ -127,10 +127,10 @@ export const spec = { if ( response === undefined || - !response.hasOwnProperty("bids") || + !response.hasOwnProperty('bids') || utils.isEmpty(response.bids) ) { - utils.logError("Sub-optimal JSON received from Quantcast server"); + utils.logError('Sub-optimal JSON received from Quantcast server'); return []; } From bee2344ab901d411e7855fbef81ca2a4a704cf30 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Wed, 25 Oct 2017 10:12:49 +0800 Subject: [PATCH 22/24] Update the first argument for interpretResponse method and its spec --- modules/quantcastBidAdapter.js | 2 +- test/spec/modules/quantcastBidAdapter_spec.js | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index cd513111870..e059bfdb4e4 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -123,7 +123,7 @@ export const spec = { * */ interpretResponse(serverResponse) { - const response = serverResponse; + const response = serverResponse['body']; if ( response === undefined || diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index bb10e0682da..c38a0b77334 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -136,7 +136,7 @@ describe('Quantcast adapter', () => { describe('`interpretResponse`', () => { // The sample response is from https://wiki.corp.qc/display/adinf/QCX - const response = { + const body = { bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames bids: [ @@ -152,6 +152,11 @@ describe('Quantcast adapter', () => { ] }; + const response = { + body, + headers: {} + }; + it('should return an empty array if `serverResponse` is `undefined`', () => { const interpretedResponse = qcSpec.interpretResponse(); @@ -185,11 +190,15 @@ describe('Quantcast adapter', () => { }); it('handles no bid response', () => { - const response = { + const body = { bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames bids: [] }; + const response = { + body, + headers: {} + }; const expectedResponse = []; const interpretedResponse = qcSpec.interpretResponse(response); From 417852e46d6a50829604c6bf8ae9d9ed8a776f7d Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Wed, 25 Oct 2017 10:23:23 +0800 Subject: [PATCH 23/24] Handle undefined Server Response --- modules/quantcastBidAdapter.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index e059bfdb4e4..0d0d2040476 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -123,6 +123,11 @@ export const spec = { * */ interpretResponse(serverResponse) { + if (serverResponse === undefined) { + utils.logError('Server Response is undefined'); + return []; + } + const response = serverResponse['body']; if ( From d6a00e6d9ef4a25af3b9bdfc4e7c1605ca53d726 Mon Sep 17 00:00:00 2001 From: Li Xinyang Date: Wed, 25 Oct 2017 12:31:53 +0800 Subject: [PATCH 24/24] Add required params from the server response --- modules/quantcastBidAdapter.js | 11 +++++++++-- test/spec/modules/quantcastBidAdapter_spec.js | 18 +++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 0d0d2040476..f10fd48502f 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -3,9 +3,12 @@ import { registerBidder } from 'src/adapters/bidderFactory'; const BIDDER_CODE = 'quantcast'; const DEFAULT_BID_FLOOR = 0.0000000001; + export const QUANTCAST_CALLBACK_URL = 'global.qc.rtb.quantserve.com'; export const QUANTCAST_CALLBACK_URL_TEST = 's2s-canary.quantserve.com'; +export const QUANTCAST_NET_REVENUE = true; export const QUANTCAST_TEST_PUBLISHER = 'test-publisher'; +export const QUANTCAST_TTL = 4; /** * The documentation for Prebid.js Adapter 1.0 can be found at link below, @@ -140,14 +143,18 @@ export const spec = { } const bidResponsesList = response.bids.map(bid => { - const { ad, cpm, width, height } = bid; + const { ad, cpm, width, height, creativeId, currency } = bid; return { requestId: response.requestId, cpm, width, height, - ad + ad, + ttl: QUANTCAST_TTL, + creativeId, + netRevenue: QUANTCAST_NET_REVENUE, + currency }; }); diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index c38a0b77334..14981f198b6 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,9 +1,11 @@ import * as utils from 'src/utils'; import { expect } from 'chai'; import { - spec as qcSpec, + QUANTCAST_CALLBACK_URL_TEST, QUANTCAST_CALLBACK_URL, - QUANTCAST_CALLBACK_URL_TEST + QUANTCAST_NET_REVENUE, + QUANTCAST_TTL, + spec as qcSpec } from '../../../modules/quantcastBidAdapter'; import { newBidder } from '../../../src/adapters/bidderFactory'; @@ -144,8 +146,10 @@ describe('Quantcast adapter', () => { statusCode: 1, placementCode: 'imp1', // Changing this to placementCode to be reflective cpm: 4.5, + currency: 'USD', ad: '
Quantcast
', + creativeId: 1001, width: 300, height: 250 } @@ -177,12 +181,16 @@ describe('Quantcast adapter', () => { it('should get correct bid response', () => { const expectedResponse = { - ad: - '
Quantcast
', + requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', cpm: 4.5, width: 300, height: 250, - requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458' + ad: + '
Quantcast
', + ttl: QUANTCAST_TTL, + creativeId: 1001, + netRevenue: QUANTCAST_NET_REVENUE, + currency: 'USD' }; const interpretedResponse = qcSpec.interpretResponse(response);