UNPKG

mk9-prebid

Version:

Header Bidding Management Library

541 lines (492 loc) 17.1 kB
import { malltvAnalyticsAdapter, parseBidderCode, parseAdUnitCode, ANALYTICS_VERSION, BIDDER_STATUS, DEFAULT_SERVER } from 'modules/malltvAnalyticsAdapter.js' import { expect } from 'chai' import { getCpmInEur } from '../../../modules/malltvAnalyticsAdapter' import events from 'src/events' import constants from 'src/constants.json' const auctionId = 'b0b39610-b941-4659-a87c-de9f62d3e13e' const propertyId = '123456' const server = 'https://analytics.server.url/v1' describe('Malltv Prebid AnalyticsAdapter Testing', function () { describe('event tracking and message cache manager', function () { beforeEach(function () { const configOptions = { propertyId } sinon.stub(events, 'getEvents').returns([]) malltvAnalyticsAdapter.enableAnalytics({ provider: 'malltvAnalytics', options: configOptions }) }) afterEach(function () { malltvAnalyticsAdapter.disableAnalytics() events.getEvents.restore() }) describe('#getCpmInEur()', function() { it('should get bid cpm as currency is EUR', function() { const receivedBids = [ { auctionId: auctionId, adUnitCode: 'adunit_1', bidder: 'malltv', bidderCode: 'MALLTV', requestId: 'a1b2c3d4', timeToRespond: 72, cpm: 0.1, currency: 'EUR', originalCpm: 0.1, originalCurrency: 'EUR', ad: '<html>fake ad1</html>' }, ] const result = getCpmInEur(receivedBids[0]) expect(result).to.equal(0.1) }) }) describe('#parseBidderCode()', function() { it('should get lower case bidder code from bidderCode field value', function() { const receivedBids = [ { auctionId: auctionId, adUnitCode: 'adunit_1', bidder: 'malltv', bidderCode: 'MALLTV', requestId: 'a1b2c3d4', timeToRespond: 72, cpm: 0.1, currency: 'EUR', originalCpm: 0.1, originalCurrency: 'EUR', ad: '<html>fake ad1</html>' }, ] const result = parseBidderCode(receivedBids[0]) expect(result).to.equal('malltv') }) it('should get lower case bidder code from bidder field value as bidderCode field is missing', function() { const receivedBids = [ { auctionId: auctionId, adUnitCode: 'adunit_1', bidder: 'MALLTV', bidderCode: '', requestId: 'a1b2c3d4', timeToRespond: 72, cpm: 0.1, currency: 'EUR', originalCpm: 0.1, originalCurrency: 'EUR', ad: '<html>fake ad1</html>' }, ] const result = parseBidderCode(receivedBids[0]) expect(result).to.equal('malltv') }) }) describe('#parseAdUnitCode()', function() { it('should get lower case adUnit code from adUnitCode field value', function() { const receivedBids = [ { auctionId: auctionId, adUnitCode: 'ADUNIT', bidder: 'malltv', bidderCode: 'MALLTV', requestId: 'a1b2c3d4', timeToRespond: 72, cpm: 0.1, currency: 'EUR', originalCpm: 0.1, originalCurrency: 'EUR', ad: '<html>fake ad1</html>' }, ] const result = parseAdUnitCode(receivedBids[0]) expect(result).to.equal('adunit') }) }) describe('#getCachedAuction()', function() { const existing = {timeoutBids: [{}]} malltvAnalyticsAdapter.cachedAuctions['test_auction_id'] = existing it('should get the existing cached object if it exists', function() { const result = malltvAnalyticsAdapter.getCachedAuction('test_auction_id') expect(result).to.equal(existing) }) it('should create a new object and store it in the cache on cache miss', function() { const result = malltvAnalyticsAdapter.getCachedAuction('no_such_id') expect(result).to.deep.include({ timeoutBids: [], }) }) }) describe('when formatting JSON payload sent to backend', function() { const receivedBids = [ { auctionId: auctionId, adUnitCode: 'adunit_1', bidder: 'malltv', bidderCode: 'malltv', requestId: 'a1b2c3d4', timeToRespond: 72, cpm: 0.1, currency: 'EUR', originalCpm: 0.1, originalCurrency: 'EUR', ad: '<html>fake ad1</html>', vastUrl: null }, { auctionId: auctionId, adUnitCode: 'adunit_1', bidder: 'gjirafa', bidderCode: 'gjirafa', requestId: 'b2c3d4e5', timeToRespond: 100, cpm: 0.08, currency: 'EUR', originalCpm: 0.08, originalCurrency: 'EUR', ad: '<html>fake ad2</html>', vastUrl: null }, { auctionId: auctionId, adUnitCode: 'adunit_2', bidder: 'malltv', bidderCode: 'malltv', requestId: 'c3d4e5f6', timeToRespond: 120, cpm: 0.09, currency: 'EUR', originalCpm: 0.09, originalCurrency: 'EUR', ad: '<html>fake ad3</html>', vastUrl: null }, ] const highestCpmBids = [ { auctionId: auctionId, adUnitCode: 'adunit_1', bidder: 'malltv', bidderCode: 'malltv', // No requestId timeToRespond: 72, cpm: 0.1, currency: 'EUR', originalCpm: 0.1, originalCurrency: 'EUR', ad: '<html>fake ad1</html>', vastUrl: null } ] const noBids = [ { auctionId: auctionId, adUnitCode: 'adunit_2', bidder: 'malltv', bidderCode: 'malltv', bidId: 'a1b2c3d4', } ] const timeoutBids = [ { auctionId: auctionId, adUnitCode: 'adunit_2', bidder: 'gjirafa', bidderCode: 'gjirafa', bidId: '00123d4c', } ] const withoutOriginalCpmBids = [ { auctionId: auctionId, adUnitCode: 'adunit_2', bidder: 'malltv', bidderCode: 'malltv', requestId: 'c3d4e5f6', timeToRespond: 120, cpm: 0.29, currency: 'EUR', originalCpm: '', originalCurrency: 'EUR', ad: '<html>fake ad3</html>' }, ] const withoutOriginalCurrencyBids = [ { auctionId: auctionId, adUnitCode: 'adunit_2', bidder: 'malltv', bidderCode: 'malltv', requestId: 'c3d4e5f6', timeToRespond: 120, cpm: 0.09, currency: 'EUR', originalCpm: 0.09, originalCurrency: '', ad: '<html>fake ad3</html>' }, ] function assertHavingRequiredMessageFields(message) { expect(message).to.include({ analyticsVersion: ANALYTICS_VERSION, auctionId: auctionId, propertyId: propertyId, prebidVersion: '$prebid.version$', }) } describe('#createCommonMessage', function() { it('should correctly serialize some common fields', function() { const message = malltvAnalyticsAdapter.createCommonMessage(auctionId) assertHavingRequiredMessageFields(message) }) }) describe('#serializeBidResponse', function() { it('should handle BID properly and serialize bid price related fields', function() { const result = malltvAnalyticsAdapter.serializeBidResponse(receivedBids[0], BIDDER_STATUS.BID) expect(result).to.include({ prebidWon: false, isTimeout: false, status: BIDDER_STATUS.BID, time: 72, cpm: 0.1, currency: 'EUR', originalCpm: 0.1, originalCurrency: 'EUR', cpmEur: 0.1, }) }) it('should handle NO_BID properly and set status to noBid', function() { const result = malltvAnalyticsAdapter.serializeBidResponse(noBids[0], BIDDER_STATUS.NO_BID) expect(result).to.include({ prebidWon: false, isTimeout: false, status: BIDDER_STATUS.NO_BID, }) }) it('should handle BID_WON properly and serialize bid price related fields', function() { const result = malltvAnalyticsAdapter.serializeBidResponse(receivedBids[0], BIDDER_STATUS.BID_WON) expect(result).to.include({ prebidWon: true, isTimeout: false, status: BIDDER_STATUS.BID_WON, time: 72, cpm: 0.1, currency: 'EUR', originalCpm: 0.1, originalCurrency: 'EUR', cpmEur: 0.1, }) }) it('should handle TIMEOUT properly and set status to timeout and isTimeout to true', function() { const result = malltvAnalyticsAdapter.serializeBidResponse(noBids[0], BIDDER_STATUS.TIMEOUT) expect(result).to.include({ prebidWon: false, isTimeout: true, status: BIDDER_STATUS.TIMEOUT, }) }) it('should handle BID_WON properly and fill originalCpm field with cpm in missing originalCpm case', function() { const result = malltvAnalyticsAdapter.serializeBidResponse(withoutOriginalCpmBids[0], BIDDER_STATUS.BID_WON) expect(result).to.include({ prebidWon: true, isTimeout: false, status: BIDDER_STATUS.BID_WON, time: 120, cpm: 0.29, currency: 'EUR', originalCpm: 0.29, originalCurrency: 'EUR', cpmEur: 0.29, }) }) it('should handle BID_WON properly and fill originalCurrency field with currency in missing originalCurrency case', function() { const result = malltvAnalyticsAdapter.serializeBidResponse(withoutOriginalCurrencyBids[0], BIDDER_STATUS.BID_WON) expect(result).to.include({ prebidWon: true, isTimeout: false, status: BIDDER_STATUS.BID_WON, time: 120, cpm: 0.09, currency: 'EUR', originalCpm: 0.09, originalCurrency: 'EUR', cpmEur: 0.09, }) }) }) describe('#addBidResponseToMessage()', function() { it('should add a bid response in the output message, grouped by adunit_id and bidder', function() { const message = { adUnits: {} } malltvAnalyticsAdapter.addBidResponseToMessage(message, noBids[0], BIDDER_STATUS.NO_BID) expect(message.adUnits).to.deep.include({ 'adunit_2': { 'malltv': { prebidWon: false, isTimeout: false, status: BIDDER_STATUS.NO_BID, } } }) }) }) describe('#createBidMessage()', function() { it('should format auction message sent to the backend', function() { const args = { auctionId: auctionId, timestamp: 1234567890, timeout: 3000, auctionEnd: 1234567990, adUnitCodes: ['adunit_1', 'adunit_2'], bidsReceived: receivedBids, noBids: noBids } const result = malltvAnalyticsAdapter.createBidMessage(args, highestCpmBids, timeoutBids) assertHavingRequiredMessageFields(result) expect(result).to.deep.include({ auctionElapsed: 100, timeout: 3000, adUnits: { 'adunit_1': { 'malltv': { prebidWon: true, isTimeout: false, status: BIDDER_STATUS.BID, time: 72, cpm: 0.1, currency: 'EUR', originalCpm: 0.1, originalCurrency: 'EUR', cpmEur: 0.1, vastUrl: null }, 'gjirafa': { prebidWon: false, isTimeout: false, status: BIDDER_STATUS.BID, time: 100, cpm: 0.08, currency: 'EUR', originalCpm: 0.08, originalCurrency: 'EUR', cpmEur: 0.08, vastUrl: null } }, 'adunit_2': { // this bid result exists in both bid and noBid arrays and should be treated as bid 'malltv': { prebidWon: false, isTimeout: false, time: 120, cpm: 0.09, currency: 'EUR', originalCpm: 0.09, originalCurrency: 'EUR', cpmEur: 0.09, status: BIDDER_STATUS.BID, vastUrl: null }, 'gjirafa': { prebidWon: false, isTimeout: true, status: BIDDER_STATUS.TIMEOUT, } } } }) }) }) describe('#handleBidTimeout()', function() { it('should cached the timeout bid as BID_TIMEOUT event was triggered', function() { malltvAnalyticsAdapter.cachedAuctions['test_timeout_auction_id'] = { 'timeoutBids': [] } const args = [{ auctionId: 'test_timeout_auction_id', timestamp: 1234567890, timeout: 3000, auctionEnd: 1234567990, bidsReceived: receivedBids, noBids: noBids }] malltvAnalyticsAdapter.handleBidTimeout(args) const result = malltvAnalyticsAdapter.getCachedAuction('test_timeout_auction_id') expect(result).to.deep.include({ timeoutBids: [{ auctionId: 'test_timeout_auction_id', timestamp: 1234567890, timeout: 3000, auctionEnd: 1234567990, bidsReceived: receivedBids, noBids: noBids }] }) }) }) }) }) describe('Malltv Analytics Adapter track handler ', function () { const configOptions = { propertyId } beforeEach(function () { sinon.stub(events, 'getEvents').returns([]) malltvAnalyticsAdapter.enableAnalytics({ provider: 'malltvAnalytics', options: configOptions }) }) afterEach(function () { malltvAnalyticsAdapter.disableAnalytics() events.getEvents.restore() }) it('should call handleBidTimeout as BID_TIMEOUT trigger event', function() { sinon.spy(malltvAnalyticsAdapter, 'handleBidTimeout') events.emit(constants.EVENTS.BID_TIMEOUT, {}) sinon.assert.callCount(malltvAnalyticsAdapter.handleBidTimeout, 1) malltvAnalyticsAdapter.handleBidTimeout.restore() }) it('should call handleAuctionEnd as AUCTION_END trigger event', function() { sinon.spy(malltvAnalyticsAdapter, 'handleAuctionEnd') events.emit(constants.EVENTS.AUCTION_END, {}) sinon.assert.callCount(malltvAnalyticsAdapter.handleAuctionEnd, 1) malltvAnalyticsAdapter.handleAuctionEnd.restore() }) }) describe('enableAnalytics and config parser', function () { const configOptions = { propertyId, server } beforeEach(function () { sinon.stub(events, 'getEvents').returns([]) malltvAnalyticsAdapter.enableAnalytics({ provider: 'malltvAnalytics', options: configOptions }) }) afterEach(function () { malltvAnalyticsAdapter.disableAnalytics() events.getEvents.restore() }) it('should parse config correctly with optional values', function () { const { options, propertyId, server } = malltvAnalyticsAdapter.getAnalyticsOptions() expect(options).to.deep.equal(configOptions) expect(propertyId).to.equal(configOptions.propertyId) expect(server).to.equal(configOptions.server) }) it('should not enable Analytics when propertyId is missing', function() { const configOptions = { options: { } } const isConfigValid = malltvAnalyticsAdapter.initConfig(configOptions) expect(isConfigValid).to.equal(false) }) it('should use DEFAULT_SERVER when server is missing', function () { const configOptions = { options: { propertyId } } malltvAnalyticsAdapter.initConfig(configOptions) expect(malltvAnalyticsAdapter.getAnalyticsOptions().server).to.equal(DEFAULT_SERVER) }) }) })