From ecd3815262661bb4e6186e6f6d79f21884e4746a Mon Sep 17 00:00:00 2001 From: dpapworth-qc <50959025+dpapworth-qc@users.noreply.github.com> Date: Fri, 9 Aug 2019 13:21:40 +0100 Subject: [PATCH] Fix for #4047 (#4063) * Changed isBidRequestValid to reject bid requests missing required parameters. * Filter outstream video bid requests. * Improved detection of different media types. Ignore all media types except instream video and banner. * Added test to confirm behaviour with multi-format request. * Removed unnecessary change to bid sizes. * Removed unused imports and tests. * Added log message for unsupported media types. --- modules/quantcastBidAdapter.js | 34 ++--- test/spec/modules/quantcastBidAdapter_spec.js | 131 +++++++++++------- 2 files changed, 100 insertions(+), 65 deletions(-) diff --git a/modules/quantcastBidAdapter.js b/modules/quantcastBidAdapter.js index 64cec7e231a..afe95ffb832 100644 --- a/modules/quantcastBidAdapter.js +++ b/modules/quantcastBidAdapter.js @@ -83,17 +83,7 @@ export const spec = { * @return boolean `true` is this is a valid bid, and `false` otherwise */ isBidRequestValid(bid) { - if (!bid) { - return false; - } - - const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); - const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - if (videoMediaType && context == 'outstream') { - return false; - } - - return true; + return !!bid.params.publisherId; }, /** @@ -112,12 +102,22 @@ export const spec = { const page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href'); const domain = getDomain(page); - const bidRequestsList = bids.map(bid => { + let bidRequestsList = []; + + bids.forEach(bid => { let imp; - const videoContext = utils.deepAccess(bid, 'mediaTypes.video.context'); - if (videoContext === 'instream') { - imp = makeVideoImp(bid); + if (bid.mediaTypes) { + if (bid.mediaTypes.video && bid.mediaTypes.video.context === 'instream') { + imp = makeVideoImp(bid); + } else if (bid.mediaTypes.banner) { + imp = makeBannerImp(bid); + } else { + // Unsupported mediaType + utils.logInfo(`${BIDDER_CODE}: No supported mediaTypes found in ${JSON.stringify(bid.mediaTypes)}`); + return; + } } else { + // Parse as banner by default imp = makeBannerImp(bid); } @@ -143,11 +143,11 @@ export const spec = { : QUANTCAST_DOMAIN; const url = `${QUANTCAST_PROTOCOL}://${qcDomain}:${QUANTCAST_PORT}/qchb`; - return { + bidRequestsList.push({ data, method: 'POST', url - }; + }); }); return bidRequestsList; diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 662641de17b..e29a12a22be 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,6 +1,4 @@ -import * as utils from 'src/utils'; import { expect } from 'chai'; -import { stub, sandbox } from 'sinon'; import { QUANTCAST_DOMAIN, QUANTCAST_TEST_DOMAIN, @@ -13,11 +11,11 @@ import { } from '../../../modules/quantcastBidAdapter'; import { newBidder } from '../../../src/adapters/bidderFactory'; import { parse } from 'src/url'; -import * as ajax from 'src/ajax'; describe('Quantcast adapter', function () { const quantcastAdapter = newBidder(qcSpec); let bidRequest; + let bidderRequest; beforeEach(function () { bidRequest = { @@ -32,6 +30,13 @@ describe('Quantcast adapter', function () { }, sizes: [[300, 250]] }; + + bidderRequest = { + refererInfo: { + referer: 'http://example.com/hello.html', + canonicalUrl: 'http://example.com/hello.html' + } + }; }); function setupVideoBidRequest() { @@ -68,27 +73,25 @@ describe('Quantcast adapter', function () { }); describe('`isBidRequestValid`', function () { - it('should return `false` when bid is not passed', function () { - expect(qcSpec.isBidRequestValid()).to.equal(false); - }); - - it('should return `false` when bid is for outstream video', function () { + it('should return `true` when bid has publisherId', function () { const bidRequest = { - mediaType: 'video', - mediaTypes: { - video: { - context: 'outstream' - } + bidder: 'quantcast', + params: { + publisherId: 'my_publisher_id' } }; - expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); + expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return `true` when bid contains required params', function () { - const bidRequest = { mediaType: 'banner' }; + it('should return `false` when bid has no publisherId', function () { + const bidRequest = { + bidder: 'quantcast', + params: { + } + }; - expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); + expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); }); }); @@ -131,13 +134,6 @@ describe('Quantcast adapter', function () { }); it('sends banner bid requests contains all the required parameters', function () { - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/hello.html', - canonicalUrl: 'http://example.com/hello.html' - } - }; - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); const expectedBannerBidRequest = { publisherId: QUANTCAST_TEST_PUBLISHER, @@ -168,13 +164,6 @@ describe('Quantcast adapter', function () { it('sends video bid requests containing all the required parameters', function () { setupVideoBidRequest(); - const bidderRequest = { - refererInfo: { - referer: 'http://example.com/hello.html', - canonicalUrl: 'http://example.com/hello.html' - } - }; - const requests = qcSpec.buildRequests([bidRequest], bidderRequest); const expectedVideoBidRequest = { publisherId: QUANTCAST_TEST_PUBLISHER, @@ -213,6 +202,69 @@ describe('Quantcast adapter', function () { expect(requests[0].data).to.equal(JSON.stringify(expectedVideoBidRequest)); }); + + it('ignores unsupported video bid requests', function () { + bidRequest.mediaTypes = { + video: { + context: 'outstream', + playerSize: [[550, 310]] + } + }; + + const requests = qcSpec.buildRequests([bidRequest], bidderRequest); + + expect(requests).to.be.empty; + }); + + it('parses multi-format bid request', function () { + bidRequest.mediaTypes = { + banner: {sizes: [[300, 250], [728, 90], [250, 250], [468, 60], [320, 50]]}, + native: { + image: {required: true, sizes: [150, 50]}, + title: {required: true, len: 80}, + sponsoredBy: {required: true}, + clickUrl: {required: true}, + privacyLink: {required: false}, + body: {required: true}, + icon: {required: true, sizes: [50, 50]} + }, + video: { + context: 'outstream', + playerSize: [[550, 310]] + } + }; + bidRequest.sizes = [[300, 250], [728, 90], [250, 250], [468, 60], [320, 50]]; + + const requests = qcSpec.buildRequests([bidRequest], bidderRequest); + const expectedBidRequest = { + publisherId: QUANTCAST_TEST_PUBLISHER, + requestId: '2f7b179d443f14', + imp: [{ + banner: { + battr: [1, 2], + sizes: [ + {width: 300, height: 250}, + {width: 728, height: 90}, + {width: 250, height: 250}, + {width: 468, height: 60}, + {width: 320, height: 50} + ] + }, + placementCode: 'div-gpt-ad-1438287399331-0', + bidFloor: 1e-10 + }], + site: { + page: 'http://example.com/hello.html', + referrer: 'http://example.com/hello.html', + domain: 'example.com' + }, + bidId: '2f7b179d443f14', + gdprSignal: 0, + prebidJsVersion: '$prebid.version$' + }; + + expect(requests[0].data).to.equal(JSON.stringify(expectedBidRequest)); + }); }); it('propagates GDPR consent string and signal', function () { @@ -354,26 +406,9 @@ describe('Quantcast adapter', function () { body, headers: {} }; - const expectedResponse = []; const interpretedResponse = qcSpec.interpretResponse(response); expect(interpretedResponse.length).to.equal(0); }); }); - - // can't stub ajax with es6 anymore, need to fix this - // describe('`onTimeout`', function() { - // it('makes a request to the notify endpoint', function() { - // const sinonSandbox = sandbox.create(); - // const ajaxStub = sinonSandbox.stub(ajax, 'ajax').callsFake(function() {}); - // const timeoutData = { - // bidder: 'quantcast' - // }; - // qcSpec.onTimeout(timeoutData); - // const expectedUrl = `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb_notify?type=timeout`; - // ajaxStub.withArgs(expectedUrl, null, null).calledOnce.should.be.true; - // ajaxStub.restore(); - // sinonSandbox.restore(); - // }); - // }); });