From ee93a3fd6dc7e14d933d08d4ff2f80ee5fa0d8c7 Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Tue, 26 Nov 2024 23:27:43 +0900 Subject: [PATCH 01/11] Michao Bid Adapter: Initial release --- modules/michaoBidAdapter.js | 222 ++++++++ modules/michaoBidAdapter.md | 58 +++ test/spec/modules/michaoBidAdapter_spec.js | 577 +++++++++++++++++++++ 3 files changed, 857 insertions(+) create mode 100644 modules/michaoBidAdapter.js create mode 100644 modules/michaoBidAdapter.md create mode 100644 test/spec/modules/michaoBidAdapter_spec.js diff --git a/modules/michaoBidAdapter.js b/modules/michaoBidAdapter.js new file mode 100644 index 00000000000..41dd6d9234e --- /dev/null +++ b/modules/michaoBidAdapter.js @@ -0,0 +1,222 @@ +import { ortbConverter } from '../libraries/ortbConverter/converter.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { Renderer } from '../src/Renderer.js'; +import { + deepSetValue, + isStr, + logError, + replaceAuctionPrice, + triggerPixel, +} from '../src/utils.js'; + +const ENV = { + BIDDER_CODE: 'michao', + SUPPORTED_MEDIA_TYPES: [BANNER, VIDEO], + ENDPOINT: 'https://rtb.michao-ssp.com/openrtb/prebid', + NET_REVENUE: true, + DEFAULT_CURRENCY: 'USD', + RENDERER_URL: + 'https://cdn.jsdelivr.net/npm/in-renderer-js@latest/dist/in-renderer.umd.min.js', +}; + +export const spec = { + code: ENV.BIDDER_CODE, + supportedMediaTypes: ENV.SUPPORTED_MEDIA_TYPES, + + isBidRequestValid: function (bid) { + if (!hasParamsObject(bid)) { + return false; + } + + if (!validateMichaoParams(bid.params)) { + domainLogger.bidRequestValidationError(); + return false; + } + + return true; + }, + + buildRequests: function (validBidRequests, bidderRequest) { + const bidRequests = []; + + validBidRequests.forEach((validBidRequest) => { + if ( + hasVideoMediaType(validBidRequest) && + hasBannerMediaType(validBidRequest) + ) { + bidRequests.push( + buildRequest(validBidRequest, bidderRequest, 'banner') + ); + bidRequests.push(buildRequest(validBidRequest, bidderRequest, 'video')); + } else if (hasVideoMediaType(validBidRequest)) { + bidRequests.push(buildRequest(validBidRequest, bidderRequest, 'video')); + } else if (hasBannerMediaType(validBidRequest)) { + bidRequests.push( + buildRequest(validBidRequest, bidderRequest, 'banner') + ); + } + }); + + return bidRequests; + }, + + interpretResponse: function (serverResponse, request) { + return interpretResponse(serverResponse, request); + }, + + getUserSyncs: function ( + syncOptions, + serverResponses, + gdprConsent, + uspConsent + ) { + if (syncOptions.iframeEnabled) { + return [syncUser(gdprConsent)]; + } + }, + + onBidBillable: function (bid) { + if (bid.burl && isStr(bid.burl)) { + billBid(bid); + } + }, +}; + +export const domainLogger = { + bidRequestValidationError() { + logError('Michao: wrong format of site or placement.'); + }, +}; + +export function buildRequest(bidRequest, bidderRequest, mediaType) { + const openRTBBidRequest = converter.toORTB({ + bidRequests: [bidRequest], + bidderRequest, + context: { + mediaType: mediaType, + }, + }); + + return { + method: 'POST', + url: ENV.ENDPOINT, + data: openRTBBidRequest, + options: { contentType: 'application/json', withCredentials: true }, + }; +} + +export function interpretResponse(response, request) { + const bids = converter.fromORTB({ + response: response.body, + request: request.data, + }).bids; + + return bids; +} + +export function syncUser(gdprConsent) { + let gdprParams = ''; + + if (typeof gdprConsent === 'object') { + if (typeof gdprConsent.gdprApplies === 'boolean') { + gdprParams = `gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${ + gdprConsent.consentString + }`; + } else { + gdprParams = `gdpr_consent=${gdprConsent.consentString}`; + } + } + + return { + type: 'iframe', + url: 'https://sync.michao-ssp.com/cookie-syncs?' + gdprParams, + }; +} + +export function addRenderer(bid) { + bid.renderer.push(() => { + const inRenderer = new window.InRenderer(); + inRenderer.render(bid.adUnitCode, bid); + }); +} + +export function hasParamsObject(bid) { + return typeof bid.params === 'object'; +} + +export function validateMichaoParams(params) { + const michaoParams = ['site', 'placement']; + return michaoParams.every((michaoParam) => + Number.isFinite(params[michaoParam]) + ); +} + +export function billBid(bid) { + bid.burl = replaceAuctionPrice(bid.burl, bid.originalCpm || bid.cpm); + triggerPixel(bid.burl); +} + +const converter = ortbConverter({ + request(buildRequest, imps, bidderRequest, context) { + const bidRequest = context.bidRequests[0]; + const openRTBBidRequest = buildRequest(imps, bidderRequest, context); + openRTBBidRequest.cur = [ENV.DEFAULT_CURRENCY]; + openRTBBidRequest.test = config.getConfig('debug') ? 1 : 0; + deepSetValue( + openRTBBidRequest, + 'site.id', + bidRequest.params.site.toString() + ); + if (bidRequest?.schain) { + deepSetValue(openRTBBidRequest, 'source.schain', bidRequest.schain); + } + + return openRTBBidRequest; + }, + + imp(buildImp, bidRequest, context) { + const imp = buildImp(bidRequest, context); + // imp.id = bidRequest.adUnitCode; + deepSetValue(imp, 'ext.placement', bidRequest.params.placement.toString()); + + return imp; + }, + + bidResponse(buildBidResponse, bid, context) { + const { bidRequest } = context; + let bidResponse = buildBidResponse(bid, context); + if (bidRequest.mediaTypes.video?.context === 'outstream') { + const renderer = Renderer.install({ + id: bid.bidId, + url: ENV.RENDERER_URL, + adUnitCode: bid.adUnitCode, + }); + renderer.setRender(addRenderer); + bidResponse.renderer = renderer; + } + + return bidResponse; + }, + + context: { + netRevenue: ENV.NET_REVENUE, + currency: ENV.DEFAULT_CURRENCY, + ttl: 360, + }, +}); + +function hasBannerMediaType(bid) { + return hasMediaType(bid, 'banner'); +} + +function hasVideoMediaType(bid) { + return hasMediaType(bid, 'video'); +} + +function hasMediaType(bid, mediaType) { + return bid.mediaTypes.hasOwnProperty(mediaType); +} + +registerBidder(spec); diff --git a/modules/michaoBidAdapter.md b/modules/michaoBidAdapter.md new file mode 100644 index 00000000000..8767d04abd7 --- /dev/null +++ b/modules/michaoBidAdapter.md @@ -0,0 +1,58 @@ +# Overview + +```markdown +Module Name: Michao Bidder Adapter +Module Type: Bidder Adapter +Maintainer: miyamoto.kai@lookverin.com +``` + +# Description + +Module that connects to Michao’s demand sources + +Supported Ad format: +* Banner +* Video (instream and outstream) + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'banner-div', + mediaTypes: { + banner: { + sizes: [[300, 250]], + } + }, + bids: [{ + bidder: 'michao', + params: { + site: 1, + placement: 1, + } + }] + }, + // Video adUnit + { + code: 'video-div', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480], + minduration: 0, + maxduration: 120, + mimes: ['video/mp4'], + protocols: [7] + } + }, + bids: [{ + bidder: 'michao', + params: { + site: 1, + placement: 1, + } + }] + } +]; +``` diff --git a/test/spec/modules/michaoBidAdapter_spec.js b/test/spec/modules/michaoBidAdapter_spec.js new file mode 100644 index 00000000000..ad64a66f5f9 --- /dev/null +++ b/test/spec/modules/michaoBidAdapter_spec.js @@ -0,0 +1,577 @@ +import { expect } from 'chai'; +import { + addRenderer, + billBid, + buildRequest, + interpretResponse, + spec, + syncUser, + validateMichaoParams, +} from '../../../modules/michaoBidAdapter'; +import * as utils from 'src/utils.js'; +import { config } from '../../../src/config'; + +describe('the michao bidder adapter', () => { + beforeEach(() => { + config.resetConfig(); + }); + + describe('unit', () => { + describe('validate bid request', () => { + const invalidBidParams = [ + { site: '123', placement: 'super-placement' }, + { site: '123', placement: 456 }, + { site: Infinity, placement: 456 }, + ]; + invalidBidParams.forEach((params) => { + it('Detecting incorrect parameters', () => { + const result = validateMichaoParams(params); + + expect(result).to.be.false; + }); + }); + + it('If the site ID and placement ID are correct, the verification succeeds.', () => { + const params = { + site: 123, + placement: 234, + }; + + const result = validateMichaoParams(params); + + expect(result).to.be.true; + }); + }); + + describe('build bid request', () => { + it('Banner bid requests are converted to banner server request objects', () => { + const bannerBidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { banner: [[300, 250]] }, + params: { + site: 123, + placement: 456, + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [bannerBidRequest], + }; + + const result = buildRequest(bannerBidRequest, bidderRequest, 'banner'); + + expect(result).to.nested.include({ + url: 'https://rtb.michao-ssp.com/openrtb/prebid', + 'options.contentType': 'application/json', + 'options.withCredentials': true, + method: 'POST', + 'data.cur[0]': 'USD', + 'data.imp[0].ext.placement': '456', + 'data.site.id': '123', + 'data.test': 0, + }); + }); + + it('Video bid requests are converted to video server request objects', () => { + const videoBidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480], + mimes: ['video/mp4'], + }, + }, + params: { + site: 123, + placement: 456, + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [videoBidRequest], + }; + + const result = buildRequest(videoBidRequest, bidderRequest, 'banner'); + + expect(result).to.nested.include({ + url: 'https://rtb.michao-ssp.com/openrtb/prebid', + 'options.contentType': 'application/json', + 'options.withCredentials': true, + method: 'POST', + 'data.cur[0]': 'USD', + 'data.imp[0].ext.placement': '456', + 'data.site.id': '123', + 'data.test': 0, + }); + }); + + it('Converted to server request object for testing in debug mode', () => { + const bidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { banner: [[300, 250]] }, + params: { + site: 123, + placement: 456, + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [bidRequest], + }; + config.setConfig({ + debug: true, + }); + + const result = buildRequest(bidRequest, bidderRequest, 'banner'); + + expect(result).to.nested.include({ + 'data.test': 1, + }); + }); + }); + + describe('interpret response', () => { + it('Server response is interpreted as a bid.', () => { + const response = { + headers: null, + body: { + id: 'requestId', + seatbid: [ + { + bid: [ + { + id: 'bidId1', + impid: 'bidId1', + price: 0.18, + adm: '', + adid: '144762342', + adomain: ['https://dummydomain.com'], + iurl: 'iurl', + cid: '109', + crid: 'creativeId', + cat: [], + w: 300, + h: 250, + mtype: 1, + }, + ], + seat: 'seat', + }, + ], + cur: 'USD', + }, + }; + const bannerBidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: 'bidId1', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { banner: [[300, 250]] }, + params: { + site: 123, + placement: 456, + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [bannerBidRequest], + }; + const request = buildRequest(bannerBidRequest, bidderRequest, 'banner'); + + const result = interpretResponse(response, request); + + expect(result).to.be.an('array'); + expect(result[0]).to.have.property('currency', 'USD'); + expect(result[0]).to.have.property('requestId', 'bidId1'); + expect(result[0]).to.have.property('cpm', 0.18); + expect(result[0]).to.have.property('width', 300); + expect(result[0]).to.have.property('height', 250); + expect(result[0]).to.have.property('ad', ''); + expect(result[0]).to.have.property('creativeId', 'creativeId'); + expect(result[0]).to.have.property('netRevenue', true); + }); + + it('Empty server responses are interpreted as empty bids', () => { + const response = { body: {} }; + const bannerBidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { banner: [[300, 250]] }, + params: { + site: 123, + placement: 456, + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [bannerBidRequest], + }; + const request = buildRequest(bannerBidRequest, bidderRequest, 'banner'); + + const result = interpretResponse(response, request); + + expect(result).to.be.an('array'); + expect(result.length).to.equal(0); + }); + + it('Set renderer with outstream video ads', () => { + const response = { + headers: null, + body: { + id: 'requestId', + seatbid: [ + { + bid: [ + { + id: 'bidId1', + impid: 'bidId1', + price: 0.18, + adm: '', + adid: '144762342', + adomain: ['https://dummydomain.com'], + iurl: 'iurl', + cid: '109', + crid: 'creativeId', + cat: [], + w: 300, + h: 250, + mtype: 1, + }, + ], + seat: 'seat', + }, + ], + cur: 'USD', + }, + }; + const videoBidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: 'bidId1', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480], + }, + }, + params: { + site: 123, + placement: 456, + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [videoBidRequest], + }; + const request = buildRequest(videoBidRequest, bidderRequest, 'video'); + + const result = interpretResponse(response, request); + + expect(result).to.be.an('array'); + expect(result[0]).to.have.property('currency', 'USD'); + expect(result[0]).to.have.property('requestId', 'bidId1'); + expect(result[0]).to.have.property('cpm', 0.18); + expect(result[0]).to.have.property('width', 300); + expect(result[0]).to.have.property('height', 250); + expect(result[0]).to.have.property('vastXml', ''); + expect(result[0]).to.have.property('creativeId', 'creativeId'); + expect(result[0]).to.have.property('netRevenue', true); + expect(result[0]).to.have.property('mediaType', 'video'); + expect(result[0]).to.have.property('renderer'); + }); + }); + + describe('user syncs', () => { + it('Sync Users', () => { + const gdprConsent = { + gdprApplies: false, + consentString: '', + }; + + const result = syncUser(gdprConsent); + + expect(result).to.deep.equal({ + type: 'iframe', + url: 'https://sync.michao-ssp.com/cookie-syncs?gdpr=0&gdpr_consent=', + }); + }); + }); + + describe('bill a bid', () => { + const triggerPixelSpy = sinon.spy(utils, 'triggerPixel'); + const bid = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { banner: [[300, 250]] }, + params: { + site: 123, + placement: 456, + }, + burl: 'https://example.com/burl', + }; + + billBid(bid); + + expect(triggerPixelSpy.calledWith('https://example.com/burl')).to.true; + triggerPixelSpy.restore(); + }); + + describe('renderer', () => { + it('Set outstream renderer', () => { + const bid = { + renderer: [], + }; + + addRenderer(bid); + + expect(bid.renderer[0]).that.is.a('function'); + }); + }); + }); + + describe('integration', () => { + it('`isBidRequestValid`', () => { + const validBidRequest = { + params: { + placement: 124, + site: 456, + }, + }; + + const result = spec.isBidRequestValid(validBidRequest); + + expect(result).to.true; + }); + + it('`buildRequests`', () => { + const validBidRequests = [ + { + adUnitCode: 'test-div', + auctionId: 'auction-1', + bidId: 'bid-1', + bidder: 'michao', + bidderRequestId: 'bidder-request-1', + mediaTypes: { + banner: { + sizes: [[300, 250]], + }, + }, + params: { + site: 12, + placement: 12, + }, + }, + { + adUnitCode: 'test-div', + auctionId: 'auction-1', + bidId: 'bid-2', + bidder: 'michao', + bidderRequestId: 'bidder-request-1', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [640, 480], + mimes: ['video/mp4'], + minduration: 0, + maxduration: 30, + }, + }, + params: { + site: 12, + placement: 12, + }, + }, + ]; + const bidderRequest = { + auctionId: 'auction-1', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: 'bidder-request-1', + }; + + const result = spec.buildRequests(validBidRequests, bidderRequest); + + expect(result.length).to.equal(2); + }); + + it('`interpretResponse`', () => { + const response = { + headers: null, + body: { + id: 'requestId', + seatbid: [ + { + bid: [ + { + id: 'bidId1', + impid: 'bidId1', + price: 0.18, + adm: '', + adid: '144762342', + adomain: ['https://dummydomain.com'], + iurl: 'iurl', + cid: '109', + crid: 'creativeId', + cat: [], + w: 640, + h: 480, + mtype: 1, + }, + ], + seat: 'seat', + }, + ], + cur: 'USD', + }, + }; + const bannerBidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: 'bidId1', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { + video: { + context: 'outstream', + mimes: ['video/mp4'], + minduration: 0, + maxduration: 120, + }, + }, + params: { + site: 123, + placement: 456, + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [bannerBidRequest], + }; + const request = buildRequest(bannerBidRequest, bidderRequest, 'banner'); + + const result = interpretResponse(response, request); + + expect(result).to.be.an('array'); + expect(result[0]).to.have.property('currency', 'USD'); + expect(result[0]).to.have.property('requestId', 'bidId1'); + expect(result[0]).to.have.property('cpm', 0.18); + expect(result[0]).to.have.property('width', 640); + expect(result[0]).to.have.property('height', 480); + expect(result[0]).to.have.property('ad', ''); + expect(result[0]).to.have.property('creativeId', 'creativeId'); + expect(result[0]).to.have.property('netRevenue', true); + }); + + it('`getUserSyncs`', () => { + const syncOptions = { + iframeEnabled: true, + }; + const gdprConsent = { + gdprApplies: true, + consentString: + 'CQIhBPbQIhBPbEkAAAENCZCAAAAAAAAAAAAAAAAAAAAA.II7Nd_X__bX9n-_7_6ft0eY1f9_r37uQzDhfNs-8F3L_W_LwX32E7NF36tq4KmR4ku1bBIQNtHMnUDUmxaolVrzHsak2cpyNKJ_JkknsZe2dYGF9Pn9lD-YKZ7_5_9_f52T_9_9_-39z3_9f___dv_-__-vjf_599n_v9fV_78_Kf9______-____________8A', + }; + + const result = spec.getUserSyncs(syncOptions, {}, gdprConsent); + + expect(result).to.deep.equal([ + { + type: 'iframe', + url: 'https://sync.michao-ssp.com/cookie-syncs?gdpr=1&gdpr_consent=CQIhBPbQIhBPbEkAAAENCZCAAAAAAAAAAAAAAAAAAAAA.II7Nd_X__bX9n-_7_6ft0eY1f9_r37uQzDhfNs-8F3L_W_LwX32E7NF36tq4KmR4ku1bBIQNtHMnUDUmxaolVrzHsak2cpyNKJ_JkknsZe2dYGF9Pn9lD-YKZ7_5_9_f52T_9_9_-39z3_9f___dv_-__-vjf_599n_v9fV_78_Kf9______-____________8A', + }, + ]); + }); + + it('`onBidBillable`', () => { + const triggerPixelSpy = sinon.spy(utils, 'triggerPixel'); + const bid = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { banner: [[300, 250]] }, + params: { + site: 123, + placement: 456, + }, + burl: 'https://example.com/burl', + }; + + spec.onBidBillable(bid); + + expect(triggerPixelSpy.calledWith('https://example.com/burl')).to.true; + triggerPixelSpy.restore(); + }); + }); +}); From 2b0d4fd56456a19a619b4d7bc5fd365a3182768f Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Wed, 27 Nov 2024 17:33:58 +0900 Subject: [PATCH 02/11] Michao Bid Adapter: Fix incomprehensible integration tests --- test/spec/modules/michaoBidAdapter_spec.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/spec/modules/michaoBidAdapter_spec.js b/test/spec/modules/michaoBidAdapter_spec.js index ad64a66f5f9..f66e1da895b 100644 --- a/test/spec/modules/michaoBidAdapter_spec.js +++ b/test/spec/modules/michaoBidAdapter_spec.js @@ -467,7 +467,7 @@ describe('the michao bidder adapter', () => { id: 'bidId1', impid: 'bidId1', price: 0.18, - adm: '', + adm: '
ad
', adid: '144762342', adomain: ['https://dummydomain.com'], iurl: 'iurl', @@ -495,11 +495,8 @@ describe('the michao bidder adapter', () => { bidderRequestsCount: 1, bidderWinsCount: 0, mediaTypes: { - video: { - context: 'outstream', - mimes: ['video/mp4'], - minduration: 0, - maxduration: 120, + banner: { + sizes: [[300, 250]] }, }, params: { @@ -524,7 +521,7 @@ describe('the michao bidder adapter', () => { expect(result[0]).to.have.property('cpm', 0.18); expect(result[0]).to.have.property('width', 640); expect(result[0]).to.have.property('height', 480); - expect(result[0]).to.have.property('ad', ''); + expect(result[0]).to.have.property('ad', '
ad
'); expect(result[0]).to.have.property('creativeId', 'creativeId'); expect(result[0]).to.have.property('netRevenue', true); }); From ae817a3b15dbc1002b691dfaee2fb2cddd54043e Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Wed, 27 Nov 2024 19:06:30 +0900 Subject: [PATCH 03/11] Michao Bid Adapter: Explicitly specify VAST XML --- modules/michaoBidAdapter.js | 19 +++++++++++-------- test/spec/modules/michaoBidAdapter_spec.js | 3 +++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/modules/michaoBidAdapter.js b/modules/michaoBidAdapter.js index 41dd6d9234e..678d80f560d 100644 --- a/modules/michaoBidAdapter.js +++ b/modules/michaoBidAdapter.js @@ -187,14 +187,17 @@ const converter = ortbConverter({ bidResponse(buildBidResponse, bid, context) { const { bidRequest } = context; let bidResponse = buildBidResponse(bid, context); - if (bidRequest.mediaTypes.video?.context === 'outstream') { - const renderer = Renderer.install({ - id: bid.bidId, - url: ENV.RENDERER_URL, - adUnitCode: bid.adUnitCode, - }); - renderer.setRender(addRenderer); - bidResponse.renderer = renderer; + if (hasVideoMediaType(bidRequest)) { + bidResponse.vastXml = bid.adm; + if (bidRequest.mediaTypes.video?.context === 'outstream') { + const renderer = Renderer.install({ + id: bid.bidId, + url: ENV.RENDERER_URL, + adUnitCode: bid.adUnitCode, + }); + renderer.setRender(addRenderer); + bidResponse.renderer = renderer; + } } return bidResponse; diff --git a/test/spec/modules/michaoBidAdapter_spec.js b/test/spec/modules/michaoBidAdapter_spec.js index f66e1da895b..0548f9689fe 100644 --- a/test/spec/modules/michaoBidAdapter_spec.js +++ b/test/spec/modules/michaoBidAdapter_spec.js @@ -304,6 +304,9 @@ describe('the michao bidder adapter', () => { video: { context: 'outstream', playerSize: [640, 480], + minduration: 0, + maxduration: 30, + protocols: [7] }, }, params: { From 27d6259f85db3287078918bdd632f4a6096992a9 Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Wed, 27 Nov 2024 19:22:58 +0900 Subject: [PATCH 04/11] Michao Bid Adapter: Support for rewarded advertising --- modules/michaoBidAdapter.js | 11 +++-- test/spec/modules/michaoBidAdapter_spec.js | 47 ++++++++++++++++++---- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/modules/michaoBidAdapter.js b/modules/michaoBidAdapter.js index 678d80f560d..4254fb0c10d 100644 --- a/modules/michaoBidAdapter.js +++ b/modules/michaoBidAdapter.js @@ -147,10 +147,15 @@ export function hasParamsObject(bid) { } export function validateMichaoParams(params) { - const michaoParams = ['site', 'placement']; - return michaoParams.every((michaoParam) => + let valid = true; + + const michaoAdUnitInfoParams = ['site', 'placement']; + + valid = michaoAdUnitInfoParams.every((michaoParam) => Number.isFinite(params[michaoParam]) ); + + return valid } export function billBid(bid) { @@ -178,8 +183,8 @@ const converter = ortbConverter({ imp(buildImp, bidRequest, context) { const imp = buildImp(bidRequest, context); - // imp.id = bidRequest.adUnitCode; deepSetValue(imp, 'ext.placement', bidRequest.params.placement.toString()); + deepSetValue(imp, 'rwdd', bidRequest.params?.reward ? 1 : false); return imp; }, diff --git a/test/spec/modules/michaoBidAdapter_spec.js b/test/spec/modules/michaoBidAdapter_spec.js index 0548f9689fe..c7e2f427a4c 100644 --- a/test/spec/modules/michaoBidAdapter_spec.js +++ b/test/spec/modules/michaoBidAdapter_spec.js @@ -159,6 +159,41 @@ describe('the michao bidder adapter', () => { 'data.test': 1, }); }); + + it('Specifying a reward builds a bid request for the reward.', () => { + const bidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { banner: [[300, 250]] }, + params: { + site: 123, + placement: 456, + reward: true, + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [bidRequest], + }; + config.setConfig({ + debug: true, + }); + + const result = buildRequest(bidRequest, bidderRequest, 'banner'); + + expect(result).to.nested.include({ + 'data.imp[0].rwdd': 1, + }); + }); }); describe('interpret response', () => { @@ -427,17 +462,13 @@ describe('the michao bidder adapter', () => { }, { adUnitCode: 'test-div', - auctionId: 'auction-1', + auctionId: 'auction-2', bidId: 'bid-2', bidder: 'michao', - bidderRequestId: 'bidder-request-1', + bidderRequestId: 'bidder-request-2', mediaTypes: { - video: { - context: 'outstream', - playerSize: [640, 480], - mimes: ['video/mp4'], - minduration: 0, - maxduration: 30, + banner: { + sizes: [[300, 250]], }, }, params: { From 522b79d75b3eb338cf8af22df4deda366163e264 Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Wed, 27 Nov 2024 21:55:51 +0900 Subject: [PATCH 05/11] Michao Bid Adapter: Re-run E2e test --- modules/michaoBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/michaoBidAdapter.js b/modules/michaoBidAdapter.js index 4254fb0c10d..821e3ef1061 100644 --- a/modules/michaoBidAdapter.js +++ b/modules/michaoBidAdapter.js @@ -86,7 +86,7 @@ export const spec = { export const domainLogger = { bidRequestValidationError() { - logError('Michao: wrong format of site or placement.'); + logError('Michao Bid Adapter: wrong format of site or placement.'); }, }; From d8313fc1ada6eeeff43e521a5e2aa3abe43a0e30 Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Tue, 3 Dec 2024 04:11:20 +0900 Subject: [PATCH 06/11] Michao Bid Adapter: Support for native format --- modules/michaoBidAdapter.js | 28 ++++--- test/spec/modules/michaoBidAdapter_spec.js | 86 +++++++++++++++++++++- 2 files changed, 99 insertions(+), 15 deletions(-) diff --git a/modules/michaoBidAdapter.js b/modules/michaoBidAdapter.js index 821e3ef1061..f5d7ba6d757 100644 --- a/modules/michaoBidAdapter.js +++ b/modules/michaoBidAdapter.js @@ -1,7 +1,7 @@ import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { Renderer } from '../src/Renderer.js'; import { deepSetValue, @@ -13,7 +13,7 @@ import { const ENV = { BIDDER_CODE: 'michao', - SUPPORTED_MEDIA_TYPES: [BANNER, VIDEO], + SUPPORTED_MEDIA_TYPES: [BANNER, VIDEO, NATIVE], ENDPOINT: 'https://rtb.michao-ssp.com/openrtb/prebid', NET_REVENUE: true, DEFAULT_CURRENCY: 'USD', @@ -42,19 +42,19 @@ export const spec = { const bidRequests = []; validBidRequests.forEach((validBidRequest) => { - if ( - hasVideoMediaType(validBidRequest) && - hasBannerMediaType(validBidRequest) - ) { + if (hasVideoMediaType(validBidRequest)) { + bidRequests.push(buildRequest(validBidRequest, bidderRequest, 'video')); + } + + if (hasBannerMediaType(validBidRequest)) { bidRequests.push( buildRequest(validBidRequest, bidderRequest, 'banner') ); - bidRequests.push(buildRequest(validBidRequest, bidderRequest, 'video')); - } else if (hasVideoMediaType(validBidRequest)) { - bidRequests.push(buildRequest(validBidRequest, bidderRequest, 'video')); - } else if (hasBannerMediaType(validBidRequest)) { + } + + if (hasNativeMediaType(validBidRequest)) { bidRequests.push( - buildRequest(validBidRequest, bidderRequest, 'banner') + buildRequest(validBidRequest, bidderRequest, 'native') ); } }); @@ -184,7 +184,7 @@ const converter = ortbConverter({ imp(buildImp, bidRequest, context) { const imp = buildImp(bidRequest, context); deepSetValue(imp, 'ext.placement', bidRequest.params.placement.toString()); - deepSetValue(imp, 'rwdd', bidRequest.params?.reward ? 1 : false); + deepSetValue(imp, 'rwdd', bidRequest.params?.reward ? 1 : 0); return imp; }, @@ -223,6 +223,10 @@ function hasVideoMediaType(bid) { return hasMediaType(bid, 'video'); } +function hasNativeMediaType(bid) { + return hasMediaType(bid, 'native'); +} + function hasMediaType(bid, mediaType) { return bid.mediaTypes.hasOwnProperty(mediaType); } diff --git a/test/spec/modules/michaoBidAdapter_spec.js b/test/spec/modules/michaoBidAdapter_spec.js index c7e2f427a4c..90c4c4fd559 100644 --- a/test/spec/modules/michaoBidAdapter_spec.js +++ b/test/spec/modules/michaoBidAdapter_spec.js @@ -126,6 +126,58 @@ describe('the michao bidder adapter', () => { }); }); + it('Native bid requests are converted to video server request objects', () => { + const nativeBidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { + native: { + ortb: { + assets: [ + { + id: 2, + required: 1, + title: { + len: 80 + } + } + ] + } + } + }, + params: { + site: 123, + placement: 456, + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [nativeBidRequest], + }; + + const result = buildRequest(nativeBidRequest, bidderRequest, 'native'); + + expect(result).to.nested.include({ + url: 'https://rtb.michao-ssp.com/openrtb/prebid', + 'options.contentType': 'application/json', + 'options.withCredentials': true, + method: 'POST', + 'data.cur[0]': 'USD', + 'data.imp[0].ext.placement': '456', + 'data.site.id': '123', + 'data.test': 0, + }); + }); + it('Converted to server request object for testing in debug mode', () => { const bidRequest = { adUnitCode: 'test-div', @@ -467,8 +519,36 @@ describe('the michao bidder adapter', () => { bidder: 'michao', bidderRequestId: 'bidder-request-2', mediaTypes: { - banner: { - sizes: [[300, 250]], + video: { + context: 'outstream', + playerSize: [640, 480], + mimes: ['video/mp4'], + }, + }, + params: { + site: 12, + placement: 12, + }, + }, + { + adUnitCode: 'test-div', + auctionId: 'auction-2', + bidId: 'bid-2', + bidder: 'michao', + bidderRequestId: 'bidder-request-2', + mediaTypes: { + native: { + ortb: { + assets: [ + { + id: 2, + required: 1, + title: { + len: 80 + } + } + ] + } }, }, params: { @@ -486,7 +566,7 @@ describe('the michao bidder adapter', () => { const result = spec.buildRequests(validBidRequests, bidderRequest); - expect(result.length).to.equal(2); + expect(result.length).to.equal(3); }); it('`interpretResponse`', () => { From 222861367b927ddf793f57ff95ae1ef9c8b2a6c3 Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Tue, 3 Dec 2024 06:02:32 +0900 Subject: [PATCH 07/11] Michao Bid Adapter: Change renderer URL --- modules/michaoBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/michaoBidAdapter.js b/modules/michaoBidAdapter.js index f5d7ba6d757..fb72eda2762 100644 --- a/modules/michaoBidAdapter.js +++ b/modules/michaoBidAdapter.js @@ -18,7 +18,7 @@ const ENV = { NET_REVENUE: true, DEFAULT_CURRENCY: 'USD', RENDERER_URL: - 'https://cdn.jsdelivr.net/npm/in-renderer-js@latest/dist/in-renderer.umd.min.js', + 'https://cdn.jsdelivr.net/npm/in-renderer-js@latest/dist/in-video-renderer.umd.min.js', }; export const spec = { @@ -137,7 +137,7 @@ export function syncUser(gdprConsent) { export function addRenderer(bid) { bid.renderer.push(() => { - const inRenderer = new window.InRenderer(); + const inRenderer = new window.InVideoRenderer(); inRenderer.render(bid.adUnitCode, bid); }); } From 08d9ce2647dd4e7df1c4cfe0e61fc7e25ff1ace1 Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Wed, 4 Dec 2024 03:43:46 +0900 Subject: [PATCH 08/11] Michao Bid Adapter: Support for blocked categories and blocked advertisers --- modules/michaoBidAdapter.js | 2 + test/spec/modules/michaoBidAdapter_spec.js | 72 +++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/modules/michaoBidAdapter.js b/modules/michaoBidAdapter.js index fb72eda2762..a843496eac6 100644 --- a/modules/michaoBidAdapter.js +++ b/modules/michaoBidAdapter.js @@ -169,6 +169,8 @@ const converter = ortbConverter({ const openRTBBidRequest = buildRequest(imps, bidderRequest, context); openRTBBidRequest.cur = [ENV.DEFAULT_CURRENCY]; openRTBBidRequest.test = config.getConfig('debug') ? 1 : 0; + openRTBBidRequest.bcat = bidRequest.params?.bcat || []; + openRTBBidRequest.badv = bidRequest.params?.badv || []; deepSetValue( openRTBBidRequest, 'site.id', diff --git a/test/spec/modules/michaoBidAdapter_spec.js b/test/spec/modules/michaoBidAdapter_spec.js index 90c4c4fd559..259b08d1ac9 100644 --- a/test/spec/modules/michaoBidAdapter_spec.js +++ b/test/spec/modules/michaoBidAdapter_spec.js @@ -212,7 +212,7 @@ describe('the michao bidder adapter', () => { }); }); - it('Specifying a reward builds a bid request for the reward.', () => { + it('Specifying a reward builds a bid request for the reward', () => { const bidRequest = { adUnitCode: 'test-div', auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', @@ -246,6 +246,76 @@ describe('the michao bidder adapter', () => { 'data.imp[0].rwdd': 1, }); }); + + it('Block categories are set in the bid request through parameters', () => { + const bidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { banner: [[300, 250]] }, + params: { + site: 123, + placement: 456, + bcat: ['IAB2'] + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [bidRequest], + }; + config.setConfig({ + debug: true, + }); + + const result = buildRequest(bidRequest, bidderRequest, 'banner'); + + expect(result).to.nested.include({ + 'data.bcat[0]': 'IAB2', + }); + }); + + it('Block advertisers set in bid request through parameters', () => { + const bidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { banner: [[300, 250]] }, + params: { + site: 123, + placement: 456, + badv: ['adomain.com'] + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [bidRequest], + }; + config.setConfig({ + debug: true, + }); + + const result = buildRequest(bidRequest, bidderRequest, 'banner'); + + expect(result).to.nested.include({ + 'data.badv[0]': 'adomain.com', + }); + }); }); describe('interpret response', () => { From dfd29c96990d49c614bb7cf259161ab2b1739684 Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Wed, 4 Dec 2024 10:00:47 +0900 Subject: [PATCH 09/11] Michao Bid Adapter: Change placement to string type --- modules/michaoBidAdapter.js | 11 ++++--- modules/michaoBidAdapter.md | 33 +++++++++++++++++-- test/spec/modules/michaoBidAdapter_spec.js | 38 +++++++++++----------- 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/modules/michaoBidAdapter.js b/modules/michaoBidAdapter.js index a843496eac6..8b598617dac 100644 --- a/modules/michaoBidAdapter.js +++ b/modules/michaoBidAdapter.js @@ -5,6 +5,7 @@ import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { Renderer } from '../src/Renderer.js'; import { deepSetValue, + isNumber, isStr, logError, replaceAuctionPrice, @@ -149,11 +150,13 @@ export function hasParamsObject(bid) { export function validateMichaoParams(params) { let valid = true; - const michaoAdUnitInfoParams = ['site', 'placement']; + if (!isNumber(params?.site)) { + valid = false; + } - valid = michaoAdUnitInfoParams.every((michaoParam) => - Number.isFinite(params[michaoParam]) - ); + if (!isStr(params?.placement)) { + valid = false; + } return valid } diff --git a/modules/michaoBidAdapter.md b/modules/michaoBidAdapter.md index 8767d04abd7..b45e8e2b5bd 100644 --- a/modules/michaoBidAdapter.md +++ b/modules/michaoBidAdapter.md @@ -13,6 +13,7 @@ Module that connects to Michao’s demand sources Supported Ad format: * Banner * Video (instream and outstream) +* Native # Test Parameters ``` @@ -29,7 +30,7 @@ var adUnits = [ bidder: 'michao', params: { site: 1, - placement: 1, + placement: '1', } }] }, @@ -50,7 +51,35 @@ var adUnits = [ bidder: 'michao', params: { site: 1, - placement: 1, + placement: '1', + } + }] + }, + // Native AdUnit + { + code: 'native-div', + mediaTypes: { + native: { + ortb: { + assets: [ + { + id: 1, + required: 1, + img: { + type: 3, + w: 989, + h: 742, + }, + }, + ] + } + } + }, + bids: [{ + bidder: 'michao', + params: { + site: 1, + placement: '1', } }] } diff --git a/test/spec/modules/michaoBidAdapter_spec.js b/test/spec/modules/michaoBidAdapter_spec.js index 259b08d1ac9..fce71baea58 100644 --- a/test/spec/modules/michaoBidAdapter_spec.js +++ b/test/spec/modules/michaoBidAdapter_spec.js @@ -34,7 +34,7 @@ describe('the michao bidder adapter', () => { it('If the site ID and placement ID are correct, the verification succeeds.', () => { const params = { site: 123, - placement: 234, + placement: 'placement' }; const result = validateMichaoParams(params); @@ -57,7 +57,7 @@ describe('the michao bidder adapter', () => { mediaTypes: { banner: [[300, 250]] }, params: { site: 123, - placement: 456, + placement: '456', }, }; const bidderRequest = { @@ -101,7 +101,7 @@ describe('the michao bidder adapter', () => { }, params: { site: 123, - placement: 456, + placement: '456', }, }; const bidderRequest = { @@ -153,7 +153,7 @@ describe('the michao bidder adapter', () => { }, params: { site: 123, - placement: 456, + placement: '456', }, }; const bidderRequest = { @@ -191,7 +191,7 @@ describe('the michao bidder adapter', () => { mediaTypes: { banner: [[300, 250]] }, params: { site: 123, - placement: 456, + placement: '456', }, }; const bidderRequest = { @@ -225,7 +225,7 @@ describe('the michao bidder adapter', () => { mediaTypes: { banner: [[300, 250]] }, params: { site: 123, - placement: 456, + placement: '456', reward: true, }, }; @@ -260,7 +260,7 @@ describe('the michao bidder adapter', () => { mediaTypes: { banner: [[300, 250]] }, params: { site: 123, - placement: 456, + placement: '456', bcat: ['IAB2'] }, }; @@ -295,7 +295,7 @@ describe('the michao bidder adapter', () => { mediaTypes: { banner: [[300, 250]] }, params: { site: 123, - placement: 456, + placement: '456', badv: ['adomain.com'] }, }; @@ -361,7 +361,7 @@ describe('the michao bidder adapter', () => { mediaTypes: { banner: [[300, 250]] }, params: { site: 123, - placement: 456, + placement: '456', }, }; const bidderRequest = { @@ -400,7 +400,7 @@ describe('the michao bidder adapter', () => { mediaTypes: { banner: [[300, 250]] }, params: { site: 123, - placement: 456, + placement: '456', }, }; const bidderRequest = { @@ -468,7 +468,7 @@ describe('the michao bidder adapter', () => { }, params: { site: 123, - placement: 456, + placement: '456', }, }; const bidderRequest = { @@ -526,7 +526,7 @@ describe('the michao bidder adapter', () => { mediaTypes: { banner: [[300, 250]] }, params: { site: 123, - placement: 456, + placement: '456', }, burl: 'https://example.com/burl', }; @@ -554,8 +554,8 @@ describe('the michao bidder adapter', () => { it('`isBidRequestValid`', () => { const validBidRequest = { params: { - placement: 124, - site: 456, + placement: '124', + site: 234, }, }; @@ -579,7 +579,7 @@ describe('the michao bidder adapter', () => { }, params: { site: 12, - placement: 12, + placement: '12', }, }, { @@ -597,7 +597,7 @@ describe('the michao bidder adapter', () => { }, params: { site: 12, - placement: 12, + placement: '12', }, }, { @@ -623,7 +623,7 @@ describe('the michao bidder adapter', () => { }, params: { site: 12, - placement: 12, + placement: '12', }, }, ]; @@ -685,7 +685,7 @@ describe('the michao bidder adapter', () => { }, params: { site: 123, - placement: 456, + placement: '456', }, }; const bidderRequest = { @@ -744,7 +744,7 @@ describe('the michao bidder adapter', () => { mediaTypes: { banner: [[300, 250]] }, params: { site: 123, - placement: 456, + placement: '456', }, burl: 'https://example.com/burl', }; From 1fb9d7e654da05bc20632f5fe0a19c40b89f272e Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Wed, 4 Dec 2024 10:24:31 +0900 Subject: [PATCH 10/11] Michao Bid Adapter: Add minimum bid price --- modules/michaoBidAdapter.js | 1 + test/spec/modules/michaoBidAdapter_spec.js | 35 ++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/modules/michaoBidAdapter.js b/modules/michaoBidAdapter.js index 8b598617dac..953f0e05268 100644 --- a/modules/michaoBidAdapter.js +++ b/modules/michaoBidAdapter.js @@ -190,6 +190,7 @@ const converter = ortbConverter({ const imp = buildImp(bidRequest, context); deepSetValue(imp, 'ext.placement', bidRequest.params.placement.toString()); deepSetValue(imp, 'rwdd', bidRequest.params?.reward ? 1 : 0); + deepSetValue(imp, 'bidfloor', isNumber(bidRequest.params?.bidFloor) ? bidRequest.params?.bidFloor : 0); return imp; }, diff --git a/test/spec/modules/michaoBidAdapter_spec.js b/test/spec/modules/michaoBidAdapter_spec.js index fce71baea58..adf76b633ea 100644 --- a/test/spec/modules/michaoBidAdapter_spec.js +++ b/test/spec/modules/michaoBidAdapter_spec.js @@ -316,6 +316,41 @@ describe('the michao bidder adapter', () => { 'data.badv[0]': 'adomain.com', }); }); + + it('The lowest bid will be set', () => { + const bidRequest = { + adUnitCode: 'test-div', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: '22c4871113f461', + bidder: 'michao', + bidderRequestId: '15246a574e859f', + bidRequestsCount: 1, + bidderRequestsCount: 1, + bidderWinsCount: 0, + mediaTypes: { banner: [[300, 250]] }, + params: { + site: 123, + placement: '456', + bidFloor: 1, + }, + }; + const bidderRequest = { + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + auctionStart: 1579746300522, + bidderCode: 'michao', + bidderRequestId: '15246a574e859f', + bids: [bidRequest], + }; + config.setConfig({ + debug: true, + }); + + const result = buildRequest(bidRequest, bidderRequest, 'banner'); + + expect(result).to.nested.include({ + 'data.imp[0].bidfloor': 1, + }); + }); }); describe('interpret response', () => { From 0c0d5e4fe5386eb2a05fc20eda3e34d62ca4e734 Mon Sep 17 00:00:00 2001 From: Kai Miyamoto Date: Wed, 4 Dec 2024 10:51:59 +0900 Subject: [PATCH 11/11] Michao Bid Adapter: Added log system validation to integration testing for parameter validation --- test/spec/modules/michaoBidAdapter_spec.js | 37 ++++++++++++++++------ 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/test/spec/modules/michaoBidAdapter_spec.js b/test/spec/modules/michaoBidAdapter_spec.js index adf76b633ea..47dea68b538 100644 --- a/test/spec/modules/michaoBidAdapter_spec.js +++ b/test/spec/modules/michaoBidAdapter_spec.js @@ -3,6 +3,7 @@ import { addRenderer, billBid, buildRequest, + domainLogger, interpretResponse, spec, syncUser, @@ -586,17 +587,35 @@ describe('the michao bidder adapter', () => { }); describe('integration', () => { - it('`isBidRequestValid`', () => { - const validBidRequest = { - params: { - placement: '124', - site: 234, - }, - }; + describe('`isBidRequestValid`', () => { + it('Happy path', () => { + const validBidRequest = { + params: { + placement: '124', + site: 234, + }, + }; + + const result = spec.isBidRequestValid(validBidRequest); - const result = spec.isBidRequestValid(validBidRequest); + expect(result).to.true; + }); - expect(result).to.true; + it('If the parameter is invalid, it will be logged', () => { + const validationErrorLog = sinon.spy(domainLogger, 'bidRequestValidationError'); + const validBidRequest = { + params: { + placement: '124', + site: '234', + }, + }; + + const result = spec.isBidRequestValid(validBidRequest); + + expect(result).to.false; + expect(validationErrorLog.calledOnce).to.true; + validationErrorLog.restore(); + }); }); it('`buildRequests`', () => {