diff --git a/modules/a1MediaBidAdapter.js b/modules/a1MediaBidAdapter.js new file mode 100644 index 00000000000..6a137e621c5 --- /dev/null +++ b/modules/a1MediaBidAdapter.js @@ -0,0 +1,89 @@ +import { ortbConverter } from '../libraries/ortbConverter/converter.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js'; + +const BIDDER_CODE = 'a1media'; +const END_POINT = 'https://d11.contentsfeed.com/dsp/breq/a1'; +const DEFAULT_CURRENCY = 'JPY'; + +const converter = ortbConverter({ + context: { + netRevenue: true, + ttl: 30, + }, + imp(buildImp, bidRequest, context) { + const imp = buildImp(bidRequest, context); + if (!imp.bidfloor) { + imp.bidfloor = bidRequest.params.bidfloor || 0; + imp.bidfloorcur = bidRequest.params.currency || DEFAULT_CURRENCY; + } + if (bidRequest.params.battr) { + Object.keys(bidRequest.mediaTypes).forEach(mType => { + imp[mType].battr = bidRequest.params.battr; + }) + } + return imp; + }, + request(buildRequest, imps, bidderRequest, context) { + const request = buildRequest(imps, bidderRequest, context); + const bid = context.bidRequests[0]; + if (!request.cur) { + request.cur = [bid.params.currency || DEFAULT_CURRENCY]; + } + if (bid.params.bcat) { + request.bcat = bid.params.bcat; + } + return request; + }, + bidResponse(buildBidResponse, bid, context) { + const { bidRequest } = context; + + let resMediaType; + const reqMediaTypes = Object.keys(bidRequest.mediaTypes); + if (reqMediaTypes.length === 1) { + resMediaType = reqMediaTypes[0]; + } else { + if (bid.adm.search(/^(<\?xml| { + return { + bidderCode: 'a1media', + auctionId: 'ba87bfdf-493e-4a88-8e26-17b4cbc9adbd', + bidderRequestId: '104e8d2392bd6f', + bids: [ + { + bidder: 'a1media', + params: {}, + auctionId: 'ba87bfdf-493e-4a88-8e26-17b4cbc9adbd', + mediaTypes: { + banner: { + sizes: [ + [ 320, 100 ], + ] + }, + ...(isMulti && { + video: { + mimes: ['video/mp4'] + }, + native: { + title: { + required: true, + }} + }) + }, + ...(isMulti && { + nativeOrtbRequest: { + ver: '1.2', + assets: [ + { + id: 0, + required: 1, + title: { + len: 140 + } + } + ] + } + }), + adUnitCode: 'test-div', + transactionId: 'cab00498-028b-4061-8f9d-a8d66c8cb91d', + bidId: '2e9f38ea93bb9e', + bidderRequestId: '104e8d2392bd6f', + } + ], + } +}; +const getConvertedBidReq = () => { + return { + cur: [ + 'JPY' + ], + imp: [ + { + banner: { + format: [ + { + h: 100, + w: 320 + }, + ], + topframe: 0 + }, + bidfloor: 0, + bidfloorcur: 'JPY', + id: '2e9f38ea93bb9e' + } + ], + test: 0, + } +}; + +const getBidderResponse = () => { + return { + body: { + id: 'bid-response', + cur: 'JPY', + seatbid: [ + { + bid: [{ + impid: '2e9f38ea93bb9e', + crid: 'creative-id', + cur: 'JPY', + price: 9, + }] + } + ] + } + } +} +const bannerAdm = '
'; +const videoAdm = 'testvast1'; +const nativeAdm = '{"ver":"1.2","link":{"url":"test_url"},"assets":[{"id":1,"required":1,"title":{"text":"native_title"}}]}'; + +describe('a1MediaBidAdapter', function() { + describe('isValidRequest', function() { + const bid = { + bidder: 'a1media', + }; + + it('should return true always', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); + + describe('buildRequests', function() { + let bidderRequest, convertedRequest; + beforeEach(function() { + bidderRequest = getBidderRequest(); + convertedRequest = getConvertedBidReq(); + }); + + it('should return expected request object', function() { + const bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest); + convertedRequest.id = bidRequest.data.id; + + expect(bidRequest.method).equal('POST'); + expect(bidRequest.url).equal('https://d11.contentsfeed.com/dsp/breq/a1'); + expect(bidRequest.data).deep.equal(convertedRequest); + }); + it('should set ortb blocking using params', function() { + bidderRequest.bids[0].params = ortbBlockParams; + + const bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest); + convertedRequest.id = bidRequest.data.id; + convertedRequest.bcat = ortbBlockParams.bcat; + convertedRequest.imp[0].banner.battr = ortbBlockParams.battr; + + expect(bidRequest.data).deep.equal(convertedRequest); + }); + + it('should set bidfloor when getFloor is available', function() { + bidderRequest.bids[0].getFloor = () => ({ currency: 'USD', floor: 999 }); + const bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest); + + expect(bidRequest.data.imp[0].bidfloor).equal(999); + expect(bidRequest.data.imp[0].bidfloorcur).equal('USD'); + }); + + it('should set cur when currency config is configured', function() { + config.setConfig({ + currency: { + adServerCurrency: 'USD', + } + }); + const bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest); + + expect(bidRequest.data.cur[0]).equal('USD'); + }); + + it('should set bidfloor and currency using params when modules not available', function() { + bidderRequest.bids[0].params.currency = 'USD'; + bidderRequest.bids[0].params.bidfloor = 0.99; + + const bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest); + convertedRequest.id = bidRequest.data.id; + convertedRequest.imp[0].bidfloor = 0.99; + convertedRequest.imp[0].bidfloorcur = 'USD'; + convertedRequest.cur[0] = 'USD'; + + expect(bidRequest.data).deep.equal(convertedRequest); + }); + }); + + describe('interpretResponse', function() { + describe('when request mediaType is single', function() { + let bidRequest, bidderResponse; + beforeEach(function() { + const bidderRequest = getBidderRequest(); + bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest); + bidderResponse = getBidderResponse(); + }); + it('should set cpm using price attribute', function() { + const bidResPrice = 9; + bidderResponse.body.seatbid[0].bid[0].price = bidResPrice; + const interpretedRes = spec.interpretResponse(bidderResponse, bidRequest); + expect(interpretedRes[0].cpm).equal(bidResPrice); + }); + it('should set mediaType using request mediaTypes', function() { + const interpretedRes = spec.interpretResponse(bidderResponse, bidRequest); + expect(interpretedRes[0].mediaType).equal(BANNER); + }); + }); + + describe('when request mediaType is multi', function() { + let bidRequest, bidderResponse; + beforeEach(function() { + const bidderRequest = getBidderRequest(true); + bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest); + bidderResponse = getBidderResponse(); + }); + it('should set mediaType to video', function() { + bidderResponse.body.seatbid[0].bid[0].adm = videoAdm; + const interpretedRes = spec.interpretResponse(bidderResponse, bidRequest); + expect(interpretedRes[0].mediaType).equal(VIDEO); + }); + it('should set mediaType to native', function() { + bidderResponse.body.seatbid[0].bid[0].adm = nativeAdm; + const interpretedRes = spec.interpretResponse(bidderResponse, bidRequest); + expect(interpretedRes[0].mediaType).equal(NATIVE); + }); + it('should set mediaType to banner when adm is neither native or video', function() { + bidderResponse.body.seatbid[0].bid[0].adm = bannerAdm; + const interpretedRes = spec.interpretResponse(bidderResponse, bidRequest); + expect(interpretedRes[0].mediaType).equal(BANNER); + }); + }); + }); +})