diff --git a/modules/showheroes-bsBidAdapter.js b/modules/showheroes-bsBidAdapter.js index 2ae7cc56c0f..2831d793aad 100644 --- a/modules/showheroes-bsBidAdapter.js +++ b/modules/showheroes-bsBidAdapter.js @@ -29,6 +29,7 @@ export const spec = { return !!bid.params.playerId; }, buildRequests: function(validBidRequests, bidderRequest) { + let adUnits = []; const pageURL = validBidRequests[0].params.contentPageUrl || bidderRequest.refererInfo.referer; const isStage = !!validBidRequests[0].params.stage; const isOutstream = utils.deepAccess(validBidRequests[0], 'mediaTypes.video.context') === 'outstream'; @@ -38,53 +39,53 @@ export const spec = { const outstreamOptions = utils.deepAccess(validBidRequests[0], 'params.outstreamOptions'); const isBanner = !!validBidRequests[0].mediaTypes.banner || (isOutstream && !(isCustomRender || isNativeRender || isNodeRender)); - let adUnits = validBidRequests.map((bid) => { + validBidRequests.forEach((bid) => { + const videoSizes = getVideoSizes(bid); + const bannerSizes = getBannerSizes(bid); const vpaidMode = utils.getBidIdParameter('vpaidMode', bid.params); - let sizes = bid.sizes.length === 1 ? bid.sizes[0] : bid.sizes; - if (sizes && !sizes.length) { - let mediaSize; - let mediaVideoSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); - if (utils.isArray(mediaVideoSize)) { - mediaSize = mediaVideoSize; + const makeBids = (type, size) => { + let context = ''; + let streamType = 2; + + if (type === BANNER) { + streamType = 5; } else { - mediaSize = bid.mediaTypes.banner.sizes; - } - if (utils.isArray(mediaSize[0])) { - sizes = mediaSize[0]; - } else if (utils.isNumber(mediaSize[0])) { - sizes = mediaSize; + context = utils.deepAccess(bid, 'mediaTypes.video.context'); + if (vpaidMode && context === 'instream') { + streamType = 1; + } + if (context === 'outstream') { + streamType = 5; + } } - } - const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - - let streamType = 2; + return { + type: streamType, + bidId: bid.bidId, + mediaType: type, + context: context, + playerId: utils.getBidIdParameter('playerId', bid.params), + auctionId: bidderRequest.auctionId, + bidderCode: BIDDER_CODE, + gdprConsent: bidderRequest.gdprConsent, + start: +new Date(), + timeout: 3000, + size: { + width: size[0], + height: size[1] + }, + params: bid.params, + }; + }; - if (vpaidMode && context === 'instream') { - streamType = 1; - } - if (isBanner || context === 'outstream') { - streamType = 5; - } + videoSizes.forEach((size) => { + adUnits.push(makeBids(VIDEO, size)); + }); - return { - type: streamType, - bidId: bid.bidId, - mediaType: isBanner ? BANNER : VIDEO, - context: context, - playerId: utils.getBidIdParameter('playerId', bid.params), - auctionId: bidderRequest.auctionId, - bidderCode: BIDDER_CODE, - gdprConsent: bidderRequest.gdprConsent, - start: +new Date(), - timeout: 3000, - video: { - width: sizes[0], - height: sizes[1] - }, - params: bid.params, - }; + bannerSizes.forEach((size) => { + adUnits.push(makeBids(BANNER, size)); + }); }); return { @@ -94,6 +95,7 @@ export const spec = { data: { 'user': [], 'meta': { + 'adapterVersion': 2, 'pageURL': encodeURIComponent(pageURL), 'vastCacheEnabled': (!!config.getConfig('cache') && !isBanner && !outstreamOptions) || false, 'isDesktop': utils.getWindowTop().document.documentElement.clientWidth > 700, @@ -156,12 +158,12 @@ function createBids(bidRes, reqData) { bidUnit.cpm = bid.cpm; bidUnit.requestId = bid.bidId; bidUnit.currency = bid.currency; - bidUnit.mediaType = reqBid.mediaType || VIDEO; + bidUnit.mediaType = bid.mediaType || VIDEO; bidUnit.ttl = TTL; bidUnit.creativeId = 'c_' + bid.bidId; bidUnit.netRevenue = true; - bidUnit.width = bid.video.width; - bidUnit.height = bid.video.height; + bidUnit.width = bid.size.width; + bidUnit.height = bid.size.height; if (bid.vastXml) { bidUnit.vastXml = bid.vastXml; bidUnit.adResponse = { @@ -171,16 +173,16 @@ function createBids(bidRes, reqData) { if (bid.vastTag) { bidUnit.vastUrl = bid.vastTag; } - if (reqBid.mediaType === BANNER) { + if (bid.mediaType === BANNER) { bidUnit.ad = getBannerHtml(bid, reqBid, reqData); - } else if (reqBid.context === 'outstream') { + } else if (bid.context === 'outstream') { const renderer = Renderer.install({ id: bid.bidId, url: '//', config: { playerId: reqBid.playerId, - width: bid.video.width, - height: bid.video.height, + width: bid.size.width, + height: bid.size.height, vastUrl: bid.vastTag, vastXml: bid.vastXml, debug: reqData.debug, @@ -267,4 +269,19 @@ function getBannerHtml (bid, reqBid, reqData) { `; } +function getVideoSizes(bidRequest) { + return formatSizes(utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize') || []); +} + +function getBannerSizes(bidRequest) { + return formatSizes(utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes || []); +} + +function formatSizes(sizes) { + if (!sizes || !sizes.length) { + return [] + } + return Array.isArray(sizes[0]) ? sizes : [sizes]; +} + registerBidder(spec); diff --git a/test/spec/modules/showheroes-bsBidAdapter_spec.js b/test/spec/modules/showheroes-bsBidAdapter_spec.js index c82042469ef..4f2fd9d641a 100644 --- a/test/spec/modules/showheroes-bsBidAdapter_spec.js +++ b/test/spec/modules/showheroes-bsBidAdapter_spec.js @@ -79,6 +79,22 @@ const bidRequestBanner = { } } +const bidRequestBannerMultiSizes = { + ...bidRequestCommonParams, + ...{ + 'mediaTypes': { + 'banner': { + 'sizes': [[640, 360], [480, 320]] + } + } + } +} + +const bidRequestVideoAndBanner = { + ...bidRequestBanner, + ...bidRequestVideo +} + describe('shBidAdapter', function () { const adapter = newBidder(spec) @@ -120,8 +136,8 @@ describe('shBidAdapter', function () { }], bidderRequest) const payload = request.data.requests[0]; expect(payload).to.be.an('object'); - expect(payload.video).to.have.property('width', 640); - expect(payload.video).to.have.property('height', 480); + expect(payload.size).to.have.property('width', 640); + expect(payload.size).to.have.property('height', 480); const request2 = spec.buildRequests([{ 'params': {}, @@ -130,8 +146,8 @@ describe('shBidAdapter', function () { }], bidderRequest) const payload2 = request2.data.requests[0]; expect(payload).to.be.an('object'); - expect(payload2.video).to.have.property('width', 320); - expect(payload2.video).to.have.property('height', 240); + expect(payload2.size).to.have.property('width', 320); + expect(payload2.size).to.have.property('height', 240); }) it('should get size from mediaTypes when sizes property is empty', function () { @@ -146,8 +162,8 @@ describe('shBidAdapter', function () { }], bidderRequest) const payload = request.data.requests[0]; expect(payload).to.be.an('object'); - expect(payload.video).to.have.property('width', 640); - expect(payload.video).to.have.property('height', 480); + expect(payload.size).to.have.property('width', 640); + expect(payload.size).to.have.property('height', 480); const request2 = spec.buildRequests([{ 'params': {}, @@ -160,8 +176,8 @@ describe('shBidAdapter', function () { }], bidderRequest) const payload2 = request2.data.requests[0]; expect(payload).to.be.an('object'); - expect(payload2.video).to.have.property('width', 320); - expect(payload2.video).to.have.property('height', 240); + expect(payload2.size).to.have.property('width', 320); + expect(payload2.size).to.have.property('height', 240); }) it('should attach valid params to the payload when type is video', function () { @@ -191,6 +207,38 @@ describe('shBidAdapter', function () { expect(payload).to.have.property('type', 5); }) + it('should attach valid params to the payload when type is banner (multi sizes)', function () { + const request = spec.buildRequests([bidRequestBannerMultiSizes], bidderRequest) + const payload = request.data.requests[0]; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('playerId', '47427aa0-f11a-4d24-abca-1295a46a46cd'); + expect(payload).to.have.property('mediaType', BANNER); + expect(payload).to.have.property('type', 5); + expect(payload).to.have.nested.property('size.width', 640); + expect(payload).to.have.nested.property('size.height', 360); + const payload2 = request.data.requests[1]; + expect(payload2).to.be.an('object'); + expect(payload2).to.have.property('playerId', '47427aa0-f11a-4d24-abca-1295a46a46cd'); + expect(payload2).to.have.property('mediaType', BANNER); + expect(payload2).to.have.property('type', 5); + expect(payload2).to.have.nested.property('size.width', 480); + expect(payload2).to.have.nested.property('size.height', 320); + }) + + it('should attach valid params to the payload when type is banner and video', function () { + const request = spec.buildRequests([bidRequestVideoAndBanner], bidderRequest) + const payload = request.data.requests[0]; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('playerId', '47427aa0-f11a-4d24-abca-1295a46a46cd'); + expect(payload).to.have.property('mediaType', VIDEO); + expect(payload).to.have.property('type', 2); + const payload2 = request.data.requests[1]; + expect(payload2).to.be.an('object'); + expect(payload2).to.have.property('playerId', '47427aa0-f11a-4d24-abca-1295a46a46cd'); + expect(payload2).to.have.property('mediaType', BANNER); + expect(payload2).to.have.property('type', 5); + }) + it('passes gdpr if present', function () { const request = spec.buildRequests([bidRequestVideo], {...bidderRequest, ...gdpr}) const payload = request.data.requests[0]; @@ -208,16 +256,36 @@ describe('shBidAdapter', function () { const vastTag = 'https://video-library.stage.showheroes.com/commercial/wrapper?player_id=47427aa0-f11a-4d24-abca-1295a46a46cd&ad_bidder=showheroes-bs&master_shadt=1&description_url=https%3A%2F%2Fbid-service.stage.showheroes.com%2Fvast%2Fad%2Fcache%2F4840b920-40e1-4e09-9231-60bbf088c8d6' const vastXml = '' - const response = { + const basicResponse = { + 'cpm': 5, + 'currency': 'EUR', + 'mediaType': VIDEO, + 'context': 'instream', + 'bidId': '38b373e1e31c18', + 'size': {'width': 640, 'height': 480}, + 'vastTag': 'https:\/\/video-library.stage.showheroes.com\/commercial\/wrapper?player_id=47427aa0-f11a-4d24-abca-1295a46a46cd&ad_bidder=showheroes-bs&master_shadt=1&description_url=https%3A%2F%2Fbid-service.stage.showheroes.com%2Fvast%2Fad%2Fcache%2F4840b920-40e1-4e09-9231-60bbf088c8d6', + 'vastXml': vastXml, + }; + + const responseVideo = { 'bids': [{ - 'cpm': 5, - 'currency': 'EUR', - 'bidId': '38b373e1e31c18', - 'video': {'width': 640, 'height': 480}, - 'vastTag': 'https:\/\/video-library.stage.showheroes.com\/commercial\/wrapper?player_id=47427aa0-f11a-4d24-abca-1295a46a46cd&ad_bidder=showheroes-bs&master_shadt=1&description_url=https%3A%2F%2Fbid-service.stage.showheroes.com%2Fvast%2Fad%2Fcache%2F4840b920-40e1-4e09-9231-60bbf088c8d6', - 'vastXml': vastXml, + ...basicResponse, }], - } + }; + + const responseVideoOutstream = { + 'bids': [{ + ...basicResponse, + 'context': 'outstream', + }], + }; + + const responseBanner = { + 'bids': [{ + ...basicResponse, + 'mediaType': BANNER, + }], + }; it('should get correct bid response when type is video', function () { const request = spec.buildRequests([bidRequestVideo], bidderRequest) @@ -240,14 +308,14 @@ describe('shBidAdapter', function () { } ] - const result = spec.interpretResponse({'body': response}, request) + const result = spec.interpretResponse({'body': responseVideo}, request) expect(result).to.deep.equal(expectedResponse) }) it('should get correct bid response when type is banner', function () { const request = spec.buildRequests([bidRequestBanner], bidderRequest) - const result = spec.interpretResponse({'body': response}, request) + const result = spec.interpretResponse({'body': responseBanner}, request) expect(result[0]).to.have.property('mediaType', BANNER); expect(result[0].ad).to.include('