From 429c50db8fe5733636467ede335a73faa2590887 Mon Sep 17 00:00:00 2001 From: Marian Rusnak Date: Mon, 10 Oct 2016 18:53:26 +0100 Subject: [PATCH 1/6] Refactoring of AOL analytics --- CHANGELOG | 5 + src/adapters/analytics/aol.js | 362 +++++++++++++++++----------------- 2 files changed, 188 insertions(+), 179 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d85465448a8..0488f608b60 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +AOL Prebid 1.3.2 +---------------- +Refactoring of AOL analytics. + + AOL Prebid 1.3.1 ---------------- Fixed reporting of timed out bids in AOL analytics. diff --git a/src/adapters/analytics/aol.js b/src/adapters/analytics/aol.js index dae4f747f61..fa8e6be35c1 100644 --- a/src/adapters/analytics/aol.js +++ b/src/adapters/analytics/aol.js @@ -28,201 +28,205 @@ const EVENTS = { WIN: 2 }; -let adUnits = {}; - let baseSchemaTemplate = template`${'protocol'}://${'host'}/hbevent/${'tagversion'}/${'network'}/${'placement'}/${'site'}/${'eventid'}/hbeventts=${'hbeventts'};cors=yes`; let auctionSchemaTemplate = template`;pubadid=${'pubadid'};hbauctionid=${'hbauctionid'};hbwinner=${'hbwinner'};hbprice=${'hbprice'}${'hbcur'}${'pubapi'}`; let winSchemaTemplate = template`;hbauctioneventts=${'hbauctioneventts'};pubadid=${'pubadid'};hbauctionid=${'hbauctionid'};hbwinner=${'hbwinner'};pubcpm=${'pubcpm'}`; let bidderSchemaTemplate = template`;hbbidder=${'hbbidder'};hbbid=${'hbbid'};hbstatus=${'hbstatus'};hbtime=${'hbtime'}`; export default utils.extend(adapter({ - url: '', - analyticsType - }), { + url: '', + analyticsType +}), { - enableAnalytics({ - options = { - server: null // Internal use only. Use 'region' config option for AOL adapter. + enableAnalytics({ + options = { + server: null // Internal use only. Use 'region' config option for AOL adapter. + } + }) { + this.server = options ? options.server : null; + this.adUnits = {}; + + //first send all events fired before enableAnalytics called + events.getEvents().forEach(event => { + if (!event) { + return; } - }) { - this.server = options ? options.server : null; - - //first send all events fired before enableAnalytics called - events.getEvents().forEach(event => { - if (!event) { - return; - } - this.enqueue(event); - }); - - events.on(AUCTION_END, args => this.enqueue({ eventType: AUCTION_END, args })); - events.on(BID_WON, args => this.enqueue({ eventType: BID_WON, args })); - - this.enableAnalytics = function _enable() { - return utils.logMessage( - `AOL analytics adapter already enabled, unnecessary call to 'enableAnalytics()'.` - ); - }; - }, - - //override AnalyticsAdapter functions by supplying custom methods - track({ eventType, args }) { - switch (eventType) { - case AUCTION_END: - let adUnitsConf = $$PREBID_GLOBAL$$.adUnits; - let bidsReceived = $$PREBID_GLOBAL$$._bidsReceived; - let bidsRequested = $$PREBID_GLOBAL$$._bidsRequested; - - let bidsReceivedPerBidderPerAdUnit = bidsReceived - .reduce((bidsReceivedPerBidderPerAdUnit, bid) => { - let bidsPerBidder = bidsReceivedPerBidderPerAdUnit[bid.bidder] || {}; - let bidsPerBidderPerAdUnit = bidsPerBidder[bid.adUnitCode] || []; - bidsPerBidderPerAdUnit.push(bid); - bidsPerBidder[bid.adUnitCode] = bidsPerBidderPerAdUnit; - bidsReceivedPerBidderPerAdUnit[bid.bidder] = bidsPerBidder; - return bidsReceivedPerBidderPerAdUnit; - }, {}); - - let bidsToReport = bidsRequested - .map(bidderRequest => bidderRequest.bids - .map(bid => { - let receivedBidsForBidder = bidsReceivedPerBidderPerAdUnit[bid.bidder] || {}; - let receivedBidsForBidderForAdUnit = receivedBidsForBidder[bid.placementCode] || []; - // check received bids, or mark bid as timed out if no more received bids - if (receivedBidsForBidderForAdUnit.length > 0) { - return receivedBidsForBidderForAdUnit.shift(); // remove to count timed out bids - } else { - return { - adUnitCode: bid.placementCode, - bidder: bid.bidder, - cpm: 0, - getStatusCode: () => 3, // ERROR_TIMEOUT - timeToRespond: new Date().getTime() - bidderRequest.start - }; - } - }) - ) - .reduce((a, b) => a.concat(b), []); - - bidsToReport.forEach(bid => { - const currentAdUnitCode = bid.adUnitCode; - let adUnit = adUnits[currentAdUnitCode]; - if (!adUnit) { - adUnit = initAdUnit(currentAdUnitCode); - adUnit = addAolParams(adUnit, adUnitsConf, bidsReceived); - adUnits[currentAdUnitCode] = adUnit; - } - adUnit.winner = (adUnit.winner.cpm < bid.cpm) ? bid : adUnit.winner; - adUnit.bids.push(Object.assign(bid)); - }); - - for (let code in adUnits) { - if (adUnits.hasOwnProperty(code)) { - let adUnit = adUnits[code]; - if (adUnit.aolParams) { - let url = this.buildEndpoint(EVENTS.AUCTION, adUnit); - this.reportEvent(url); - } - } - } - - break; - - case BID_WON: - let bidWon = args; + this.enqueue(event); + }); - for (let code in adUnits) { - if (adUnits.hasOwnProperty(code) && bidWon.adUnitCode === code) { - let url = this.buildEndpoint(EVENTS.WIN, adUnits[code]); - this.reportEvent(url); - } + events.on(AUCTION_END, args => this.enqueue({ eventType: AUCTION_END, args })); + events.on(BID_WON, args => this.enqueue({ eventType: BID_WON, args })); + + this.enableAnalytics = function _enable() { + return utils.logMessage( + `AOL analytics adapter already enabled, unnecessary call to 'enableAnalytics()'.` + ); + }; + }, + + //override AnalyticsAdapter functions by supplying custom methods + track({ eventType, args }) { + switch (eventType) { + case AUCTION_END: + this.reportAuctionEvent({ + adUnitsConfig: $$PREBID_GLOBAL$$.adUnits, + bidsReceived: $$PREBID_GLOBAL$$._bidsReceived, + bidsRequested: $$PREBID_GLOBAL$$._bidsRequested + }); + break; + + case BID_WON: + this.reportWinEvent({ winningBid: args }); + break; + } + }, + + reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }) { + let bidsReceivedPerBidderPerAdUnit = bidsReceived + .reduce((bidsReceivedPerBidderPerAdUnit, bid) => { + let bidsPerBidder = bidsReceivedPerBidderPerAdUnit[bid.bidder] || {}; + let bidsPerBidderPerAdUnit = bidsPerBidder[bid.adUnitCode] || []; + bidsPerBidderPerAdUnit.push(bid); + bidsPerBidder[bid.adUnitCode] = bidsPerBidderPerAdUnit; + bidsReceivedPerBidderPerAdUnit[bid.bidder] = bidsPerBidder; + return bidsReceivedPerBidderPerAdUnit; + }, {}); + + let bidsToReport = bidsRequested + .map(bidderRequest => bidderRequest.bids + .map(bid => { + let receivedBidsForBidder = bidsReceivedPerBidderPerAdUnit[bid.bidder] || {}; + let receivedBidsForBidderForAdUnit = receivedBidsForBidder[bid.placementCode] || []; + // check received bids, or mark bid as timed out if no more received bids + if (receivedBidsForBidderForAdUnit.length > 0) { + return receivedBidsForBidderForAdUnit.shift(); // remove to count timed out bids + } else { + return { + adUnitCode: bid.placementCode, + bidder: bid.bidder, + cpm: 0, + getStatusCode: () => 3, // ERROR_TIMEOUT + timeToRespond: new Date().getTime() - bidderRequest.start + }; } - - break; + }) + ) + .reduce(utils.flatten, []); + + let adUnits = this.adUnits; + + bidsToReport.forEach(bid => { + const currentAdUnitCode = bid.adUnitCode; + let adUnit = adUnits[currentAdUnitCode]; + if (!adUnit) { + adUnit = initAdUnit(currentAdUnitCode); + adUnit = addAolParams(adUnit, adUnitsConfig, bidsReceived); + adUnits[currentAdUnitCode] = adUnit; } + adUnit.winner = (adUnit.winner.cpm < bid.cpm) ? bid : adUnit.winner; + adUnit.bids.push(Object.assign({}, bid)); + }); - }, - - reportEvent(url) { - ajax(url, null, null, { withCredentials: true }); - }, - - getBaseSchema(eventId, adUnit) { - let aolParams = adUnit.aolParams; - return { - protocol: (document.location.protocol === 'https:') ? 'https' : 'http', - host: this.server || serverMap[aolParams.region] || serverMap.us, - tagversion: '3.0', - network: aolParams.network || '', - placement: aolParams.placement, - site: aolParams.pageid || 0, - eventid: eventId, - hbeventts: Math.floor(Date.now() / 1000) // Unix timestamp in seconds. - }; - }, - - getAuctionSchema(adUnit) { - let aolParams = adUnit.aolParams; - return { - pubadid: adUnit.code, - hbauctionid: generateAuctionId(aolParams.placement), - hbwinner: adUnit.winner.bidder ? getBidderId(adUnit.winner.bidder) : 0, - hbprice: adUnit.winner.cpm || 0, - hbcur: aolParams.currencyCode ? `;hbcur=${aolParams.currencyCode}` : '', - pubapi: aolParams.pubapiId ? `;pubapi=${aolParams.pubapiId}` : '' - }; - }, - - getWinSchema(adUnit) { - let auctionParams = adUnit.auctionParams; - return { - pubadid: adUnit.code, - hbauctioneventts: auctionParams.hbauctioneventts, - hbauctionid: auctionParams.hbauctionid, - hbwinner: getBidderId(adUnit.winner.bidder), - pubcpm: adUnit.winner.cpm - }; - }, - - getBidderSchema(bid) { - return { - hbbidder: getBidderId(bid.bidder), - hbbid: bid.cpm || 0, - hbstatus: getStatusCode(bid), - hbtime: bid.timeToRespond || '' - }; - }, - - buildEndpoint(event, adUnit) { - let baseSchema, url; - - switch (event) { - - case EVENTS.AUCTION: - - baseSchema = this.getBaseSchema(EVENTS.AUCTION, adUnit); - let auctionSchema = this.getAuctionSchema(adUnit); - adUnit.auctionParams = { - hbauctioneventts: baseSchema.hbeventts, - hbauctionid: auctionSchema.hbauctionid - }; - url = baseSchemaTemplate(baseSchema) + auctionSchemaTemplate(auctionSchema); - adUnit.bids.forEach(bid => { - url = url + bidderSchemaTemplate(this.getBidderSchema(bid)); - }); - return url; - - case EVENTS.WIN: - - baseSchema = this.getBaseSchema(EVENTS.WIN, adUnit); - let winSchema = this.getWinSchema(adUnit); - url = baseSchemaTemplate(baseSchema) + winSchemaTemplate(winSchema); - return url; + for (let code in adUnits) { + if (adUnits.hasOwnProperty(code)) { + let adUnit = adUnits[code]; + if (adUnit.aolParams) { + this.reportEvent(EVENTS.AUCTION, adUnit); + } + } + } + }, + reportWinEvent({ winningBid }) { + let adUnits = this.adUnits; + for (let code in adUnits) { + if (adUnits.hasOwnProperty(code) && winningBid.adUnitCode === code) { + this.reportEvent(EVENTS.WIN, adUnits[code]); } } + }, + + reportEvent(event, adUnit) { + let url = this.buildEventUrl(event, adUnit); + ajax(url, null, null, { withCredentials: true }); + }, + + getBaseSchema(eventId, adUnit) { + let aolParams = adUnit.aolParams; + return { + protocol: (document.location.protocol === 'https:') ? 'https' : 'http', + host: this.server || serverMap[aolParams.region] || serverMap.us, + tagversion: '3.0', + network: aolParams.network || '', + placement: aolParams.placement, + site: aolParams.pageid || 0, + eventid: eventId, + hbeventts: Math.floor(Date.now() / 1000) // Unix timestamp in seconds. + }; + }, + + getAuctionSchema(adUnit) { + let aolParams = adUnit.aolParams; + return { + pubadid: adUnit.code, + hbauctionid: generateAuctionId(aolParams.placement), + hbwinner: adUnit.winner.bidder ? getBidderId(adUnit.winner.bidder) : 0, + hbprice: adUnit.winner.cpm || 0, + hbcur: aolParams.currencyCode ? `;hbcur=${aolParams.currencyCode}` : '', + pubapi: aolParams.pubapiId ? `;pubapi=${aolParams.pubapiId}` : '' + }; + }, + + getWinSchema(adUnit) { + let auctionParams = adUnit.auctionParams; + return { + pubadid: adUnit.code, + hbauctioneventts: auctionParams.hbauctioneventts, + hbauctionid: auctionParams.hbauctionid, + hbwinner: getBidderId(adUnit.winner.bidder), + pubcpm: adUnit.winner.cpm + }; + }, + + getBidderSchema(bid) { + return { + hbbidder: getBidderId(bid.bidder), + hbbid: bid.cpm || 0, + hbstatus: getStatusCode(bid), + hbtime: bid.timeToRespond || '' + }; + }, + + buildEventUrl(event, adUnit) { + let baseSchema, url; + + switch (event) { + + case EVENTS.AUCTION: + + baseSchema = this.getBaseSchema(EVENTS.AUCTION, adUnit); + let auctionSchema = this.getAuctionSchema(adUnit); + adUnit.auctionParams = { + hbauctioneventts: baseSchema.hbeventts, + hbauctionid: auctionSchema.hbauctionid + }; + url = baseSchemaTemplate(baseSchema) + auctionSchemaTemplate(auctionSchema); + adUnit.bids.forEach(bid => { + url = url + bidderSchemaTemplate(this.getBidderSchema(bid)); + }); + return url; + + case EVENTS.WIN: + + baseSchema = this.getBaseSchema(EVENTS.WIN, adUnit); + let winSchema = this.getWinSchema(adUnit); + url = baseSchemaTemplate(baseSchema) + winSchemaTemplate(winSchema); + return url; - }); + } + } + +}); function template(strings, ...keys) { return function(...values) { From 748871c045b915f3044c4011f5f6b3ad84a92be7 Mon Sep 17 00:00:00 2001 From: Marian Rusnak Date: Mon, 10 Oct 2016 18:56:28 +0100 Subject: [PATCH 2/6] Added unit tests for AOL analytics - fixed reporting of pageId parameter --- CHANGELOG | 1 + src/adapters/analytics/aol.js | 2 +- test/fixtures/fixturesAnalytics.js | 440 ++----- test/spec/unit/adapters/analytics/aol_spec.js | 1030 ++++++++++++++++- 4 files changed, 1091 insertions(+), 382 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0488f608b60..4d061457e00 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ AOL Prebid 1.3.2 ---------------- Refactoring of AOL analytics. +Fixed reporting of pageId parameter in AOL analytics. AOL Prebid 1.3.1 diff --git a/src/adapters/analytics/aol.js b/src/adapters/analytics/aol.js index fa8e6be35c1..3d16daea60c 100644 --- a/src/adapters/analytics/aol.js +++ b/src/adapters/analytics/aol.js @@ -159,7 +159,7 @@ export default utils.extend(adapter({ tagversion: '3.0', network: aolParams.network || '', placement: aolParams.placement, - site: aolParams.pageid || 0, + site: aolParams.pageId || 0, eventid: eventId, hbeventts: Math.floor(Date.now() / 1000) // Unix timestamp in seconds. }; diff --git a/test/fixtures/fixturesAnalytics.js b/test/fixtures/fixturesAnalytics.js index 1f2aaa82554..4ca7ad75a67 100644 --- a/test/fixtures/fixturesAnalytics.js +++ b/test/fixtures/fixturesAnalytics.js @@ -1,327 +1,125 @@ -// jscs:disable +// Copyright 2016 AOL Platforms. -export function getBidResponses() { - return [ - { - "bidderCode": "aol", - "width": 0, - "height": 0, - "statusMessage": "Bid available", - "adId": "222bb26f9e8be", - "cpm": 0.112256, - "ad": "", - "responseTimestamp": 1462919239337, - "requestTimestamp": 1462919238936, - "bidder": "aol", - "adUnitCode": "/19968336/header-bid-tag-0", - "timeToRespond": 401, - "pbLg": "0.00", - "pbMg": "0.10", - "pbHg": "0.11", - "pbAg": "0.10", - "size": "0x0", - "adserverTargeting": { - "hb_bidder": "aol", - "hb_adid": "222bb26f9e8be", - "hb_pb": "10.00", - "hb_size": "0x0", - "foobar": "0x0" - } - }, - { - "bidderCode": "triplelift", - "width": 0, - "height": 0, - "statusMessage": "Bid available", - "adId": "222bb26f9e8bd", - "cpm": 0.112256, - "ad": "", - "responseTimestamp": 1462919239337, - "requestTimestamp": 1462919238936, - "bidder": "triplelift", - "adUnitCode": "/19968336/header-bid-tag-0", - "timeToRespond": 401, - "pbLg": "0.00", - "pbMg": "0.10", - "pbHg": "0.11", - "pbAg": "0.10", - "size": "0x0", - "adserverTargeting": { - "hb_bidder": "triplelift", - "hb_adid": "222bb26f9e8bd", - "hb_pb": "10.00", - "hb_size": "0x0", - "foobar": "0x0" - } - }, - { - "bidderCode": "appnexus", - "width": 300, - "height": 250, - "statusMessage": "Bid available", - "adId": "233bcbee889d46d", - "creative_id": 29681110, - "cpm": 10, - "adUrl": "http://lax1-ib.adnxs.com/ab?e=wqT_3QL8BKh8AgAAAwDWAAUBCMjAybkFEMLLiJWTu9PsVxjL84KE1tzG-kkgASotCQAAAQII4D8RAQcQAADgPxkJCQjwPyEJCQjgPykRCaAwuvekAji-B0C-B0gCUNbLkw5YweAnYABokUB4190DgAEBigEDVVNEkgUG8FKYAawCoAH6AagBAbABALgBAcABA8gBANABANgBAOABAPABAIoCOnVmKCdhJywgNDk0NDcyLCAxNDYyOTE5MjQwKTt1ZigncicsIDI5NjgxMTEwLDIeAPBskgLZASFmU21rZ0FpNjBJY0VFTmJMa3c0WUFDREI0Q2N3QURnQVFBUkl2Z2RRdXZla0FsZ0FZSk1IYUFCd0EzZ0RnQUVEaUFFRGtBRUJtQUVCb0FFQnFBRURzQUVBdVFFQUFBQUFBQURnUDhFQgkMTEFBNERfSkFRMkxMcEVUMU93XzJRFSggd1AtQUJBUFVCBSxASmdDaW9EVTJnV2dBZ0MxQWcBFgRDOQkIqERBQWdQSUFnUFFBZ1BZQWdQZ0FnRG9BZ0Q0QWdDQUF3RS6aAiUhV1FrbmI63AAcd2VBbklBUW8JXPCVVS7YAugH4ALH0wHqAh9odHRwOi8vcHJlYmlkLm9yZzo5OTk5L2dwdC5odG1sgAMAiAMBkAMAmAMFoAMBqgMAsAMAuAMAwAOsAsgDANgDAOADAOgDAPgDA4AEAJIEBC9qcHSYBACiBAoxMC4xLjEzLjM3qAQAsgQICAAQABgAIAC4BADABADIBADSBAoxMC4wLjg1Ljkx&s=1bf15e8cdc7c0c8c119614c6386ab1496560da39&referrer=http%3A%2F%2Fprebid.org%3A9999%2Fgpt.html", - "responseTimestamp": 1462919239340, - "requestTimestamp": 1462919238919, - "bidder": "appnexus", - "adUnitCode": "/19968336/header-bid-tag-0", - "timeToRespond": 421, - "pbLg": "5.00", - "pbMg": "10.00", - "pbHg": "10.00", - "pbAg": "10.00", - "size": "300x250", - "alwaysUseBid": true, - "adserverTargeting": { - "hb_bidder": "appnexus", - "hb_adid": "233bcbee889d46d", - "hb_pb": "10.00", - "hb_size": "300x250", - "foobar": "300x250" - } - }, - { - "bidderCode": "appnexus", - "width": 728, - "height": 90, - "statusMessage": "Bid available", - "adId": "24bd938435ec3fc", - "creative_id": 33989846, - "cpm": 10, - "adUrl": "http://lax1-ib.adnxs.com/ab?e=wqT_3QLyBKhyAgAAAwDWAAUBCMjAybkFEOOryfjI7rGNWhjL84KE1tzG-kkgASotCQAAAQII4D8RAQcQAADgPxkJCQjwPyEJCQjgPykRCaAwuvekAji-B0C-B0gCUNbJmhBYweAnYABokUB4mt0CgAEBigEDVVNEkgUG8ECYAdgFoAFaqAEBsAEAuAEBwAEDyAEA0AEA2AEA4AEA8AEAigI6dWYoJ2EnLCA0OTQ0NzIsIDE0NjI5MTkyNDApOwEcLHInLCAzMzk4OTg0NjYeAPBvkgLNASFwU2Y1YUFpNjBJY0VFTmJKbWhBWUFDREI0Q2N3QURnQVFBUkl2Z2RRdXZla0FsZ0FZSk1IYUFCd3lnNTRDb0FCcGh5SUFRcVFBUUdZQVFHZ0FRR29BUU93QVFDNUFRQUFBQUFBQU9BX3dRRQkMSEFEZ1A4a0JJNTJDbGs5VjB6X1oVKCRQQV80QUVBOVFFBSw8bUFLS2dNQ0NENkFDQUxVQwUVBEwwCQh0T0FDQU9nQ0FQZ0NBSUFEQVEuLpoCJSFfZ2lqYXdpMtAA8KZ3ZUFuSUFRb2lvREFnZzgu2ALoB-ACx9MB6gIfaHR0cDovL3ByZWJpZC5vcmc6OTk5OS9ncHQuaHRtbIADAIgDAZADAJgDBaADAaoDALADALgDAMADrALIAwDYAwDgAwDoAwD4AwOABACSBAQvanB0mAQAogQKMTAuMS4xMy4zN6gEi-wJsgQICAAQABgAIAC4BADABADIBADSBAsxMC4wLjgwLjI0MA..&s=1f584d32c2d7ae3ce3662cfac7ca24e710bc7fd0&referrer=http%3A%2F%2Fprebid.org%3A9999%2Fgpt.html", - "responseTimestamp": 1462919239342, - "requestTimestamp": 1462919238919, - "bidder": "appnexus", - "adUnitCode": "/19968336/header-bid-tag1", - "timeToRespond": 423, - "pbLg": "5.00", - "pbMg": "10.00", - "pbHg": "10.00", - "pbAg": "10.00", - "size": "728x90", - "alwaysUseBid": true, - "adserverTargeting": { - "hb_bidder": "appnexus", - "hb_adid": "24bd938435ec3fc", - "hb_pb": "10.00", - "hb_size": "728x90", - "foobar": "728x90" - } - }, - { - "bidderCode": "pagescience", - "width": 300, - "height": 250, - "statusMessage": "Bid available", - "adId": "25bedd4813632d7", - "creative_id": 29681110, - "cpm": 0.5, - "adUrl": "http://lax1-ib.adnxs.com/ab?e=wqT_3QLzBKhzAgAAAwDWAAUBCMjAybkFEM7fioW41qjIQRjL84KE1tzG-kkgASotCQAAAQII4D8RAQcQAADgPxkJCQjwPyEJCQjgPykRCaAwuvekAji-B0C-B0gCUNbLkw5YweAnYABokUB4yIsEgAEBigEDVVNEkgUG8FKYAawCoAH6AagBAbABALgBAcABA8gBANABANgBAOABAPABAIoCOnVmKCdhJywgNDk0NDcyLCAxNDYyOTE5MjQwKTt1ZigncicsIDI5NjgxMTEwLDIeAPBvkgLNASFfeWVLYndpNjBJY0VFTmJMa3c0WUFDREI0Q2N3QURnQVFBUkl2Z2RRdXZla0FsZ0FZSk1IYUFCdzNBMTRDb0FCcGh5SUFRcVFBUUdZQVFHZ0FRR29BUU93QVFDNUFRQUFBQUFBQU9BX3dRRQkMSEFEZ1A4a0JSR3RLaGp1UTFEX1oVKCRQQV80QUVBOVFFBSw8bUFLS2dQVFNES0FDQUxVQwUVBEwwCQhwT0FDQU9nQ0FQZ0NBSUFEQVEuLpoCJSFlQWwtYkE20ADwpndlQW5JQVFvaW9EMDBndy7YAugH4ALH0wHqAh9odHRwOi8vcHJlYmlkLm9yZzo5OTk5L2dwdC5odG1sgAMAiAMBkAMAmAMFoAMBqgMAsAMAuAMAwAOsAsgDANgDAOADAOgDAPgDA4AEAJIEBC9qcHSYBACiBAoxMC4xLjEzLjM3qASL7AmyBAgIABAAGAAgALgEAMAEAMgEANIECzEwLjAuOTMuMjAy&s=1fd8d5650fa1fb8d918a2f403d6a1f97c10d7ec2&referrer=http%3A%2F%2Fprebid.org%3A9999%2Fgpt.html", - "responseTimestamp": 1462919239343, - "requestTimestamp": 1462919238943, - "bidder": "pagescience", - "adUnitCode": "/19968336/header-bid-tag-0", - "timeToRespond": 400, - "pbLg": "0.50", - "pbMg": "0.50", - "pbHg": "0.50", - "pbAg": "0.50", - "size": "300x250", - "adserverTargeting": { - "hb_bidder": "pagescience", - "hb_adid": "25bedd4813632d7", - "hb_pb": "10.00", - "hb_size": "300x250", - "foobar": "300x250" - } - }, - { - "bidderCode": "brightcom", - "width": 300, - "height": 250, - "statusMessage": "Bid available", - "adId": "26e0795ab963896", - "cpm": 0.17, - "ad": "", - "responseTimestamp": 1462919239420, - "requestTimestamp": 1462919238937, - "bidder": "brightcom", - "adUnitCode": "/19968336/header-bid-tag-0", - "timeToRespond": 483, - "pbLg": "0.00", - "pbMg": "0.10", - "pbHg": "0.17", - "pbAg": "0.15", - "size": "300x250", - "adserverTargeting": { - "hb_bidder": "brightcom", - "hb_adid": "26e0795ab963896", - "hb_pb": "10.00", - "hb_size": "300x250", - "foobar": "300x250" - } - }, - { - "bidderCode": "brealtime", - "width": 300, - "height": 250, - "statusMessage": "Bid available", - "adId": "275bd666f5a5a5d", - "creative_id": 29681110, - "cpm": 0.5, - "adUrl": "http://lax1-ib.adnxs.com/ab?e=wqT_3QLzBKhzAgAAAwDWAAUBCMjAybkFEIPr4YfMvKLoQBjL84KE1tzG-kkgASotCQAAAQII4D8RAQcQAADgPxkJCQjwPyEJCQjgPykRCaAwuvekAji-B0C-B0gCUNbLkw5YweAnYABokUB4mo8EgAEBigEDVVNEkgUG8FKYAawCoAH6AagBAbABALgBAcABA8gBANABANgBAOABAPABAIoCOnVmKCdhJywgNDk0NDcyLCAxNDYyOTE5MjQwKTt1ZigncicsIDI5NjgxMTEwLDIeAPBvkgLNASFsU2NQWlFpNjBJY0VFTmJMa3c0WUFDREI0Q2N3QURnQVFBUkl2Z2RRdXZla0FsZ0FZSk1IYUFCdzNBMTRDb0FCcGh5SUFRcVFBUUdZQVFHZ0FRR29BUU93QVFDNUFRQUFBQUFBQU9BX3dRRQkMSEFEZ1A4a0JHZmNvazFBejFUX1oVKCRQQV80QUVBOVFFBSw8bUFLS2dOU0NEYUFDQUxVQwUVBEwwCQh0T0FDQU9nQ0FQZ0NBSUFEQVEuLpoCJSFDUWxfYXdpMtAA8KZ3ZUFuSUFRb2lvRFVnZzAu2ALoB-ACx9MB6gIfaHR0cDovL3ByZWJpZC5vcmc6OTk5OS9ncHQuaHRtbIADAIgDAZADAJgDBaADAaoDALADALgDAMADrALIAwDYAwDgAwDoAwD4AwOABACSBAQvanB0mAQAogQKMTAuMS4xMy4zN6gEi-wJsgQICAAQABgAIAC4BADABADIBADSBAsxMC4wLjg1LjIwOA..&s=975cfe6518f064683541240f0d780d93a5f973da&referrer=http%3A%2F%2Fprebid.org%3A9999%2Fgpt.html", - "responseTimestamp": 1462919239486, - "requestTimestamp": 1462919238941, - "bidder": "brealtime", - "adUnitCode": "/19968336/header-bid-tag-0", - "timeToRespond": 545, - "pbLg": "0.50", - "pbMg": "0.50", - "pbHg": "0.50", - "pbAg": "0.50", - "size": "300x250", - "adserverTargeting": { - "hb_bidder": "brealtime", - "hb_adid": "275bd666f5a5a5d", - "hb_pb": "10.00", - "hb_size": "300x250", - "foobar": "300x250" - } - }, - { - "bidderCode": "pubmatic", - "width": "300", - "height": "250", - "statusMessage": "Bid available", - "adId": "28f4039c636b6a7", - "adSlot": "39620189@300x250", - "cpm": 5.9396, - "ad": "\r
", - "dealId": "", - "responseTimestamp": 1462919239544, - "requestTimestamp": 1462919238922, - "bidder": "pubmatic", - "adUnitCode": "/19968336/header-bid-tag-0", - "timeToRespond": 622, - "pbLg": "5.00", - "pbMg": "5.90", - "pbHg": "5.93", - "pbAg": "5.90", - "size": "300x250", - "adserverTargeting": { - "hb_bidder": "pubmatic", - "hb_adid": "28f4039c636b6a7", - "hb_pb": "10.00", - "hb_size": "300x250", - "foobar": "300x250" - } - }, - { - "bidderCode": "rubicon", - "width": 300, - "height": 600, - "statusMessage": "Bid available", - "adId": "29019e2ab586a5a", - "cpm": 2.74, - "ad": "", - "responseTimestamp": 1462919239860, - "requestTimestamp": 1462919238934, - "bidder": "rubicon", - "adUnitCode": "/19968336/header-bid-tag-0", - "timeToRespond": 926, - "pbLg": "2.50", - "pbMg": "2.70", - "pbHg": "2.74", - "pbAg": "2.70", - "size": "300x600", - "adserverTargeting": { - "hb_bidder": "rubicon", - "hb_adid": "29019e2ab586a5a", - "hb_pb": "10.00", - "hb_size": "300x600", - "foobar": "300x600" - } - } - ]; -} +export const DEFAULT_TIMEOUT = 1000; +export const DEFAULT_REQUEST_TIMESTAMP = new Date().getTime(); +export const DEFAULT_RESPONSE_TIMESTAMP = DEFAULT_REQUEST_TIMESTAMP + 500; +export const DEFAULT_REQUEST_ID = '1863e370099524'; +export const DEFAULT_AD_UNIT_CODE = 'header-bid-tag-0'; -export function getRequestedBids() { - return [ - { - "bidderCode": "aol", - "bidderRequestId": "107f5e6e98dcf10", - "requestId": "1863e370099524", - "start": 1462918897477, - "timeout": 1000, - "bids": [ - { - "bidder": "aol", - "params": { - "inventoryCode": "sortable_all_right_sports", - "placement": "23324932", - "network": "5071.1", - "alias": "desktop_articlepage_something_box_300_250", - "server": "adserver.adtech.de" - }, - "placementCode": "/19968336/header-bid-tag-0", - "bidId": "1144e2f0de84364", - "bidderRequestId": "107f5e6e98dcf10", - "requestId": "1863e370099524", - "sizes": [ - [300, 250], - [300, 600] - ] - } - ] +export const BID_CONFIGS = { + AOL1: { + bidder: 'aol', + params: { + placement: 3675026, + network: '9599.1', + pageid: 12345 } - ]; -} - -export function getAdUnits() { - return [ - { - "code": "/19968336/header-bid-tag-0", - "sizes": [ - [ - 728, - 90 - ], - [ - 970, - 90 - ] - ], - "bids": [ - { - "bidder": "aol", - "params": { - "inventoryCode": "sortable_all_right_sports", - "placement": "23324932", - "network": "5071.1", - "alias": "desktop_articlepage_something_box_300_250", - "server": "adserver.adtech.de" - }, - "placementCode": "/19968336/header-bid-tag-0", - "sizes": [ - [ - 300, - 250 - ], - [ - 300, - 600 - ] - ], - "bidId": "1144e2f0de84364", - "bidderRequestId": "107f5e6e98dcf10", - "requestId": "1863e370099524", - "startTime": 1462918897477 - } - ] + }, + AOL2: { + bidder: 'aol', + params: { + placement: 3675027, + network: '9599.1', + pageid: 12345 + } + }, + APPNEXUS1: { + bidder: 'appnexus', + params: { + placementId: 12345, + } + }, + APPNEXUS2: { + bidder: 'appnexus', + params: { + placementId: 56789, + } + }, + APPNEXUS3: { + bidder: 'appnexus', + params: { + placementId: 2345, } - ] -} + }, + PULSEPOINT1: { + bidder: 'pulsepoint', + params: { + placement: 12345 + } + } +}; + +export const DEFAULT_AD_UNIT = { + code: DEFAULT_AD_UNIT_CODE, + sizes: [[300, 250]], + bids: [BID_CONFIGS.AOL1] +}; + +export const BID_SETS = { + AOL: { + bidder: 'aol', + bidderCode: 'aol', + bidderRequestId: '107f5e6e98dcf10', + requestId: DEFAULT_REQUEST_ID, + start: DEFAULT_REQUEST_TIMESTAMP, + timeout: DEFAULT_TIMEOUT, + bids: [Object.assign({}, BID_CONFIGS.AOL1, { + placementCode: DEFAULT_AD_UNIT_CODE, + bidId: '1144e2f0de84364', + bidderRequestId: '107f5e6e98dcf10', + requestId: DEFAULT_REQUEST_ID, + sizes: [[300, 250]] + })] + } +}; + +export const BIDS = { + VALID: { + bidder: 'aol', + bidderCode: 'aol', + adUnitCode: DEFAULT_AD_UNIT_CODE, + getStatusCode: () => 1, + statusMessage: 'Bid available', + width: 300, + height: 250, + adId: '122bb26f9e8be', + ad: '', + requestTimestamp: DEFAULT_REQUEST_TIMESTAMP, + responseTimestamp: DEFAULT_RESPONSE_TIMESTAMP, + timeToRespond: DEFAULT_RESPONSE_TIMESTAMP - DEFAULT_REQUEST_TIMESTAMP, + cpm: 0.10, + pbLg: '0.00', + pbMg: '0.10', + pbHg: '0.11', + pbAg: '0.10', + size: '300x250', + }, + EMPTY: { + bidder: 'aol', + bidderCode: 'aol', + adUnitCode: DEFAULT_AD_UNIT_CODE, + getStatusCode: () => 2, + statusMessage: 'Bid returned empty or error response', + width: 0, + height: 0, + adId: '222bb26f9e8be', + requestTimestamp: DEFAULT_REQUEST_TIMESTAMP, + responseTimestamp: DEFAULT_RESPONSE_TIMESTAMP, + timeToRespond: DEFAULT_RESPONSE_TIMESTAMP - DEFAULT_REQUEST_TIMESTAMP, + cpm: 0, + pbLg: '0', + pbMg: '0', + pbHg: '0', + pbAg: '0', + size: '0x0' + }, + TIMED_OUT: { + bidder: 'aol', + adUnitCode: DEFAULT_AD_UNIT_CODE, + getStatusCode: () => 3, + timeToRespond: 5000, + cpm: 0 + } +}; diff --git a/test/spec/unit/adapters/analytics/aol_spec.js b/test/spec/unit/adapters/analytics/aol_spec.js index 5cfa5317a0e..5db453cefc5 100644 --- a/test/spec/unit/adapters/analytics/aol_spec.js +++ b/test/spec/unit/adapters/analytics/aol_spec.js @@ -1,93 +1,1003 @@ // Copyright 2016 AOL Platforms. -import { assert } from 'chai'; +import { expect } from 'chai'; import events from '../../../../../src/events'; import CONSTANTS from '../../../../../src/constants.json'; -import { getBidResponses, getRequestedBids, getAdUnits } from '../../../../fixtures/fixturesAnalytics'; +import { + DEFAULT_REQUEST_TIMESTAMP, + DEFAULT_REQUEST_ID, + DEFAULT_TIMEOUT, + DEFAULT_AD_UNIT_CODE, + DEFAULT_AD_UNIT, + BID_CONFIGS, + BID_SETS, + BIDS, +} from '../../../../fixtures/fixturesAnalytics'; +const utils = require('../../../../../src/utils'); const aolAnalytics = require('../../../../../src/adapters/analytics/aol').default; + const AUCTION_END = CONSTANTS.EVENTS.AUCTION_END; const BID_WON = CONSTANTS.EVENTS.BID_WON; +const ANALYTICS_EVENTS = { + AUCTION: 1, + WIN: 2 +}; + +describe('AOL analytics adapter', () => { + + afterEach(() => { + aolAnalytics.adUnits = {}; + }); + + function createAdUnit(adUnitConfig) { + return Object.assign({}, DEFAULT_AD_UNIT, adUnitConfig); + } + + function createRequestedBids(adUnits) { + return utils.getBidderCodes(adUnits).map(bidderCode => { + const bidderRequestId = utils.getUniqueIdentifierStr(); + return { + bidder: bidderCode, + bidderCode: bidderCode, + bidderRequestId: bidderRequestId, + requestId: DEFAULT_REQUEST_ID, + start: DEFAULT_REQUEST_TIMESTAMP, + timeout: DEFAULT_TIMEOUT, + bids: adUnits.map(adUnit => adUnit.bids + .filter(bid => bid.bidder === bidderCode) + .map(bid => Object.assign({}, bid, { + placementCode: adUnit.code, + bidId: utils.getUniqueIdentifierStr(), + bidderRequestId: bidderRequestId, + requestId: DEFAULT_REQUEST_ID, + sizes: adUnit.sizes + })) + ) + .reduce(utils.flatten, []) + }; + }); + } + + function getDefaultReceivedBid(status) { + switch (status) { + case 1: + return BIDS.VALID; + case 2: + return BIDS.EMPTY; + case 3: + return BIDS.TIMED_OUT; + default: + return BIDS.VALID; + } + } + + function createReceivedBid(bidResponse) { + const status = bidResponse.status || 1; + const DEFAULT_RECEIVED_BID = getDefaultReceivedBid(status); + return Object.assign({}, DEFAULT_RECEIVED_BID, bidResponse); + } + + aolAnalytics.enableAnalytics({}); + + describe('enableAnalytics', () => { + afterEach(() => { + if (utils.logMessage.restore) { + utils.logMessage.restore(); + } + }); + + it('should just log a message on subsequest calls', () => { + sinon.spy(utils, 'logMessage'); + aolAnalytics.enableAnalytics({}); + expect(utils.logMessage.called).to.be.true; + }); + }); + + describe('track()', () => { + afterEach(() => { + if (aolAnalytics.reportAuctionEvent.restore) { + aolAnalytics.reportAuctionEvent.restore(); + } + if (aolAnalytics.reportWinEvent.restore) { + aolAnalytics.reportWinEvent.restore(); + } + }); + + it('should call reportAuctionEvent() when AUCTION_END event is fired', () => { + sinon.stub(aolAnalytics, 'reportAuctionEvent'); + events.emit(AUCTION_END); + expect(aolAnalytics.reportAuctionEvent.calledOnce).to.be.true; + }); + + it('should call reportWinEvent() when BID_WON event is fired', () => { + sinon.stub(aolAnalytics, 'reportWinEvent'); + events.emit(BID_WON, BIDS.VALID); + expect(aolAnalytics.reportWinEvent.calledOnce).to.be.true; + }); + }); + + describe('reportAuctionEvent()', () => { + beforeEach(() => { + sinon.stub(aolAnalytics, 'reportEvent'); + }); + + afterEach(() => { + if (aolAnalytics.reportEvent.restore) { + aolAnalytics.reportEvent.restore(); + } + }); + + describe('for one ad unit', () => { + it('should report auction with a valid bid', () => { + let adUnitsConfig = [DEFAULT_AD_UNIT]; + let bidsRequested = [BID_SETS.AOL]; + let bidsReceived = [BIDS.VALID]; + + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); + + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(1)).to.be.true; + let bids = aolAnalytics.reportEvent.getCall(0).args[1].bids; + expect(bids).to.include(BIDS.VALID); + expect(bids[0].getStatusCode()).to.equal(1); + }); + + it('should report auction with empty bid', () => { + let adUnitsConfig = [DEFAULT_AD_UNIT]; + let bidsRequested = [BID_SETS.AOL]; + let bidsReceived = [BIDS.EMPTY]; + + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); + + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(1)).to.be.true; + let bids = aolAnalytics.reportEvent.getCall(0).args[1].bids; + expect(bids).to.include(BIDS.EMPTY); + expect(bids[0].getStatusCode()).to.equal(2); + }); + + it('should report auction with timed out bid', () => { + let adUnitsConfig = [DEFAULT_AD_UNIT]; + let bidsRequested = [BID_SETS.AOL]; + let bidsReceived = []; + + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); + + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(1)).to.be.true; + let bids = aolAnalytics.reportEvent.getCall(0).args[1].bids; + expect(bids).to.have.lengthOf(1); + let timedOutBid = bids[0]; + expect(timedOutBid).to.have.property('bidder', 'aol'); + expect(timedOutBid).to.have.property('adUnitCode', DEFAULT_AD_UNIT_CODE); + expect(timedOutBid).to.have.property('cpm', 0); + expect(timedOutBid.getStatusCode()).to.equal(3); + expect(timedOutBid.timeToRespond).to.be.at.least(1); + }); + + it('should report auction with 2 valid bids', () => { + let adUnitsConfig = [createAdUnit({ + bids: [BID_CONFIGS.AOL1, BID_CONFIGS.APPNEXUS1] + })]; + let bidsRequested = createRequestedBids(adUnitsConfig); + let bidsReceived = [ + BIDS.VALID, + createReceivedBid({ + bidder: 'appnexus', + bidderCode: 'appnexus', + adUnitCode: DEFAULT_AD_UNIT_CODE, + getStatusCode: () => 1, + adId: '222bb26f9e8be' + }) + ]; + + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); + + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(1)).to.be.true; + let bids = aolAnalytics.reportEvent.getCall(0).args[1].bids; + expect(bids).to.have.lengthOf(2); + expect(bids[0]).to.have.property('bidder', 'aol'); + expect(bids[1]).to.have.property('bidder', 'appnexus'); + bids.forEach(timedOutBid => { + expect(timedOutBid.getStatusCode()).to.equal(1); + }); + }); + + it('should report auction with 2 timed out bids', () => { + let adUnitsConfig = [createAdUnit({ + bids: [BID_CONFIGS.AOL1, BID_CONFIGS.APPNEXUS1] + })]; + let bidsRequested = createRequestedBids(adUnitsConfig); + let bidsReceived = []; + + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); + + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(1)).to.be.true; + let bids = aolAnalytics.reportEvent.getCall(0).args[1].bids; + expect(bids).to.have.lengthOf(2); + expect(bids[0]).to.have.property('bidder', 'aol'); + expect(bids[1]).to.have.property('bidder', 'appnexus'); + bids.forEach(timedOutBid => { + expect(timedOutBid).to.have.property('adUnitCode', DEFAULT_AD_UNIT_CODE); + expect(timedOutBid).to.have.property('cpm', 0); + expect(timedOutBid.getStatusCode()).to.equal(3); + expect(timedOutBid.timeToRespond).to.be.at.least(1); + }); + }); + + it('should report auction with 2 valid bids and 1 pending', () => { + let adUnitsConfig = [createAdUnit({ + bids: [BID_CONFIGS.AOL1, BID_CONFIGS.APPNEXUS1, BID_CONFIGS.PULSEPOINT1] + })]; + let bidsRequested = createRequestedBids(adUnitsConfig); + let bidsReceived = [ + BIDS.VALID, + createReceivedBid({ + bidder: 'appnexus', + bidderCode: 'appnexus', + adUnitCode: DEFAULT_AD_UNIT_CODE, + getStatusCode: () => 1, + adId: '222bb26f9e8be', + cpm: 0.08, + pbLg: '0.00', + pbMg: '0.08', + pbHg: '0.10', + pbAg: '0.08', + adserverTargeting: { + hb_bidder: 'appnexus', + hb_adid: '222bb26f9e8be', + hb_pb: '8.00', + hb_size: '300x250' + } + }) + ]; + + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); + + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(1)).to.be.true; + let bids = aolAnalytics.reportEvent.getCall(0).args[1].bids; + expect(bids).to.have.lengthOf(3); + expect(bids[0]).to.have.property('bidder', 'aol'); + expect(bids[0].getStatusCode()).to.equal(1); + expect(bids[1]).to.have.property('bidder', 'appnexus'); + expect(bids[1].getStatusCode()).to.equal(1); + expect(bids[2]).to.have.property('bidder', 'pulsepoint'); + expect(bids[2].getStatusCode()).to.equal(3); + bids.forEach(bid => { + expect(bid).to.have.property('adUnitCode', DEFAULT_AD_UNIT_CODE); + expect(bid.timeToRespond).to.be.at.least(1); + }); + }); + + it('should report auction with 2 empty bids and 1 pending', () => { + let adUnitsConfig = [createAdUnit({ + bids: [ + BID_CONFIGS.AOL1, + BID_CONFIGS.APPNEXUS1, + BID_CONFIGS.PULSEPOINT1 + ] + })]; + let bidsRequested = createRequestedBids(adUnitsConfig); + let bidsReceived = [ + BIDS.EMPTY, + createReceivedBid({ + status: 2, + bidder: 'appnexus', + bidderCode: 'appnexus', + adUnitCode: DEFAULT_AD_UNIT_CODE, + getStatusCode: () => 2, + adId: '222bb26f9e8be' + }) + ]; + + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); + + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(1)).to.be.true; + let bids = aolAnalytics.reportEvent.getCall(0).args[1].bids; + expect(bids).to.have.lengthOf(3); + expect(bids[0]).to.have.property('bidder', 'aol'); + expect(bids[0].getStatusCode()).to.equal(2); + expect(bids[1]).to.have.property('bidder', 'appnexus'); + expect(bids[1].getStatusCode()).to.equal(2); + expect(bids[2]).to.have.property('bidder', 'pulsepoint'); + expect(bids[2].getStatusCode()).to.equal(3); + bids.forEach(bid => { + expect(bid).to.have.property('adUnitCode', DEFAULT_AD_UNIT_CODE); + expect(bid.timeToRespond).to.be.at.least(1); + }); + }); + }); + + describe('for 2 ad units', () => { + it('should report auction with 2 valid bids for each ad unit', () => { + let adUnitsConfig = [ + createAdUnit({ + code: 'header-bid-tag-0', + bids: [BID_CONFIGS.AOL1, BID_CONFIGS.APPNEXUS1] + }), + createAdUnit({ + code: 'header-bid-tag-1', + bids: [BID_CONFIGS.AOL2, BID_CONFIGS.PULSEPOINT1] + }) + ]; + let bidsRequested = createRequestedBids(adUnitsConfig); + let bidsReceived = [ + createReceivedBid({ + bidder: 'aol', + bidderCode: 'aol', + adUnitCode: 'header-bid-tag-0' + }), + createReceivedBid({ + bidder: 'aol', + bidderCode: 'aol', + adUnitCode: 'header-bid-tag-1' + }), + createReceivedBid({ + bidder: 'appnexus', + bidderCode: 'appnexus', + adUnitCode: 'header-bid-tag-0' + }), + createReceivedBid({ + bidder: 'pulsepoint', + bidderCode: 'pulsepoint', + adUnitCode: 'header-bid-tag-1' + }) + ]; -describe(` - FEATURE: AOL Prebid Analytics Adapter - STORY: As a publisher I use AOL Analytics to collect data for auction and win events`, () => { + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); + + expect(aolAnalytics.reportEvent.calledTwice).to.be.true; + let call1 = aolAnalytics.reportEvent.getCall(0); + let bids1 = call1.args[1].bids; + expect(call1.calledWith(1)).to.be.true; + expect(call1.args[1]).have.property('aolParams', BID_CONFIGS.AOL1.params); + expect(bids1).to.have.lengthOf(2); + expect(bids1[0]).to.have.property('bidder', 'aol'); + expect(bids1[1]).to.have.property('bidder', 'appnexus'); + bids1.forEach(bid => { + expect(bid).to.have.property('adUnitCode', 'header-bid-tag-0'); + expect(bid.getStatusCode()).to.equal(1); + expect(bid.timeToRespond).to.be.at.least(1); + }); + let call2 = aolAnalytics.reportEvent.getCall(1); + let bids2 = call2.args[1].bids; + expect(call2.calledWith(1)).to.be.true; + expect(call2.args[1]).have.property('aolParams', BID_CONFIGS.AOL2.params); + expect(bids2).to.have.lengthOf(2); + expect(bids2[0]).to.have.property('bidder', 'aol'); + expect(bids2[1]).to.have.property('bidder', 'pulsepoint'); + bids2.forEach(bid => { + expect(bid).to.have.property('adUnitCode', 'header-bid-tag-1'); + expect(bid.getStatusCode()).to.equal(1); + expect(bid.timeToRespond).to.be.at.least(1); + }); + }); + }); - aolAnalytics.enableAnalytics({}); + describe('with multiple bids for the same bidder', () => { + it('should report auction with 2 valid bids from the same bidder', () => { + let adUnitsConfig = [ + createAdUnit({ + bids: [ + BID_CONFIGS.AOL1, + BID_CONFIGS.APPNEXUS1, + BID_CONFIGS.APPNEXUS2 + ] + }) + ]; + let bidsRequested = createRequestedBids(adUnitsConfig); + let bidsReceived = [ + createReceivedBid({ + bidder: 'aol', + bidderCode: 'aol' + }), + createReceivedBid({ + bidder: 'appnexus', + bidderCode: 'appnexus' + }), + createReceivedBid({ + bidder: 'appnexus', + bidderCode: 'appnexus' + }) + ]; - describe(` - SCENARIO: The client side auction is performed to select the winning bid. - GIVEN: A publisher page requests bids`, () => { + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); - describe(`WHEN: The auction is complete by all bids being available or by timeout`, () => { + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(1)).to.be.true; + let args = aolAnalytics.reportEvent.getCall(0).args; + let bids = args[1].bids; + expect(args[1]).have.property('aolParams', BID_CONFIGS.AOL1.params); + expect(bids).to.have.lengthOf(3); + expect(bids[0]).to.have.property('bidder', 'aol'); + expect(bids[1]).to.have.property('bidder', 'appnexus'); + expect(bids[2]).to.have.property('bidder', 'appnexus'); + bids.forEach(bid => { + expect(bid).to.have.property('adUnitCode', DEFAULT_AD_UNIT_CODE); + expect(bid.getStatusCode()).to.equal(1); + expect(bid.timeToRespond).to.be.at.least(1); + }); + }); - let spyTrack = sinon.spy(aolAnalytics, 'track'); - let spyReportEvent = sinon.spy(aolAnalytics, 'reportEvent'); - let spyBuildEndpoint = sinon.spy(aolAnalytics, 'buildEndpoint'); - $$PREBID_GLOBAL$$._bidsReceived = getBidResponses(); - $$PREBID_GLOBAL$$._bidsRequested = getRequestedBids(); - const adUnitsBackup = $$PREBID_GLOBAL$$.adUnits; - $$PREBID_GLOBAL$$.adUnits = getAdUnits(); - let url = 'foobar'; + it('should report auction with 1 valid bid and 1 empty bid from the same bidder', () => { + let adUnitsConfig = [ + createAdUnit({ + bids: [ + BID_CONFIGS.AOL1, + BID_CONFIGS.APPNEXUS1, + BID_CONFIGS.APPNEXUS2 + ] + }) + ]; + let bidsRequested = createRequestedBids(adUnitsConfig); + let bidsReceived = [ + createReceivedBid({ + bidder: 'aol', + bidderCode: 'aol' + }), + createReceivedBid({ + bidder: 'appnexus', + bidderCode: 'appnexus' + }), + createReceivedBid({ + status: 2, + bidder: 'appnexus', + bidderCode: 'appnexus' + }) + ]; - events.emit(AUCTION_END); + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); - it(`THEN: AOL Analytics track is called for the auction complete event`, () => { - assert.ok(spyTrack.calledWith({ - eventType: AUCTION_END, - args: undefined - })); + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(1)).to.be.true; + let call = aolAnalytics.reportEvent.getCall(0); + let bids = call.args[1].bids; + expect(call.args[1]).have.property('aolParams', BID_CONFIGS.AOL1.params); + expect(bids).to.have.lengthOf(3); + expect(bids[0]).to.have.property('bidder', 'aol'); + expect(bids[0].getStatusCode()).to.equal(1); + expect(bids[1]).to.have.property('bidder', 'appnexus'); + expect(bids[1].getStatusCode()).to.equal(1); + expect(bids[2]).to.have.property('bidder', 'appnexus'); + expect(bids[2].getStatusCode()).to.equal(2); + bids.forEach(bid => { + expect(bid).to.have.property('adUnitCode', DEFAULT_AD_UNIT_CODE); + expect(bid.timeToRespond).to.be.at.least(1); + }); + }); + + it('should report auction with valid, empty and pending bids from the same bidder', () => { + let adUnitsConfig = [ + createAdUnit({ + bids: [ + BID_CONFIGS.AOL1, + BID_CONFIGS.APPNEXUS1, + BID_CONFIGS.APPNEXUS2, + BID_CONFIGS.APPNEXUS3 + ] + }) + ]; + let bidsRequested = createRequestedBids(adUnitsConfig); + let bidsReceived = [ + createReceivedBid({ + bidder: 'aol', + bidderCode: 'aol' + }), + createReceivedBid({ + bidder: 'appnexus', + bidderCode: 'appnexus' + }), + createReceivedBid({ + status: 2, + bidder: 'appnexus', + bidderCode: 'appnexus' + }) + ]; + + aolAnalytics.reportAuctionEvent({ adUnitsConfig, bidsRequested, bidsReceived }); + + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(1)).to.be.true; + let call = aolAnalytics.reportEvent.getCall(0); + let bids = call.args[1].bids; + expect(call.args[1]).have.property('aolParams', BID_CONFIGS.AOL1.params); + expect(bids).to.have.lengthOf(4); + expect(bids[0]).to.have.property('bidder', 'aol'); + expect(bids[0].getStatusCode()).to.equal(1); + expect(bids[1]).to.have.property('bidder', 'appnexus'); + expect(bids[1].getStatusCode()).to.equal(1); + expect(bids[2]).to.have.property('bidder', 'appnexus'); + expect(bids[2].getStatusCode()).to.equal(2); + expect(bids[3]).to.have.property('bidder', 'appnexus'); + expect(bids[3].getStatusCode()).to.equal(3); + bids.forEach(bid => { + expect(bid).to.have.property('adUnitCode', DEFAULT_AD_UNIT_CODE); + expect(bid.timeToRespond).to.be.at.least(1); + }); + }); + }); + }); + + describe('buildEventUrl()', () => { + describe('for AUCTION event', () => { + it('should build the default hbevent endpoint', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.contain('hb-us.adtech.advertising.com/hbevent/3.0/'); + }); + + it('should build hbevent endpoint based on region config', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: { + placement: 3675026, + network: '9599.1', + pageid: 12345, + region: 'eu' + }, + bids: [bid], + winner: bid + }); + expect(url).to.contain('hb-eu.adtech.advertising.com/hbevent/3.0/'); + }); + + it('should build hbevent endpoint based on the server option', () => { + aolAnalytics.server = 'hb-as.adtech.advertising.com'; + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + aolAnalytics.server = null; + expect(url).to.contain('hb-as.adtech.advertising.com/hbevent/3.0/'); + }); + + it('should build url with required params - placement & network', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: { + placement: 1234567, + network: '9599.1' + }, + bids: [bid], + winner: bid + }); + expect(url).to.contain('/hbevent/3.0/9599.1/1234567/'); + }); + + it('should build url with pageId of 0 if param is missing', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: { + placement: 1234567, + network: '9599.1' + }, + bids: [bid], + winner: bid + }); + expect(url).to.contain('/hbevent/3.0/9599.1/1234567/0/'); + }); + + it('should build url with pageId optional param', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: { + placement: 1234567, + network: '9599.1', + pageId: 12345 + }, + bids: [bid], + winner: bid + }); + expect(url).to.contain('/hbevent/3.0/9599.1/1234567/12345/'); + }); + + it('should build url with AUCTION event id', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.contain('/1/hbeventts='); + }); + + it('should build url with current timestamp in seconds', () => { + let now = Date.now() / 1000 - 1; + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.match(/hbeventts=\d+;/); + let timestamp = url.match(/hbeventts=(\d+);/)[1]; + expect(timestamp).to.be.within(now, now + 5); + }); + + it('should build url with ad unit code set as pubadid parameter', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + code: DEFAULT_AD_UNIT, + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.contain(`;pubadid=${DEFAULT_AD_UNIT};`); + }); + + it('should build url with hbauctionid parameter having at most 19 digits', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.match(/;hbauctionid=(\d+);/); + let auctionId = url.match(/;hbauctionid=(\d+);/)[1]; + expect(auctionId).to.have.length.at.most(19); + }); + + it('should build url with hbwinner parameter', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.contain(';hbwinner=1;'); // AOL + }); + + it('should build url with hbprice parameter', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.contain(';hbprice=0.1;'); + }); + + it('should build url without hbcur parameter if not set', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.not.contain(';cur='); + }); + + it('should build url with hbcur parameter if set', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: Object.assign({}, BID_CONFIGS.AOL1.params, { currencyCode: 'USD' }), + bids: [bid], + winner: bid + }); + expect(url).to.contain(';hbcur=USD;'); + }); + + it('should build url without pubapi parameter if not set', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.not.contain(';pubapi='); + }); + + it('should build url with pubapi parameter if set', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: Object.assign({}, BID_CONFIGS.AOL1.params, { pubapiId: 456 }), + bids: [bid], + winner: bid + }); + expect(url).to.contain(';pubapi=456;'); + }); + + describe('should include bidders', () => { + it('should build url with one bidder', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid }); + expect(url).to.contain(';hbbidder=1;'); + expect(url).to.contain(';hbbid=0.1;'); + expect(url).to.contain(';hbstatus=0;'); + expect(url).to.contain(`;hbtime=${bid.timeToRespond}`); + }); - it(`THEN: AOL Analytics buildEndpoint is called`, () => { - assert.ok(spyBuildEndpoint.called); + it('should build url with multiple bidders', () => { + let bid1 = BIDS.VALID; + let bid2 = createReceivedBid({ + bidder: 'appnexus', + bidderCode: 'appnexus', + cpm: 0.08 + }); + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid1, bid2], + winner: bid1 }); + expect(url).to.contain(';hbbidder=1;'); + expect(url).to.contain(';hbbid=0.1;'); + expect(url).to.contain(';hbstatus=0;'); + expect(url).to.contain(`;hbtime=${bid1.timeToRespond}`); + expect(url).to.contain(';hbbidder=3;'); + expect(url).to.contain(';hbbid=0.08;'); + expect(url).to.contain(';hbstatus=0;'); + expect(url).to.contain(`;hbtime=${bid2.timeToRespond}`); + }); - it(`THEN: AOL Analytics reportEvent is called to send the auction event with the right URL - containing the right properties`, () => { - assert.ok(spyReportEvent.called); - //TODO (marcio.pereira) deal with generated id and timestamps - //assert.equal(spyReportEvent.args[0][0], url); - }); + it('should build url with hbstatus of 1 for invalid bids', () => { + let bid = BIDS.EMPTY; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.contain(';hbbidder=1;'); + expect(url).to.contain(';hbbid=0;'); + expect(url).to.contain(';hbstatus=1;'); + expect(url).to.contain(`;hbtime=${bid.timeToRespond}`); + }); + + it('should build url with hbstatus of 3 for timed out bids', () => { + let bid = BIDS.TIMED_OUT; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid + }); + expect(url).to.contain(';hbbidder=1;'); + expect(url).to.contain(';hbbid=0;'); + expect(url).to.contain(';hbstatus=3;'); + expect(url).to.contain(`;hbtime=${bid.timeToRespond}`); + }); - $$PREBID_GLOBAL$$._bidsReceived = []; - $$PREBID_GLOBAL$$._bidsRequested = []; - $$PREBID_GLOBAL$$.adUnits = adUnitsBackup; - aolAnalytics.track.restore(); - aolAnalytics.reportEvent.restore(); - aolAnalytics.buildEndpoint.restore(); + it('should build url with valid and timed out bids', () => { + let bid1 = BIDS.VALID; + let bid2 = createReceivedBid({ + status: 3, + bidder: 'appnexus', + bidderCode: 'appnexus', + cpm: 0.08 + }); + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid1, bid2], + winner: bid1 + }); + expect(url).to.contain(';hbbidder=1;'); + expect(url).to.contain(';hbbid=0.1;'); + expect(url).to.contain(';hbstatus=0;'); + expect(url).to.contain(`;hbtime=${bid1.timeToRespond}`); + expect(url).to.contain(';hbbidder=3;'); + expect(url).to.contain(';hbbid=0.08;'); + expect(url).to.contain(';hbstatus=3;'); + expect(url).to.contain(`;hbtime=${bid2.timeToRespond}`); }); }); + }); - describe(` - SCENARIO: The Ad Server side auction is performed, bid is won and the ad is rendedered. - GIVEN: A publisher send the targeting values to the Ad Server.`, () => { + describe('for WIN event', () => { + it('should build the default hbevent endpoint', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + expect(url).to.contain('hb-us.adtech.advertising.com/hbevent/3.0/'); + }); - let spyTrack = sinon.spy(aolAnalytics, 'track'); - let spyReportEvent = sinon.spy(aolAnalytics, 'reportEvent'); - let spyBuildEndpoint = sinon.spy(aolAnalytics, 'buildEndpoint'); - let bidWon = getBidResponses()[2]; - let url = 'foobar'; + it('should build hbevent endpoint based on region config', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: { + placement: 3675026, + network: '9599.1', + pageid: 12345, + region: 'eu' + }, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + expect(url).to.contain('hb-eu.adtech.advertising.com/hbevent/3.0/'); + }); - events.emit(BID_WON, bidWon); + it('should build hbevent endpoint based on the server option', () => { + aolAnalytics.server = 'hb-as.adtech.advertising.com'; + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + aolAnalytics.server = null; + expect(url).to.contain('hb-as.adtech.advertising.com/hbevent/3.0/'); + }); - it(`THEN: AOL Analytics track is called for the bid won event`, () => { - assert.ok(spyTrack.calledWith({ eventType: BID_WON, args: bidWon })); + it('should build url with required params - placement & network', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: { + placement: 1234567, + network: '9599.1' + }, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } }); + expect(url).to.contain('/hbevent/3.0/9599.1/1234567/'); + }); - it(`THEN: AOL Analytics buildEndpoint is called`, () => { - assert.ok(spyBuildEndpoint.called); + it('should build url with pageId of 0 if param is missing', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: { + placement: 1234567, + network: '9599.1' + }, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } }); + expect(url).to.contain('/hbevent/3.0/9599.1/1234567/0/'); + }); - it(`THEN: AOL Analytics reportEvent is called to send the auction event with the right URL - containing the right properties`, () => { - assert.ok(spyReportEvent.called); - //TODO (marcio.pereira) deal with generated id and timestamps - //assert.equal(spyReportEvent.args[0][0], url); - }); + it('should build url with pageId optional param', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: { + placement: 1234567, + network: '9599.1', + pageId: 12345 + }, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + expect(url).to.contain('/hbevent/3.0/9599.1/1234567/12345/'); + }); - aolAnalytics.track.restore(); - aolAnalytics.reportEvent.restore(); - aolAnalytics.buildEndpoint.restore(); + it('should build url with WIN event id', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + expect(url).to.contain('/2/hbeventts='); + }); + + it('should build url with current timestamp in seconds', () => { + let now = Date.now() / 1000 - 1; + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + expect(url).to.match(/hbeventts=\d+;/); + let timestamp = url.match(/hbeventts=(\d+);/)[1]; + expect(timestamp).to.be.within(now, now + 5); + }); + + it('should build url with ad unit code set as pubadid parameter', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + code: DEFAULT_AD_UNIT, + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + expect(url).to.contain(`;pubadid=${DEFAULT_AD_UNIT};`); + }); + + it('should build url with hbauctionid parameter from auction', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + expect(url).to.contain(';hbauctionid=123456789;'); + }); + + it('should build url with hbauctioneventts parameter from auction', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + expect(url).to.contain(';hbauctioneventts=4567890;'); + }); + + it('should build url with hbwinner parameter', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + expect(url).to.contain(';hbwinner=1;'); // AOL + }); + + it('should build url with pubcpm parameter', () => { + let bid = BIDS.VALID; + let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.WIN, { + aolParams: BID_CONFIGS.AOL1.params, + bids: [bid], + winner: bid, + auctionParams: { + hbauctioneventts: 4567890, + hbauctionid: '123456789' + } + }); + expect(url).to.contain(`;pubcpm=${bid.cpm}`); }); + }); }); +}); From 0f7676d65fc640e16f030996b4829f1071390082 Mon Sep 17 00:00:00 2001 From: Marian Rusnak Date: Mon, 10 Oct 2016 19:22:45 +0100 Subject: [PATCH 3/6] Added more unit tests for AOL analytics --- test/spec/unit/adapters/analytics/aol_spec.js | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/test/spec/unit/adapters/analytics/aol_spec.js b/test/spec/unit/adapters/analytics/aol_spec.js index 5db453cefc5..a9bd1667b49 100644 --- a/test/spec/unit/adapters/analytics/aol_spec.js +++ b/test/spec/unit/adapters/analytics/aol_spec.js @@ -523,6 +523,80 @@ describe('AOL analytics adapter', () => { }); }); + describe('reportWinEvent()', () => { + beforeEach(() => { + sinon.stub(aolAnalytics, 'reportEvent'); + }); + + afterEach(() => { + if (aolAnalytics.reportEvent.restore) { + aolAnalytics.reportEvent.restore(); + } + }); + + it('should report win event for the correct ad unit', () => { + let winningBid = { + adUnitCode: 'header-bid-tag-1', + bidder: 'aol', + cpm: 0.1 + }; + let winningAdUnit = { + code: 'header-bid-tag-1', + bids: [winningBid], + winner: winningBid + }; + aolAnalytics.adUnits = { + 'header-bid-tag-0': {}, + 'header-bid-tag-1': winningAdUnit, + 'header-bid-tag-2': {} + }; + aolAnalytics.reportWinEvent({ winningBid }); + + expect(aolAnalytics.reportEvent.calledOnce).to.be.true; + expect(aolAnalytics.reportEvent.calledWith(ANALYTICS_EVENTS.WIN, winningAdUnit)).to.be.true; + }); + }); + + describe('reportEvent()', () => { + let xhr; + let requests; + + beforeEach(() => { + requests = []; + xhr = sinon.useFakeXMLHttpRequest(); + xhr.onCreate = request => requests.push(request); + sinon.stub(aolAnalytics, 'buildEventUrl'); + }); + + afterEach(() => { + xhr.restore(); + if (aolAnalytics.buildEventUrl.restore) { + aolAnalytics.buildEventUrl.restore(); + } + }); + + it('should build event URL', () => { + let event = AUCTION_END; + let adUnit = { foo: 'bar' }; + + aolAnalytics.reportEvent(event, adUnit); + + expect(aolAnalytics.buildEventUrl.calledOnce).to.be.true; + expect(aolAnalytics.buildEventUrl.calledWith(event, adUnit)).to.be.true; + }); + + it('make AJAX call', () => { + let event = AUCTION_END; + let adUnit = { foo: 'bar' }; + + aolAnalytics.buildEventUrl.returns('http://www.example.com/'); + aolAnalytics.reportEvent(event, adUnit); + + expect(requests).to.have.lengthOf(1); + expect(requests[0].url).to.equal('http://www.example.com/'); + }); + }); + describe('buildEventUrl()', () => { describe('for AUCTION event', () => { it('should build the default hbevent endpoint', () => { From eb1c3920d9d3aef4d1ff795570ac5f123d08da59 Mon Sep 17 00:00:00 2001 From: Marian Rusnak Date: Fri, 21 Oct 2016 15:57:34 +0100 Subject: [PATCH 4/6] Minor refactoring of unit tests for AOL analytics - addressed PR feedback --- test/spec/unit/adapters/analytics/aol_spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/spec/unit/adapters/analytics/aol_spec.js b/test/spec/unit/adapters/analytics/aol_spec.js index a9bd1667b49..22dab894728 100644 --- a/test/spec/unit/adapters/analytics/aol_spec.js +++ b/test/spec/unit/adapters/analytics/aol_spec.js @@ -80,7 +80,7 @@ describe('AOL analytics adapter', () => { aolAnalytics.enableAnalytics({}); - describe('enableAnalytics', () => { + describe('enableAnalytics()', () => { afterEach(() => { if (utils.logMessage.restore) { utils.logMessage.restore(); @@ -710,7 +710,7 @@ describe('AOL analytics adapter', () => { expect(url).to.contain(`;pubadid=${DEFAULT_AD_UNIT};`); }); - it('should build url with hbauctionid parameter having at most 19 digits', () => { + it('should build url with hbauctionid parameter having at most 18 digits', () => { let bid = BIDS.VALID; let url = aolAnalytics.buildEventUrl(ANALYTICS_EVENTS.AUCTION, { aolParams: BID_CONFIGS.AOL1.params, @@ -719,7 +719,7 @@ describe('AOL analytics adapter', () => { }); expect(url).to.match(/;hbauctionid=(\d+);/); let auctionId = url.match(/;hbauctionid=(\d+);/)[1]; - expect(auctionId).to.have.length.at.most(19); + expect(auctionId).to.have.length.at.most(18); }); it('should build url with hbwinner parameter', () => { From 0e8c0f5afb52cc9b126c599434229ec4d20b7395 Mon Sep 17 00:00:00 2001 From: Marian Rusnak Date: Fri, 21 Oct 2016 16:05:28 +0100 Subject: [PATCH 5/6] Refactoring of unit tests for AOL analytics #2 --- test/spec/unit/adapters/analytics/aol_spec.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/spec/unit/adapters/analytics/aol_spec.js b/test/spec/unit/adapters/analytics/aol_spec.js index 22dab894728..2ff35ce5516 100644 --- a/test/spec/unit/adapters/analytics/aol_spec.js +++ b/test/spec/unit/adapters/analytics/aol_spec.js @@ -26,6 +26,10 @@ const ANALYTICS_EVENTS = { describe('AOL analytics adapter', () => { + before(() => { + aolAnalytics.enableAnalytics({}); + }); + afterEach(() => { aolAnalytics.adUnits = {}; }); @@ -78,8 +82,6 @@ describe('AOL analytics adapter', () => { return Object.assign({}, DEFAULT_RECEIVED_BID, bidResponse); } - aolAnalytics.enableAnalytics({}); - describe('enableAnalytics()', () => { afterEach(() => { if (utils.logMessage.restore) { From 8dabc4fbee8f523e08262b17b791b8f8b0ac1e55 Mon Sep 17 00:00:00 2001 From: Marian Rusnak Date: Mon, 24 Oct 2016 10:01:51 +0100 Subject: [PATCH 6/6] Updated CHANGELOG --- CHANGELOG | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 13a9334cc6c..d6042358edb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,10 +1,14 @@ -AOL Prebid 1.4.0 +AOL Prebid 1.4.1 ---------------- -Updated to Prebid 0.13.1 Refactoring of AOL analytics. Fixed reporting of pageId parameter in AOL analytics. +AOL Prebid 1.4.0 +---------------- +Updated to Prebid 0.13.1 + + AOL Prebid 1.3.1 ---------------- Fixed reporting of timed out bids in AOL analytics.