diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 2da04ad3e3..4c249512e8 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -162,37 +162,11 @@ function isBidRequestValid(bidRequest) { } function buildRequests(bidRequests, bidderRequest) { - const videoRequests = bidRequests.filter(bidRequest => isVideoBidRequest(bidRequest)); - const bannerAndNativeRequests = bidRequests.filter(bidRequest => isBannerBidRequest(bidRequest) || isNativeBidRequest(bidRequest)) - // In case of multi-format bids remove `video` from mediaTypes as for video a separate bid request is built - .map(bid => ({...bid, mediaTypes: {...bid.mediaTypes, video: undefined}})); - - const requests = bannerAndNativeRequests.length ? [createRequest(bannerAndNativeRequests, bidderRequest, null)] : []; - videoRequests.forEach(bid => { - requests.push(createRequest([bid], bidderRequest, VIDEO)); - }); - return requests; -} - -function createRequest(bidRequests, bidderRequest, mediaType) { - return { + return [{ method: 'POST', url: config.getConfig('openxOrtbUrl') || REQUEST_URL, - data: converter.toORTB({bidRequests, bidderRequest, context: {mediaType}}) - } -} - -function isVideoBidRequest(bidRequest) { - return utils.deepAccess(bidRequest, 'mediaTypes.video'); -} - -function isNativeBidRequest(bidRequest) { - return utils.deepAccess(bidRequest, 'mediaTypes.native'); -} - -function isBannerBidRequest(bidRequest) { - const isNotVideoOrNativeBid = !isVideoBidRequest(bidRequest) && !isNativeBidRequest(bidRequest) - return utils.deepAccess(bidRequest, 'mediaTypes.banner') || isNotVideoOrNativeBid; + data: converter.toORTB({bidRequests, bidderRequest}) + }]; } function interpretResponse(resp, req) { diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index dfcdecdf58..4f3f2bfd8d 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -416,16 +416,12 @@ describe('OpenxRtbAdapter', function () { playerSize: [640, 480] }; const requests = spec.buildRequests([multiformat], mockBidderRequest); - expect(requests).to.have.length(2); + expect(requests).to.have.length(1); expect(requests[0].data.imp).to.have.length(1); expect(requests[0].data.imp[0].banner).to.exist; - expect(requests[0].data.imp[0].video).to.not.exist; expect(requests[0].data.imp[0].native).to.not.exist; - expect(requests[1].data.imp).to.have.length(1); - expect(requests[1].data.imp[0].banner).to.not.exist; - expect(requests[1].data.imp[0].native).to.not.exist; if (FEATURES.VIDEO) { - expect(requests[1].data.imp[0].video).to.exist; + expect(requests[0].data.imp[0].video).to.exist; } }) @@ -454,21 +450,33 @@ describe('OpenxRtbAdapter', function () { sizes: [[300, 250]] } const requests = spec.buildRequests([multiformat], mockBidderRequest); - expect(requests).to.have.length(2); + expect(requests).to.have.length(1); expect(requests[0].data.imp).to.have.length(1); expect(requests[0].data.imp[0].banner).to.exist; - expect(requests[0].data.imp[0].video).to.not.exist; if (FEATURES.NATIVE) { expect(requests[0].data.imp[0].native).to.exist; } - expect(requests[1].data.imp).to.have.length(1); - expect(requests[1].data.imp[0].banner).to.not.exist; - expect(requests[1].data.imp[0].native).to.not.exist; if (FEATURES.VIDEO) { - expect(requests[1].data.imp[0].video).to.exist; + expect(requests[0].data.imp[0].video).to.exist; } }) + it('should send banner, video and native bids in a single HTTP request', function () { + const allBids = [...bidRequestsWithMediaTypes, nativeBidRequest]; + const request = spec.buildRequests(allBids, mockBidderRequest); + expect(request).to.have.length(1); + expect(request[0].data.imp).to.have.length(3); + expect(request[0].data.imp[0].banner).to.exist; + if (FEATURES.VIDEO) { + const videoImp = request[0].data.imp.find(imp => imp.id === bidRequestsWithMediaTypes[1].bidId); + expect(videoImp.video).to.exist; + } + if (FEATURES.NATIVE) { + const nativeImp = request[0].data.imp.find(imp => imp.id === nativeBidRequest.bidId); + expect(nativeImp.native).to.exist; + } + }); + it('should send bid request to openx url via POST', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); expect(request[0].url).to.equal(REQUEST_URL); @@ -482,19 +490,26 @@ describe('OpenxRtbAdapter', function () { expect(request[0].data.ext.platformId).to.be.undefined; }); - it('should send platform id, if available', function () { + it('should send platform id from first bid, if available', function () { bidRequestsWithMediaTypes[0].params.platform = '1cabba9e-cafe-3665-beef-f00f00f00f00'; bidRequestsWithMediaTypes[1].params.platform = '51ca3159-abc2-4035-8e00-fe26eaa09397'; const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); + expect(request.length).to.equal(1); expect(request[0].data.ext.platform).to.equal(bidRequestsWithMediaTypes[0].params.platform); - expect(request[1].data.ext.platform).to.equal(bidRequestsWithMediaTypes[1].params.platform); + }); + + it('should send delDomain from first bid when bids have different delDomains', function () { + bidRequestsWithMediaTypes[0].params.delDomain = 'domain-a.test'; + bidRequestsWithMediaTypes[1].params.delDomain = 'domain-b.test'; + const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); + expect(request[0].data.ext.delDomain).to.equal('domain-a.test'); }); it('should send openx adunit codes', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); expect(request[0].data.imp[0].tagid).to.equal(bidRequestsWithMediaTypes[0].params.unit); - expect(request[1].data.imp[0].tagid).to.equal(bidRequestsWithMediaTypes[1].params.unit); + expect(request[0].data.imp[1].tagid).to.equal(bidRequestsWithMediaTypes[1].params.unit); }); it('should send out custom params on bids that have customParams specified', function () { @@ -563,7 +578,7 @@ describe('OpenxRtbAdapter', function () { expect(request[0].data.imp[0].bidfloorcur).to.equal('USD'); }); - it('should send not send floors', function () { + it('should not send floors', function () { adServerCurrencyStub.returns('EUR'); const bidRequest = Object.assign({}, bidRequestsWithMediaTypes[0], @@ -904,7 +919,6 @@ describe('OpenxRtbAdapter', function () { it('should send a signal to specify that US Privacy applies to this request', async function () { const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); expect(request[0].data.regs.ext.us_privacy).to.equal('1YYN'); - expect(request[1].data.regs.ext.us_privacy).to.equal('1YYN'); }); it('should not send the regs object, when consent string is undefined', async function () { @@ -946,21 +960,18 @@ describe('OpenxRtbAdapter', function () { bidderRequest.bids = bidRequests; const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); expect(request[0].data.regs.ext.gdpr).to.equal(1); - expect(request[1].data.regs.ext.gdpr).to.equal(1); }); it('should send the consent string', async function () { bidderRequest.bids = bidRequests; const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); expect(request[0].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); - expect(request[1].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); }); it('should send the addtlConsent string', async function () { bidderRequest.bids = bidRequests; const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); expect(request[0].data.user.ext.ConsentedProvidersSettings.consented_providers).to.equal(bidderRequest.gdprConsent.addtlConsent); - expect(request[1].data.user.ext.ConsentedProvidersSettings.consented_providers).to.equal(bidderRequest.gdprConsent.addtlConsent); }); it('should send a signal to specify that GDPR does not apply to this request', async function () { @@ -968,7 +979,6 @@ describe('OpenxRtbAdapter', function () { bidderRequest.bids = bidRequests; const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); expect(request[0].data.regs.ext.gdpr).to.equal(0); - expect(request[1].data.regs.ext.gdpr).to.equal(0); }); it('when GDPR application is undefined, should not send a signal to specify whether GDPR applies to this request, ' + @@ -978,7 +988,6 @@ describe('OpenxRtbAdapter', function () { const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); expect(request[0].data.regs?.ext?.gdpr).to.not.be.ok; expect(request[0].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); - expect(request[1].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); }); it('when consent string is undefined, should not send the consent string, ', async function () { @@ -986,7 +995,7 @@ describe('OpenxRtbAdapter', function () { bidderRequest.bids = bidRequests; const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest)); expect(request[0].data.imp[0].ext.consent).to.equal(undefined); - expect(request[1].data.imp[0].ext.consent).to.equal(undefined); + expect(request[0].data.imp[1].ext.consent).to.equal(undefined); }); }); @@ -1002,8 +1011,6 @@ describe('OpenxRtbAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request[0].data.regs.gpp).to.equal('test-gpp-string'); expect(request[0].data.regs.gpp_sid).to.deep.equal([6]); - expect(request[1].data.regs.gpp).to.equal('test-gpp-string'); - expect(request[1].data.regs.gpp_sid).to.deep.equal([6]); }); it('should not send GPP string and GPP section IDs in bid request when not available', async function () { @@ -1014,8 +1021,6 @@ describe('OpenxRtbAdapter', function () { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request[0].data.regs.gpp).to.not.exist; expect(request[0].data.regs.gpp_sid).to.not.exist; - expect(request[1].data.regs.gpp).to.not.exist; - expect(request[1].data.regs.gpp_sid).to.not.exist; }); }); }); @@ -1251,7 +1256,7 @@ describe('OpenxRtbAdapter', function () { context('video', function () { it('should send bid request with a mediaTypes specified with video type', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); - expect(request[1].data.imp[0]).to.have.any.keys(VIDEO); + expect(request[0].data.imp[1]).to.have.any.keys(VIDEO); }); it('Update imp.video with OpenRTB options from mimeTypes and params', function() { @@ -1288,8 +1293,8 @@ describe('OpenxRtbAdapter', function () { h: 250 }; const requests = spec.buildRequests([bid01], bidderRequest); - expect(requests).to.have.lengthOf(2); - expect(requests[1].data.imp[0].video).to.deep.equal(expected); + expect(requests).to.have.lengthOf(1); + expect(requests[0].data.imp[0].video).to.deep.equal(expected); }); }); } @@ -1573,6 +1578,7 @@ describe('OpenxRtbAdapter', function () { crid: 'test-creative-id', dealid: 'test-deal-id', adm: '', + mtype: 2, }] }], cur: 'AUS' @@ -1693,6 +1699,39 @@ describe('OpenxRtbAdapter', function () { }); } + context('when multiple bid requests (banner + video) are in one request and both bids are returned', function() { + it('should correctly return both banner and video bids', function () { + const bidRequestConfigs = [ + { + bidder: 'openx', params: { unit: '1', delDomain: 'test-del-domain' }, + adUnitCode: 'au-1', mediaTypes: { banner: { sizes: [[300, 250]] } }, + bidId: 'bid-id-banner', bidderRequestId: 'br-1', auctionId: 'a-1' + }, + { + bidder: 'openx', params: { unit: '2', delDomain: 'test-del-domain' }, + adUnitCode: 'au-2', mediaTypes: { video: { playerSize: [640, 480] } }, + bidId: 'bid-id-video', bidderRequestId: 'br-1', auctionId: 'a-1' + } + ]; + const bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; + const bidResponse = { + seatbid: [{ + bid: [ + { impid: 'bid-id-banner', price: 1, adm: '
ad
', mtype: 1 }, + { impid: 'bid-id-video', price: 2, adm: '', mtype: 2 } + ] + }], + cur: 'USD' + }; + const result = spec.interpretResponse({ body: bidResponse }, bidRequest); + expect(result.bids).to.have.length(2); + expect(result.bids[0].mediaType).to.equal(BANNER); + expect(result.bids[1].mediaType).to.equal(VIDEO); + expect(result.bids[0].requestId).to.equal('bid-id-banner'); + expect(result.bids[1].requestId).to.equal('bid-id-video'); + }); + }); + if (FEATURES.NATIVE) { context('when native request and the response is a native', function() { beforeEach(function () {