prebid.js 7.18.0 → 7.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/33acrossIdSystem.js +1 -1
- package/dist/adWMGAnalyticsAdapter.js +1 -1
- package/dist/adagioAnalyticsAdapter.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adbookpspBidAdapter.js +1 -1
- package/dist/adfBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adkernelAdnAnalyticsAdapter.js +1 -1
- package/dist/adkernelBidAdapter.js +1 -1
- package/dist/adlooxAdServerVideo.js +1 -1
- package/dist/adlooxAnalyticsAdapter.js +1 -1
- package/dist/adlooxRtdProvider.js +1 -1
- package/dist/adomikAnalyticsAdapter.js +1 -1
- package/dist/adqueryIdSystem.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adtrgtmeBidAdapter.js +1 -1
- package/dist/adxcgAnalyticsAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/adxpremiumAnalyticsAdapter.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/aolBidAdapter.js +1 -1
- package/dist/appierAnalyticsAdapter.js +1 -1
- package/dist/appnexusBidAdapter.js +1 -1
- package/dist/asoBidAdapter.js +1 -1
- package/dist/atsAnalyticsAdapter.js +1 -1
- package/dist/axonixBidAdapter.js +1 -1
- package/dist/{andBeyondMediaBidAdapter.js → beyondmediaBidAdapter.js} +1 -1
- package/dist/bidViewability.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/bidwatchAnalyticsAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/byDataAnalyticsAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -1
- package/dist/categoryTranslation.js +1 -1
- package/dist/cleanioRtdProvider.js +1 -1
- package/dist/colossussspBidAdapter.js +1 -1
- package/dist/concertAnalyticsAdapter.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectIdSystem.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consentManagement.js +1 -1
- package/dist/consentManagementUsp.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/conversantAnalyticsAdapter.js +1 -0
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/currency.js +1 -1
- package/dist/datablocksAnalyticsAdapter.js +1 -1
- package/dist/dchain.js +1 -1
- package/dist/debugging-standalone.js +1 -1
- package/dist/debugging.js +1 -1
- package/dist/dependencies.json +9 -0
- package/dist/dfpAdServerVideo.js +1 -1
- package/dist/dgkeywordRtdProvider.js +1 -1
- package/dist/dianomiBidAdapter.js +1 -1
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/enrichmentFpdModule.js +1 -1
- package/dist/eplanningAnalyticsAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/fintezaAnalyticsAdapter.js +1 -1
- package/dist/fpd.js +1 -0
- package/dist/ftrackIdSystem.js +1 -1
- package/dist/gdprEnforcement.js +1 -1
- package/dist/glimpseBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/goldbachBidAdapter.js +1 -1
- package/dist/googleAnalyticsAdapter.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/gridNMBidAdapter.js +1 -1
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/hadronAnalyticsAdapter.js +1 -1
- package/dist/id5AnalyticsAdapter.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/inmarBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/invisiblyAnalyticsAdapter.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/kargoAnalyticsAdapter.js +1 -1
- package/dist/kinessoIdSystem.js +1 -1
- package/dist/konduitAnalyticsAdapter.js +1 -1
- package/dist/kueezBidAdapter.js +1 -1
- package/dist/lassoBidAdapter.js +1 -1
- package/dist/lifestreetBidAdapter.js +1 -1
- package/dist/liveIntentAnalyticsAdapter.js +1 -1
- package/dist/liveIntentIdSystem.js +1 -1
- package/dist/livewrappedAnalyticsAdapter.js +1 -1
- package/dist/liveyieldAnalyticsAdapter.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/lotamePanoramaIdSystem.js +1 -1
- package/dist/magniteAnalyticsAdapter.js +1 -0
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mass.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/mediakeysBidAdapter.js +1 -1
- package/dist/medianetAnalyticsAdapter.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/minutemediaBidAdapter.js +1 -1
- package/dist/multibid.js +1 -1
- package/dist/nativoBidAdapter.js +1 -1
- package/dist/not-for-prod/prebid.js +198 -194
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/openxAnalyticsAdapter.js +1 -1
- package/dist/optimonAnalyticsAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/parrableIdSystem.js +1 -1
- package/dist/pianoDmpAnalyticsAdapter.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prebid-core.js +2 -2
- package/dist/prebidServerBidAdapter.js +1 -1
- package/dist/prebidmanagerAnalyticsAdapter.js +1 -1
- package/dist/priceFloors.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticAnalyticsAdapter.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubperfAnalyticsAdapter.js +1 -1
- package/dist/pubstackAnalyticsAdapter.js +1 -1
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pubxaiAnalyticsAdapter.js +1 -1
- package/dist/pulsepointAnalyticsAdapter.js +1 -1
- package/dist/pxyzBidAdapter.js +1 -1
- package/dist/quantcastBidAdapter.js +1 -1
- package/dist/quantcastIdSystem.js +1 -1
- package/dist/readpeakBidAdapter.js +1 -1
- package/dist/realvuAnalyticsAdapter.js +1 -1
- package/dist/relaidoBidAdapter.js +1 -1
- package/dist/relevantAnalyticsAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseBidAdapter.js +1 -1
- package/dist/rivrAnalyticsAdapter.js +1 -1
- package/dist/roxotAnalyticsAdapter.js +1 -1
- package/dist/rtdModule.js +1 -1
- package/dist/rubiconAnalyticsAdapter.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/s2sTesting.js +1 -1
- package/dist/scaleableAnalyticsAdapter.js +1 -1
- package/dist/schain.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- package/dist/sharedIdSystem.js +1 -1
- package/dist/sharethroughAnalyticsAdapter.js +1 -1
- package/dist/sharethroughBidAdapter.js +1 -1
- package/dist/shinezBidAdapter.js +1 -1
- package/dist/sigmoidAnalyticsAdapter.js +1 -1
- package/dist/smaatoBidAdapter.js +1 -1
- package/dist/smartadserverBidAdapter.js +1 -1
- package/dist/smartxBidAdapter.js +1 -1
- package/dist/smilewantedBidAdapter.js +1 -1
- package/dist/sonobiAnalyticsAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sovrnAnalyticsAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/staqAnalyticsAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/synacormediaBidAdapter.js +1 -1
- package/dist/taboolaBidAdapter.js +1 -1
- package/dist/tapadIdSystem.js +1 -1
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.js +1 -1
- package/dist/teadsIdSystem.js +1 -0
- package/dist/terceptAnalyticsAdapter.js +1 -1
- package/dist/trionBidAdapter.js +1 -1
- package/dist/tripleliftBidAdapter.js +1 -1
- package/dist/ttdBidAdapter.js +1 -1
- package/dist/ucfunnelAnalyticsAdapter.js +1 -1
- package/dist/underdogmediaBidAdapter.js +1 -1
- package/dist/undertoneBidAdapter.js +1 -1
- package/dist/userId.js +1 -1
- package/dist/vidazooBidAdapter.js +1 -1
- package/dist/videobyteBidAdapter.js +1 -1
- package/dist/visxBidAdapter.js +1 -1
- package/dist/vrtcalBidAdapter.js +1 -1
- package/dist/vuukleBidAdapter.js +1 -1
- package/dist/weboramaRtdProvider.js +1 -1
- package/dist/widespaceBidAdapter.js +1 -1
- package/dist/winrBidAdapter.js +1 -1
- package/dist/yahoosspBidAdapter.js +1 -1
- package/dist/yandexBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/dist/yuktamediaAnalyticsAdapter.js +1 -1
- package/dist/zeta_global_sspAnalyticsAdapter.js +1 -1
- package/libraries/fpd/sua.js +98 -0
- package/modules/.submodules.json +1 -0
- package/modules/adfBidAdapter.js +1 -1
- package/modules/adkernelAdnBidAdapter.js +1 -0
- package/modules/adkernelBidAdapter.js +2 -2
- package/modules/adqueryIdSystem.js +8 -8
- package/modules/adxcgBidAdapter.js +1 -1
- package/modules/amxBidAdapter.js +1 -1
- package/modules/aolBidAdapter.js +25 -2
- package/modules/appnexusBidAdapter.js +19 -2
- package/modules/{andBeyondMediaBidAdapter.js → beyondmediaBidAdapter.js} +0 -0
- package/modules/{andBeyondMediaBidAdapter.md → beyondmediaBidAdapter.md} +1 -1
- package/modules/categoryTranslation.js +4 -4
- package/modules/cleanioRtdProvider.js +3 -4
- package/modules/colossussspBidAdapter.js +2 -1
- package/modules/connectIdSystem.js +16 -1
- package/modules/conversantAnalyticsAdapter.js +560 -0
- package/modules/conversantAnalyticsAdapter.md +47 -0
- package/modules/criteoBidAdapter.js +1 -1
- package/modules/currency.js +11 -11
- package/modules/dchain.js +2 -2
- package/modules/debugging/bidInterceptor.js +2 -2
- package/modules/debugging/debugging.js +10 -2
- package/modules/debugging/legacy.js +2 -2
- package/modules/dgkeywordRtdProvider.js +21 -3
- package/modules/dianomiBidAdapter.js +1 -1
- package/modules/enrichmentFpdModule.js +33 -14
- package/modules/eplanningBidAdapter.js +48 -2
- package/modules/finativeBidAdapter.js +1 -1
- package/modules/gridBidAdapter.js +187 -117
- package/modules/improvedigitalBidAdapter.js +2 -2
- package/modules/ixBidAdapter.js +94 -23
- package/modules/liveIntentIdSystem.js +39 -5
- package/modules/lotamePanoramaIdSystem.js +10 -6
- package/modules/magniteAnalyticsAdapter.js +902 -0
- package/modules/magniteAnalyticsAdapter.md +18 -0
- package/modules/mass.js +2 -2
- package/modules/mediakeysBidAdapter.js +6 -1
- package/modules/mediakeysBidAdapter.md +50 -40
- package/modules/multibid/index.js +5 -5
- package/modules/nativoBidAdapter.js +1 -1
- package/modules/pixfutureBidAdapter.js +46 -15
- package/modules/prebidServerBidAdapter/index.js +54 -19
- package/modules/priceFloors.js +8 -22
- package/modules/readpeakBidAdapter.js +1 -1
- package/modules/rubiconAnalyticsAdapter.js +14 -9
- package/modules/rubiconBidAdapter.js +2 -3
- package/modules/seedingAllianceBidAdapter.js +1 -1
- package/modules/sharethroughBidAdapter.js +1 -1
- package/modules/taboolaBidAdapter.js +5 -5
- package/modules/talkadsBidAdapter.js +1 -0
- package/modules/teadsIdSystem.js +234 -0
- package/modules/teadsIdSystem.md +22 -0
- package/modules/truereachBidAdapter.js +1 -0
- package/modules/ttdBidAdapter.js +1 -1
- package/modules/userId/index.js +21 -14
- package/modules/vrtcalBidAdapter.js +7 -1
- package/modules/vuukleBidAdapter.js +34 -3
- package/modules/yahoosspBidAdapter.js +4 -2
- package/modules/yandexBidAdapter.js +31 -8
- package/package.json +2 -2
- package/src/adapterManager.js +2 -4
- package/src/adapters/bidderFactory.js +13 -11
- package/src/auction.js +140 -69
- package/src/constants.json +8 -0
- package/src/cpmBucketManager.js +22 -3
- package/src/native.js +1 -5
- package/src/prebid.js +5 -6
- package/src/targeting.js +31 -14
- package/test/fixtures/fixtures.js +2 -1
- package/test/spec/auctionmanager_spec.js +109 -21
- package/test/spec/cpmBucketManager_spec.js +239 -177
- package/test/spec/fpd/sua_spec.js +244 -0
- package/test/spec/modules/adfBidAdapter_spec.js +2 -3
- package/test/spec/modules/adqueryIdSystem_spec.js +0 -2
- package/test/spec/modules/adxcgBidAdapter_spec.js +2 -3
- package/test/spec/modules/amxBidAdapter_spec.js +3 -2
- package/test/spec/modules/aolBidAdapter_spec.js +42 -9
- package/test/spec/modules/appnexusBidAdapter_spec.js +24 -0
- package/test/spec/modules/{andBeyondMediaBidAdapter_spec.js → beyondmediaBidAdapter_spec.js} +1 -1
- package/test/spec/modules/colossussspBidAdapter_spec.js +4 -2
- package/test/spec/modules/connectIdSystem_spec.js +20 -0
- package/test/spec/modules/conversantAnalyticsAdapter_spec.js +963 -0
- package/test/spec/modules/currency_spec.js +14 -6
- package/test/spec/modules/debugging_mod_spec.js +9 -0
- package/test/spec/modules/dgkeywordRtdProvider_spec.js +83 -1
- package/test/spec/modules/dianomiBidAdapter_spec.js +2 -3
- package/test/spec/modules/enrichmentFpdModule_spec.js +50 -7
- package/test/spec/modules/eplanningBidAdapter_spec.js +285 -1
- package/test/spec/modules/fpdModule_spec.js +9 -0
- package/test/spec/modules/gridBidAdapter_spec.js +87 -31
- package/test/spec/modules/ixBidAdapter_spec.js +221 -2
- package/test/spec/modules/liveIntentIdMinimalSystem_spec.js +62 -8
- package/test/spec/modules/liveIntentIdSystem_spec.js +62 -8
- package/test/spec/modules/lotamePanoramaIdSystem_spec.js +0 -1
- package/test/spec/modules/magniteAnalyticsAdapter_spec.js +1942 -0
- package/test/spec/modules/mediakeysBidAdapter_spec.js +20 -3
- package/test/spec/modules/nativoBidAdapter_spec.js +13 -2
- package/test/spec/modules/prebidServerBidAdapter_spec.js +202 -15
- package/test/spec/modules/priceFloors_spec.js +5 -5
- package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +2 -3
- package/test/spec/modules/seedtagBidAdapter_spec.js +15 -18
- package/test/spec/modules/sharethroughBidAdapter_spec.js +2 -1
- package/test/spec/modules/taboolaBidAdapter_spec.js +112 -13
- package/test/spec/modules/teadsIdSystem_spec.js +271 -0
- package/test/spec/modules/ttdBidAdapter_spec.js +3 -3
- package/test/spec/modules/userId_spec.js +39 -4
- package/test/spec/modules/vrtcalBidAdapter_spec.js +12 -1
- package/test/spec/modules/vuukleBidAdapter_spec.js +87 -0
- package/test/spec/modules/yahoosspBidAdapter_spec.js +48 -1
- package/test/spec/modules/yandexBidAdapter_spec.js +8 -5
- package/test/spec/native_spec.js +5 -0
- package/test/spec/unit/core/bidderFactory_spec.js +66 -11
- package/test/spec/unit/core/targeting_spec.js +28 -9
- package/test/spec/unit/pbjs_api_spec.js +48 -2
|
@@ -0,0 +1,1942 @@
|
|
|
1
|
+
import magniteAdapter, {
|
|
2
|
+
parseBidResponse,
|
|
3
|
+
getHostNameFromReferer,
|
|
4
|
+
storage,
|
|
5
|
+
rubiConf,
|
|
6
|
+
} from '../../../modules/magniteAnalyticsAdapter.js';
|
|
7
|
+
import CONSTANTS from 'src/constants.json';
|
|
8
|
+
import { config } from 'src/config.js';
|
|
9
|
+
import { server } from 'test/mocks/xhr.js';
|
|
10
|
+
import * as mockGpt from '../integration/faker/googletag.js';
|
|
11
|
+
import {
|
|
12
|
+
setConfig,
|
|
13
|
+
addBidResponseHook,
|
|
14
|
+
} from 'modules/currency.js';
|
|
15
|
+
import { getGlobal } from '../../../src/prebidGlobal.js';
|
|
16
|
+
import { deepAccess } from '../../../src/utils.js';
|
|
17
|
+
|
|
18
|
+
let events = require('src/events.js');
|
|
19
|
+
let utils = require('src/utils.js');
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
EVENTS: {
|
|
23
|
+
AUCTION_INIT,
|
|
24
|
+
AUCTION_END,
|
|
25
|
+
BID_REQUESTED,
|
|
26
|
+
BID_RESPONSE,
|
|
27
|
+
BIDDER_DONE,
|
|
28
|
+
BID_WON,
|
|
29
|
+
BID_TIMEOUT,
|
|
30
|
+
BILLABLE_EVENT
|
|
31
|
+
}
|
|
32
|
+
} = CONSTANTS;
|
|
33
|
+
|
|
34
|
+
const STUBBED_UUID = '12345678-1234-1234-1234-123456789abc';
|
|
35
|
+
|
|
36
|
+
// Mock Event Data
|
|
37
|
+
const MOCK = {
|
|
38
|
+
AUCTION_INIT: {
|
|
39
|
+
'auctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
40
|
+
'timestamp': 1658868383741,
|
|
41
|
+
'adUnits': [
|
|
42
|
+
{
|
|
43
|
+
'code': 'box',
|
|
44
|
+
'mediaTypes': {
|
|
45
|
+
'banner': {
|
|
46
|
+
'sizes': [
|
|
47
|
+
[
|
|
48
|
+
300,
|
|
49
|
+
250
|
|
50
|
+
]
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
'bids': [
|
|
55
|
+
{
|
|
56
|
+
'bidder': 'rubicon',
|
|
57
|
+
'params': {
|
|
58
|
+
'accountId': 1001,
|
|
59
|
+
'siteId': 267318,
|
|
60
|
+
'zoneId': 1861698
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
'sizes': [
|
|
65
|
+
[
|
|
66
|
+
300,
|
|
67
|
+
250
|
|
68
|
+
]
|
|
69
|
+
],
|
|
70
|
+
'transactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
71
|
+
'ortb2Imp': {
|
|
72
|
+
'ext': {
|
|
73
|
+
'tid': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
74
|
+
'data': {
|
|
75
|
+
'adserver': {
|
|
76
|
+
'name': 'gam',
|
|
77
|
+
'adslot': '/1234567/prebid-slot'
|
|
78
|
+
},
|
|
79
|
+
'pbadslot': '/1234567/prebid-slot'
|
|
80
|
+
},
|
|
81
|
+
'gpid': '/1234567/prebid-slot'
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
'bidderRequests': [
|
|
87
|
+
{
|
|
88
|
+
'bidderCode': 'rubicon',
|
|
89
|
+
'bids': [
|
|
90
|
+
{
|
|
91
|
+
'bidder': 'rubicon',
|
|
92
|
+
'params': {
|
|
93
|
+
'accountId': 1001,
|
|
94
|
+
'siteId': 267318,
|
|
95
|
+
'zoneId': 1861698,
|
|
96
|
+
},
|
|
97
|
+
'adUnitCode': 'box',
|
|
98
|
+
'transactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
99
|
+
'bidId': '23fcd8cf4bf0d7',
|
|
100
|
+
'src': 'client',
|
|
101
|
+
'startTime': 1658868383748
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
'refererInfo': {
|
|
105
|
+
'page': 'http://a-test-domain.com:8000/test_pages/sanity/TEMP/prebidTest.html?pbjs_debug=true',
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
'timeout': 3000,
|
|
110
|
+
'config': {
|
|
111
|
+
'accountId': 1001,
|
|
112
|
+
'endpoint': 'https://pba-event-service-alb-dev.use1.fanops.net/event'
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
BID_REQUESTED: {
|
|
116
|
+
'bidderCode': 'rubicon',
|
|
117
|
+
'auctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
118
|
+
'transactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
119
|
+
'bids': [
|
|
120
|
+
{
|
|
121
|
+
'bidder': 'rubicon',
|
|
122
|
+
'params': {
|
|
123
|
+
'accountId': 1001,
|
|
124
|
+
'siteId': 267318,
|
|
125
|
+
'zoneId': 1861698,
|
|
126
|
+
},
|
|
127
|
+
'adUnitCode': 'box',
|
|
128
|
+
'bidId': '23fcd8cf4bf0d7',
|
|
129
|
+
'transactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
130
|
+
'src': 'client',
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
BID_RESPONSE: {
|
|
135
|
+
'bidderCode': 'rubicon',
|
|
136
|
+
'width': 300,
|
|
137
|
+
'height': 250,
|
|
138
|
+
'adId': '3c0b59947ced11',
|
|
139
|
+
'requestId': '23fcd8cf4bf0d7',
|
|
140
|
+
'transactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
141
|
+
'auctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
142
|
+
'mediaType': 'banner',
|
|
143
|
+
'source': 'client',
|
|
144
|
+
'currency': 'USD',
|
|
145
|
+
'creativeId': '4954828',
|
|
146
|
+
'cpm': 3.4,
|
|
147
|
+
'ttl': 300,
|
|
148
|
+
'netRevenue': true,
|
|
149
|
+
'ad': '<html></html>',
|
|
150
|
+
'bidder': 'rubicon',
|
|
151
|
+
'adUnitCode': 'box',
|
|
152
|
+
'timeToRespond': 271,
|
|
153
|
+
'size': '300x250',
|
|
154
|
+
'status': 'rendered',
|
|
155
|
+
getStatusCode: () => 1,
|
|
156
|
+
},
|
|
157
|
+
AUCTION_END: {
|
|
158
|
+
'auctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
159
|
+
'auctionEnd': 1658868384019,
|
|
160
|
+
},
|
|
161
|
+
BIDDER_DONE: {
|
|
162
|
+
'bidderCode': 'rubicon',
|
|
163
|
+
'auctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
164
|
+
'bids': [
|
|
165
|
+
{
|
|
166
|
+
'bidder': 'rubicon',
|
|
167
|
+
'adUnitCode': 'box',
|
|
168
|
+
'transactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
169
|
+
'bidId': '23fcd8cf4bf0d7',
|
|
170
|
+
'auctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
171
|
+
'src': 'client',
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
BID_WON: {
|
|
176
|
+
'bidderCode': 'rubicon',
|
|
177
|
+
'bidId': '23fcd8cf4bf0d7',
|
|
178
|
+
'adId': '3c0b59947ced11',
|
|
179
|
+
'requestId': '23fcd8cf4bf0d7',
|
|
180
|
+
'transactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
181
|
+
'auctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
182
|
+
'mediaType': 'banner',
|
|
183
|
+
'currency': 'USD',
|
|
184
|
+
'cpm': 3.4,
|
|
185
|
+
'ttl': 300,
|
|
186
|
+
'bidder': 'rubicon',
|
|
187
|
+
'adUnitCode': 'box',
|
|
188
|
+
'status': 'rendered',
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const ANALYTICS_MESSAGE = {
|
|
193
|
+
'channel': 'web',
|
|
194
|
+
'integration': 'pbjs',
|
|
195
|
+
'referrerUri': 'http://a-test-domain.com:8000/test_pages/sanity/TEMP/prebidTest.html?pbjs_debug=true',
|
|
196
|
+
'version': '$prebid.version$',
|
|
197
|
+
'referrerHostname': 'a-test-domain.com',
|
|
198
|
+
'timestamps': {
|
|
199
|
+
'timeSincePageLoad': 500,
|
|
200
|
+
'eventTime': 1519767014281,
|
|
201
|
+
'prebidLoaded': magniteAdapter.MODULE_INITIALIZED_TIME
|
|
202
|
+
},
|
|
203
|
+
'wrapper': {
|
|
204
|
+
'name': '10000_fakewrapper_test'
|
|
205
|
+
},
|
|
206
|
+
'session': {
|
|
207
|
+
'id': '12345678-1234-1234-1234-123456789abc',
|
|
208
|
+
'pvid': '12345678',
|
|
209
|
+
'start': 1519767013781,
|
|
210
|
+
'expires': 1519788613781
|
|
211
|
+
},
|
|
212
|
+
'auctions': [
|
|
213
|
+
{
|
|
214
|
+
'auctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
215
|
+
'auctionStart': 1658868383741,
|
|
216
|
+
'samplingFactor': 1,
|
|
217
|
+
'clientTimeoutMillis': 3000,
|
|
218
|
+
'accountId': 1001,
|
|
219
|
+
'bidderOrder': [
|
|
220
|
+
'rubicon'
|
|
221
|
+
],
|
|
222
|
+
'serverTimeoutMillis': 1000,
|
|
223
|
+
'adUnits': [
|
|
224
|
+
{
|
|
225
|
+
'adUnitCode': 'box',
|
|
226
|
+
'transactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
227
|
+
'mediaTypes': [
|
|
228
|
+
'banner'
|
|
229
|
+
],
|
|
230
|
+
'dimensions': [
|
|
231
|
+
{
|
|
232
|
+
'width': 300,
|
|
233
|
+
'height': 250
|
|
234
|
+
}
|
|
235
|
+
],
|
|
236
|
+
'pbAdSlot': '/1234567/prebid-slot',
|
|
237
|
+
'gpid': '/1234567/prebid-slot',
|
|
238
|
+
'bids': [
|
|
239
|
+
{
|
|
240
|
+
'bidder': 'rubicon',
|
|
241
|
+
'bidId': '23fcd8cf4bf0d7',
|
|
242
|
+
'source': 'client',
|
|
243
|
+
'status': 'success',
|
|
244
|
+
'clientLatencyMillis': 271,
|
|
245
|
+
'bidResponse': {
|
|
246
|
+
'bidPriceUSD': 3.4,
|
|
247
|
+
'mediaType': 'banner',
|
|
248
|
+
'dimensions': {
|
|
249
|
+
'width': 300,
|
|
250
|
+
'height': 250
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
],
|
|
255
|
+
'accountId': 1001,
|
|
256
|
+
'siteId': 267318,
|
|
257
|
+
'zoneId': 1861698,
|
|
258
|
+
'status': 'success'
|
|
259
|
+
}
|
|
260
|
+
],
|
|
261
|
+
'auctionEnd': 1658868384019
|
|
262
|
+
}
|
|
263
|
+
],
|
|
264
|
+
'gamRenders': [
|
|
265
|
+
{
|
|
266
|
+
'adSlot': 'box',
|
|
267
|
+
'advertiserId': 1111,
|
|
268
|
+
'creativeId': 2222,
|
|
269
|
+
'lineItemId': 3333,
|
|
270
|
+
'auctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
271
|
+
'transactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a'
|
|
272
|
+
}
|
|
273
|
+
],
|
|
274
|
+
'bidsWon': [
|
|
275
|
+
{
|
|
276
|
+
'bidder': 'rubicon',
|
|
277
|
+
'bidId': '23fcd8cf4bf0d7',
|
|
278
|
+
'source': 'client',
|
|
279
|
+
'status': 'success',
|
|
280
|
+
'clientLatencyMillis': 271,
|
|
281
|
+
'bidResponse': {
|
|
282
|
+
'bidPriceUSD': 3.4,
|
|
283
|
+
'mediaType': 'banner',
|
|
284
|
+
'dimensions': {
|
|
285
|
+
'width': 300,
|
|
286
|
+
'height': 250
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
'sourceAuctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
290
|
+
'renderAuctionId': '99785e47-a7c8-4c8a-ae05-ef1c717a4b4d',
|
|
291
|
+
'sourceTransactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
292
|
+
'renderTransactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
293
|
+
'transactionId': '7b10a106-89ea-4e19-bc51-9b2e970fc42a',
|
|
294
|
+
'accountId': 1001,
|
|
295
|
+
'siteId': 267318,
|
|
296
|
+
'zoneId': 1861698,
|
|
297
|
+
'mediaTypes': [
|
|
298
|
+
'banner'
|
|
299
|
+
],
|
|
300
|
+
'adUnitCode': 'box'
|
|
301
|
+
}
|
|
302
|
+
],
|
|
303
|
+
'trigger': 'gam-delayed'
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
describe('magnite analytics adapter', function () {
|
|
307
|
+
let sandbox;
|
|
308
|
+
let clock;
|
|
309
|
+
let getDataFromLocalStorageStub, setDataInLocalStorageStub, localStorageIsEnabledStub;
|
|
310
|
+
let gptSlot0;
|
|
311
|
+
let gptSlotRenderEnded0;
|
|
312
|
+
beforeEach(function () {
|
|
313
|
+
mockGpt.enable();
|
|
314
|
+
gptSlot0 = mockGpt.makeSlot({ code: 'box' });
|
|
315
|
+
gptSlotRenderEnded0 = {
|
|
316
|
+
eventName: 'slotRenderEnded',
|
|
317
|
+
params: {
|
|
318
|
+
slot: gptSlot0,
|
|
319
|
+
isEmpty: false,
|
|
320
|
+
advertiserId: 1111,
|
|
321
|
+
sourceAgnosticCreativeId: 2222,
|
|
322
|
+
sourceAgnosticLineItemId: 3333
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage');
|
|
326
|
+
setDataInLocalStorageStub = sinon.stub(storage, 'setDataInLocalStorage');
|
|
327
|
+
localStorageIsEnabledStub = sinon.stub(storage, 'localStorageIsEnabled');
|
|
328
|
+
sandbox = sinon.sandbox.create();
|
|
329
|
+
|
|
330
|
+
localStorageIsEnabledStub.returns(true);
|
|
331
|
+
|
|
332
|
+
sandbox.stub(events, 'getEvents').returns([]);
|
|
333
|
+
|
|
334
|
+
sandbox.stub(utils, 'generateUUID').returns(STUBBED_UUID);
|
|
335
|
+
|
|
336
|
+
clock = sandbox.useFakeTimers(1519767013781);
|
|
337
|
+
|
|
338
|
+
magniteAdapter.referrerHostname = '';
|
|
339
|
+
|
|
340
|
+
config.setConfig({
|
|
341
|
+
s2sConfig: {
|
|
342
|
+
timeout: 1000,
|
|
343
|
+
accountId: 10000,
|
|
344
|
+
},
|
|
345
|
+
rubicon: {
|
|
346
|
+
wrapperName: '10000_fakewrapper_test'
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
afterEach(function () {
|
|
352
|
+
sandbox.restore();
|
|
353
|
+
config.resetConfig();
|
|
354
|
+
mockGpt.enable();
|
|
355
|
+
getDataFromLocalStorageStub.restore();
|
|
356
|
+
setDataInLocalStorageStub.restore();
|
|
357
|
+
localStorageIsEnabledStub.restore();
|
|
358
|
+
magniteAdapter.disableAnalytics();
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it('should require accountId', function () {
|
|
362
|
+
sandbox.stub(utils, 'logError');
|
|
363
|
+
|
|
364
|
+
magniteAdapter.enableAnalytics({
|
|
365
|
+
options: {
|
|
366
|
+
endpoint: '//localhost:9999/event'
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
expect(utils.logError.called).to.equal(true);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it('should require endpoint', function () {
|
|
374
|
+
sandbox.stub(utils, 'logError');
|
|
375
|
+
|
|
376
|
+
magniteAdapter.enableAnalytics({
|
|
377
|
+
options: {
|
|
378
|
+
accountId: 1001
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
expect(utils.logError.called).to.equal(true);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
describe('config subscribe', function () {
|
|
386
|
+
it('should update the pvid if user asks', function () {
|
|
387
|
+
expect(utils.generateUUID.called).to.equal(false);
|
|
388
|
+
config.setConfig({ rubicon: { updatePageView: true } });
|
|
389
|
+
expect(utils.generateUUID.called).to.equal(true);
|
|
390
|
+
});
|
|
391
|
+
it('should merge in and preserve older set configs', function () {
|
|
392
|
+
config.setConfig({
|
|
393
|
+
rubicon: {
|
|
394
|
+
wrapperName: '1001_general',
|
|
395
|
+
int_type: 'dmpbjs',
|
|
396
|
+
fpkvs: {
|
|
397
|
+
source: 'fb'
|
|
398
|
+
},
|
|
399
|
+
updatePageView: true
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
expect(rubiConf).to.deep.equal({
|
|
403
|
+
analyticsEventDelay: 500,
|
|
404
|
+
analyticsBatchTimeout: 5000,
|
|
405
|
+
analyticsProcessDelay: 1,
|
|
406
|
+
dmBilling: {
|
|
407
|
+
enabled: false,
|
|
408
|
+
vendors: [],
|
|
409
|
+
waitForAuction: true
|
|
410
|
+
},
|
|
411
|
+
pvid: '12345678',
|
|
412
|
+
wrapperName: '1001_general',
|
|
413
|
+
int_type: 'dmpbjs',
|
|
414
|
+
fpkvs: {
|
|
415
|
+
source: 'fb'
|
|
416
|
+
},
|
|
417
|
+
updatePageView: true
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
// update it with stuff
|
|
421
|
+
config.setConfig({
|
|
422
|
+
rubicon: {
|
|
423
|
+
analyticsBatchTimeout: 3000,
|
|
424
|
+
fpkvs: {
|
|
425
|
+
link: 'email'
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
expect(rubiConf).to.deep.equal({
|
|
430
|
+
analyticsEventDelay: 500,
|
|
431
|
+
analyticsBatchTimeout: 3000,
|
|
432
|
+
analyticsProcessDelay: 1,
|
|
433
|
+
dmBilling: {
|
|
434
|
+
enabled: false,
|
|
435
|
+
vendors: [],
|
|
436
|
+
waitForAuction: true
|
|
437
|
+
},
|
|
438
|
+
pvid: '12345678',
|
|
439
|
+
wrapperName: '1001_general',
|
|
440
|
+
int_type: 'dmpbjs',
|
|
441
|
+
fpkvs: {
|
|
442
|
+
source: 'fb',
|
|
443
|
+
link: 'email'
|
|
444
|
+
},
|
|
445
|
+
updatePageView: true
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
// overwriting specific edge keys should update them
|
|
449
|
+
config.setConfig({
|
|
450
|
+
rubicon: {
|
|
451
|
+
fpkvs: {
|
|
452
|
+
link: 'iMessage',
|
|
453
|
+
source: 'twitter'
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
expect(rubiConf).to.deep.equal({
|
|
458
|
+
analyticsEventDelay: 500,
|
|
459
|
+
analyticsBatchTimeout: 3000,
|
|
460
|
+
analyticsProcessDelay: 1,
|
|
461
|
+
dmBilling: {
|
|
462
|
+
enabled: false,
|
|
463
|
+
vendors: [],
|
|
464
|
+
waitForAuction: true
|
|
465
|
+
},
|
|
466
|
+
pvid: '12345678',
|
|
467
|
+
wrapperName: '1001_general',
|
|
468
|
+
int_type: 'dmpbjs',
|
|
469
|
+
fpkvs: {
|
|
470
|
+
link: 'iMessage',
|
|
471
|
+
source: 'twitter'
|
|
472
|
+
},
|
|
473
|
+
updatePageView: true
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
describe('when handling events', function () {
|
|
479
|
+
function performStandardAuction({
|
|
480
|
+
gptEvents = [gptSlotRenderEnded0],
|
|
481
|
+
auctionId = MOCK.AUCTION_INIT.auctionId,
|
|
482
|
+
eventDelay = rubiConf.analyticsEventDelay,
|
|
483
|
+
sendBidWon = true
|
|
484
|
+
} = {}) {
|
|
485
|
+
events.emit(AUCTION_INIT, { ...MOCK.AUCTION_INIT, auctionId });
|
|
486
|
+
events.emit(BID_REQUESTED, { ...MOCK.BID_REQUESTED, auctionId });
|
|
487
|
+
events.emit(BID_RESPONSE, { ...MOCK.BID_RESPONSE, auctionId });
|
|
488
|
+
events.emit(BIDDER_DONE, { ...MOCK.BIDDER_DONE, auctionId });
|
|
489
|
+
events.emit(AUCTION_END, { ...MOCK.AUCTION_END, auctionId });
|
|
490
|
+
|
|
491
|
+
if (gptEvents && gptEvents.length) {
|
|
492
|
+
gptEvents.forEach(gptEvent => mockGpt.emitEvent(gptEvent.eventName, gptEvent.params));
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (sendBidWon) {
|
|
496
|
+
events.emit(BID_WON, { ...MOCK.BID_WON, auctionId });
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (eventDelay > 0) {
|
|
500
|
+
clock.tick(eventDelay);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
beforeEach(function () {
|
|
505
|
+
magniteAdapter.enableAnalytics({
|
|
506
|
+
options: {
|
|
507
|
+
endpoint: '//localhost:9999/event',
|
|
508
|
+
accountId: 1001
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
config.setConfig({ rubicon: { updatePageView: true } });
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
it('should build a batched message from prebid events', function () {
|
|
515
|
+
performStandardAuction();
|
|
516
|
+
|
|
517
|
+
expect(server.requests.length).to.equal(1);
|
|
518
|
+
let request = server.requests[0];
|
|
519
|
+
|
|
520
|
+
expect(request.url).to.equal('//localhost:9999/event');
|
|
521
|
+
|
|
522
|
+
let message = JSON.parse(request.requestBody);
|
|
523
|
+
|
|
524
|
+
expect(message).to.deep.equal(ANALYTICS_MESSAGE);
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
it('should pass along bidderOrder correctly', function () {
|
|
528
|
+
const auctionInit = utils.deepClone(MOCK.AUCTION_INIT);
|
|
529
|
+
|
|
530
|
+
auctionInit.bidderRequests = auctionInit.bidderRequests.concat([
|
|
531
|
+
{ bidderCode: 'pubmatic' },
|
|
532
|
+
{ bidderCode: 'ix' },
|
|
533
|
+
{ bidderCode: 'appnexus' }
|
|
534
|
+
])
|
|
535
|
+
|
|
536
|
+
events.emit(AUCTION_INIT, auctionInit);
|
|
537
|
+
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
|
|
538
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
539
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
540
|
+
clock.tick(rubiConf.analyticsBatchTimeout + 1000);
|
|
541
|
+
|
|
542
|
+
let message = JSON.parse(server.requests[0].requestBody);
|
|
543
|
+
expect(message.auctions[0].bidderOrder).to.deep.equal([
|
|
544
|
+
'rubicon',
|
|
545
|
+
'pubmatic',
|
|
546
|
+
'ix',
|
|
547
|
+
'appnexus'
|
|
548
|
+
]);
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
it('should pass along user ids', function () {
|
|
552
|
+
let auctionInit = utils.deepClone(MOCK.AUCTION_INIT);
|
|
553
|
+
auctionInit.bidderRequests[0].bids[0].userId = {
|
|
554
|
+
criteoId: 'sadfe4334',
|
|
555
|
+
lotamePanoramaId: 'asdf3gf4eg',
|
|
556
|
+
pubcid: 'dsfa4545-svgdfs5',
|
|
557
|
+
sharedId: { id1: 'asdf', id2: 'sadf4344' }
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
events.emit(AUCTION_INIT, auctionInit);
|
|
561
|
+
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
|
|
562
|
+
events.emit(BID_RESPONSE, MOCK.BID_RESPONSE);
|
|
563
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
564
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
565
|
+
clock.tick(rubiConf.analyticsBatchTimeout + 1000);
|
|
566
|
+
|
|
567
|
+
let message = JSON.parse(server.requests[0].requestBody);
|
|
568
|
+
|
|
569
|
+
expect(message.auctions[0].user).to.deep.equal({
|
|
570
|
+
ids: [
|
|
571
|
+
{ provider: 'criteoId', 'hasId': true },
|
|
572
|
+
{ provider: 'lotamePanoramaId', 'hasId': true },
|
|
573
|
+
{ provider: 'pubcid', 'hasId': true },
|
|
574
|
+
{ provider: 'sharedId', 'hasId': true },
|
|
575
|
+
]
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
// A-Domain tests
|
|
580
|
+
[
|
|
581
|
+
{ input: ['magnite.com'], expected: ['magnite.com'] },
|
|
582
|
+
{ input: ['magnite.com', 'prebid.org'], expected: ['magnite.com', 'prebid.org'] },
|
|
583
|
+
{ input: [123, 'prebid.org', false, true, [], 'magnite.com', {}], expected: ['prebid.org', 'magnite.com'] },
|
|
584
|
+
{ input: 'not array', expected: undefined },
|
|
585
|
+
{ input: [], expected: undefined },
|
|
586
|
+
].forEach((test, index) => {
|
|
587
|
+
it(`should handle adomain correctly - #${index + 1}`, function () {
|
|
588
|
+
events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
|
|
589
|
+
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
|
|
590
|
+
|
|
591
|
+
let bidResponse = utils.deepClone(MOCK.BID_RESPONSE);
|
|
592
|
+
bidResponse.meta = {
|
|
593
|
+
advertiserDomains: test.input
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
events.emit(BID_RESPONSE, bidResponse);
|
|
597
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
598
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
599
|
+
events.emit(BID_WON, MOCK.BID_WON);
|
|
600
|
+
clock.tick(rubiConf.analyticsBatchTimeout + 1000);
|
|
601
|
+
|
|
602
|
+
let message = JSON.parse(server.requests[0].requestBody);
|
|
603
|
+
expect(message.auctions[0].adUnits[0].bids[0].bidResponse.adomains).to.deep.equal(test.expected);
|
|
604
|
+
});
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
describe('with session handling', function () {
|
|
608
|
+
const expectedPvid = STUBBED_UUID.slice(0, 8);
|
|
609
|
+
beforeEach(function () {
|
|
610
|
+
config.setConfig({ rubicon: { updatePageView: true } });
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
it('should not log any session data if local storage is not enabled', function () {
|
|
614
|
+
localStorageIsEnabledStub.returns(false);
|
|
615
|
+
|
|
616
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
617
|
+
delete expectedMessage.session;
|
|
618
|
+
delete expectedMessage.fpkvs;
|
|
619
|
+
|
|
620
|
+
performStandardAuction();
|
|
621
|
+
|
|
622
|
+
expect(server.requests.length).to.equal(1);
|
|
623
|
+
let request = server.requests[0];
|
|
624
|
+
|
|
625
|
+
expect(request.url).to.equal('//localhost:9999/event');
|
|
626
|
+
|
|
627
|
+
let message = JSON.parse(request.requestBody);
|
|
628
|
+
|
|
629
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
it('should should pass along custom rubicon kv and pvid when defined', function () {
|
|
633
|
+
config.setConfig({
|
|
634
|
+
rubicon: {
|
|
635
|
+
fpkvs: {
|
|
636
|
+
source: 'fb',
|
|
637
|
+
link: 'email'
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
performStandardAuction();
|
|
642
|
+
expect(server.requests.length).to.equal(1);
|
|
643
|
+
let request = server.requests[0];
|
|
644
|
+
let message = JSON.parse(request.requestBody);
|
|
645
|
+
|
|
646
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
647
|
+
expectedMessage.session.pvid = STUBBED_UUID.slice(0, 8);
|
|
648
|
+
expectedMessage.fpkvs = [
|
|
649
|
+
{ key: 'source', value: 'fb' },
|
|
650
|
+
{ key: 'link', value: 'email' }
|
|
651
|
+
]
|
|
652
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
it('should convert kvs to strings before sending', function () {
|
|
656
|
+
config.setConfig({
|
|
657
|
+
rubicon: {
|
|
658
|
+
fpkvs: {
|
|
659
|
+
number: 24,
|
|
660
|
+
boolean: false,
|
|
661
|
+
string: 'hello',
|
|
662
|
+
array: ['one', 2, 'three'],
|
|
663
|
+
object: { one: 'two' }
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
performStandardAuction();
|
|
668
|
+
expect(server.requests.length).to.equal(1);
|
|
669
|
+
let request = server.requests[0];
|
|
670
|
+
let message = JSON.parse(request.requestBody);
|
|
671
|
+
|
|
672
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
673
|
+
expectedMessage.session.pvid = STUBBED_UUID.slice(0, 8);
|
|
674
|
+
expectedMessage.fpkvs = [
|
|
675
|
+
{ key: 'number', value: '24' },
|
|
676
|
+
{ key: 'boolean', value: 'false' },
|
|
677
|
+
{ key: 'string', value: 'hello' },
|
|
678
|
+
{ key: 'array', value: 'one,2,three' },
|
|
679
|
+
{ key: 'object', value: '[object Object]' }
|
|
680
|
+
]
|
|
681
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
it('should use the query utm param rubicon kv value and pass updated kv and pvid when defined', function () {
|
|
685
|
+
sandbox.stub(utils, 'getWindowLocation').returns({ 'search': '?utm_source=other', 'pbjs_debug': 'true' });
|
|
686
|
+
|
|
687
|
+
config.setConfig({
|
|
688
|
+
rubicon: {
|
|
689
|
+
fpkvs: {
|
|
690
|
+
source: 'fb',
|
|
691
|
+
link: 'email'
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
performStandardAuction();
|
|
696
|
+
expect(server.requests.length).to.equal(1);
|
|
697
|
+
let request = server.requests[0];
|
|
698
|
+
let message = JSON.parse(request.requestBody);
|
|
699
|
+
|
|
700
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
701
|
+
expectedMessage.session.pvid = STUBBED_UUID.slice(0, 8);
|
|
702
|
+
expectedMessage.fpkvs = [
|
|
703
|
+
{ key: 'source', value: 'other' },
|
|
704
|
+
{ key: 'link', value: 'email' }
|
|
705
|
+
]
|
|
706
|
+
|
|
707
|
+
message.fpkvs.sort((left, right) => left.key < right.key);
|
|
708
|
+
expectedMessage.fpkvs.sort((left, right) => left.key < right.key);
|
|
709
|
+
|
|
710
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
it('should pick up existing localStorage and use its values', function () {
|
|
714
|
+
// set some localStorage
|
|
715
|
+
let inputlocalStorage = {
|
|
716
|
+
id: '987654',
|
|
717
|
+
start: 1519767017881, // 15 mins before "now"
|
|
718
|
+
expires: 1519767039481, // six hours later
|
|
719
|
+
lastSeen: 1519766113781,
|
|
720
|
+
fpkvs: { source: 'tw' }
|
|
721
|
+
};
|
|
722
|
+
getDataFromLocalStorageStub.withArgs('mgniSession').returns(btoa(JSON.stringify(inputlocalStorage)));
|
|
723
|
+
|
|
724
|
+
config.setConfig({
|
|
725
|
+
rubicon: {
|
|
726
|
+
fpkvs: {
|
|
727
|
+
link: 'email' // should merge this with what is in the localStorage!
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
performStandardAuction();
|
|
732
|
+
expect(server.requests.length).to.equal(1);
|
|
733
|
+
let request = server.requests[0];
|
|
734
|
+
let message = JSON.parse(request.requestBody);
|
|
735
|
+
|
|
736
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
737
|
+
expectedMessage.session = {
|
|
738
|
+
id: '987654',
|
|
739
|
+
start: 1519767017881,
|
|
740
|
+
expires: 1519767039481,
|
|
741
|
+
pvid: expectedPvid
|
|
742
|
+
}
|
|
743
|
+
expectedMessage.fpkvs = [
|
|
744
|
+
{ key: 'source', value: 'tw' },
|
|
745
|
+
{ key: 'link', value: 'email' }
|
|
746
|
+
]
|
|
747
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
748
|
+
|
|
749
|
+
let calledWith;
|
|
750
|
+
try {
|
|
751
|
+
calledWith = JSON.parse(atob(setDataInLocalStorageStub.getCall(0).args[1]));
|
|
752
|
+
} catch (e) {
|
|
753
|
+
calledWith = {};
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
expect(calledWith).to.deep.equal({
|
|
757
|
+
id: '987654', // should have stayed same
|
|
758
|
+
start: 1519767017881, // should have stayed same
|
|
759
|
+
expires: 1519767039481, // should have stayed same
|
|
760
|
+
lastSeen: 1519767013781, // lastSeen updated to our auction init time
|
|
761
|
+
fpkvs: { source: 'tw', link: 'email' }, // link merged in
|
|
762
|
+
pvid: expectedPvid // new pvid stored
|
|
763
|
+
});
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
it('should overwrite matching localstorge value and use its remaining values', function () {
|
|
767
|
+
sandbox.stub(utils, 'getWindowLocation').returns({ 'search': '?utm_source=fb&utm_click=dog' });
|
|
768
|
+
|
|
769
|
+
// set some localStorage
|
|
770
|
+
let inputlocalStorage = {
|
|
771
|
+
id: '987654',
|
|
772
|
+
start: 1519766113781, // 15 mins before "now"
|
|
773
|
+
expires: 1519787713781, // six hours later
|
|
774
|
+
lastSeen: 1519766113781,
|
|
775
|
+
fpkvs: { source: 'tw', link: 'email' }
|
|
776
|
+
};
|
|
777
|
+
getDataFromLocalStorageStub.withArgs('mgniSession').returns(btoa(JSON.stringify(inputlocalStorage)));
|
|
778
|
+
|
|
779
|
+
config.setConfig({
|
|
780
|
+
rubicon: {
|
|
781
|
+
fpkvs: {
|
|
782
|
+
link: 'email' // should merge this with what is in the localStorage!
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
performStandardAuction();
|
|
787
|
+
expect(server.requests.length).to.equal(1);
|
|
788
|
+
let request = server.requests[0];
|
|
789
|
+
let message = JSON.parse(request.requestBody);
|
|
790
|
+
|
|
791
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
792
|
+
expectedMessage.session = {
|
|
793
|
+
id: '987654',
|
|
794
|
+
start: 1519766113781,
|
|
795
|
+
expires: 1519787713781,
|
|
796
|
+
pvid: expectedPvid
|
|
797
|
+
}
|
|
798
|
+
expectedMessage.fpkvs = [
|
|
799
|
+
{ key: 'source', value: 'fb' },
|
|
800
|
+
{ key: 'link', value: 'email' },
|
|
801
|
+
{ key: 'click', value: 'dog' }
|
|
802
|
+
]
|
|
803
|
+
|
|
804
|
+
message.fpkvs.sort((left, right) => left.key < right.key);
|
|
805
|
+
expectedMessage.fpkvs.sort((left, right) => left.key < right.key);
|
|
806
|
+
|
|
807
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
808
|
+
|
|
809
|
+
let calledWith;
|
|
810
|
+
try {
|
|
811
|
+
calledWith = JSON.parse(atob(setDataInLocalStorageStub.getCall(0).args[1]));
|
|
812
|
+
} catch (e) {
|
|
813
|
+
calledWith = {};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
expect(calledWith).to.deep.equal({
|
|
817
|
+
id: '987654', // should have stayed same
|
|
818
|
+
start: 1519766113781, // should have stayed same
|
|
819
|
+
expires: 1519787713781, // should have stayed same
|
|
820
|
+
lastSeen: 1519767013781, // lastSeen updated to our auction init time
|
|
821
|
+
fpkvs: { source: 'fb', link: 'email', click: 'dog' }, // link merged in
|
|
822
|
+
pvid: expectedPvid // new pvid stored
|
|
823
|
+
});
|
|
824
|
+
});
|
|
825
|
+
|
|
826
|
+
it('should throw out session if lastSeen > 30 mins ago and create new one', function () {
|
|
827
|
+
// set some localStorage
|
|
828
|
+
let inputlocalStorage = {
|
|
829
|
+
id: '987654',
|
|
830
|
+
start: 1519764313781, // 45 mins before "now"
|
|
831
|
+
expires: 1519785913781, // six hours later
|
|
832
|
+
lastSeen: 1519764313781, // 45 mins before "now"
|
|
833
|
+
fpkvs: { source: 'tw' }
|
|
834
|
+
};
|
|
835
|
+
getDataFromLocalStorageStub.withArgs('mgniSession').returns(btoa(JSON.stringify(inputlocalStorage)));
|
|
836
|
+
|
|
837
|
+
config.setConfig({
|
|
838
|
+
rubicon: {
|
|
839
|
+
fpkvs: {
|
|
840
|
+
link: 'email' // should merge this with what is in the localStorage!
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
performStandardAuction();
|
|
846
|
+
expect(server.requests.length).to.equal(1);
|
|
847
|
+
let request = server.requests[0];
|
|
848
|
+
let message = JSON.parse(request.requestBody);
|
|
849
|
+
|
|
850
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
851
|
+
// session should match what is already in ANALYTICS_MESSAGE, just need to add pvid
|
|
852
|
+
expectedMessage.session.pvid = expectedPvid;
|
|
853
|
+
|
|
854
|
+
// the saved fpkvs should have been thrown out since session expired
|
|
855
|
+
expectedMessage.fpkvs = [
|
|
856
|
+
{ key: 'link', value: 'email' }
|
|
857
|
+
]
|
|
858
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
859
|
+
|
|
860
|
+
let calledWith;
|
|
861
|
+
try {
|
|
862
|
+
calledWith = JSON.parse(atob(setDataInLocalStorageStub.getCall(0).args[1]));
|
|
863
|
+
} catch (e) {
|
|
864
|
+
calledWith = {};
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
expect(calledWith).to.deep.equal({
|
|
868
|
+
id: STUBBED_UUID, // should have generated not used input
|
|
869
|
+
start: 1519767013781, // updated to whenever auction init started
|
|
870
|
+
expires: 1519788613781, // 6 hours after start
|
|
871
|
+
lastSeen: 1519767013781, // lastSeen updated to our "now"
|
|
872
|
+
fpkvs: { link: 'email' }, // link merged in
|
|
873
|
+
pvid: expectedPvid // new pvid stored
|
|
874
|
+
});
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
it('should throw out session if past expires time and create new one', function () {
|
|
878
|
+
// set some localStorage
|
|
879
|
+
let inputlocalStorage = {
|
|
880
|
+
id: '987654',
|
|
881
|
+
start: 1519745353781, // 6 hours before "expires"
|
|
882
|
+
expires: 1519766953781, // little more than six hours ago
|
|
883
|
+
lastSeen: 1519767008781, // 5 seconds ago
|
|
884
|
+
fpkvs: { source: 'tw' }
|
|
885
|
+
};
|
|
886
|
+
getDataFromLocalStorageStub.withArgs('mgniSession').returns(btoa(JSON.stringify(inputlocalStorage)));
|
|
887
|
+
|
|
888
|
+
config.setConfig({
|
|
889
|
+
rubicon: {
|
|
890
|
+
fpkvs: {
|
|
891
|
+
link: 'email' // should merge this with what is in the localStorage!
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
});
|
|
895
|
+
|
|
896
|
+
performStandardAuction();
|
|
897
|
+
expect(server.requests.length).to.equal(1);
|
|
898
|
+
let request = server.requests[0];
|
|
899
|
+
let message = JSON.parse(request.requestBody);
|
|
900
|
+
|
|
901
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
902
|
+
// session should match what is already in ANALYTICS_MESSAGE, just need to add pvid
|
|
903
|
+
expectedMessage.session.pvid = expectedPvid;
|
|
904
|
+
|
|
905
|
+
// the saved fpkvs should have been thrown out since session expired
|
|
906
|
+
expectedMessage.fpkvs = [
|
|
907
|
+
{ key: 'link', value: 'email' }
|
|
908
|
+
]
|
|
909
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
910
|
+
|
|
911
|
+
let calledWith;
|
|
912
|
+
try {
|
|
913
|
+
calledWith = JSON.parse(atob(setDataInLocalStorageStub.getCall(0).args[1]));
|
|
914
|
+
} catch (e) {
|
|
915
|
+
calledWith = {};
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
expect(calledWith).to.deep.equal({
|
|
919
|
+
id: STUBBED_UUID, // should have generated and not used same one
|
|
920
|
+
start: 1519767013781, // updated to whenever auction init started
|
|
921
|
+
expires: 1519788613781, // 6 hours after start
|
|
922
|
+
lastSeen: 1519767013781, // lastSeen updated to our "now"
|
|
923
|
+
fpkvs: { link: 'email' }, // link merged in
|
|
924
|
+
pvid: expectedPvid // new pvid stored
|
|
925
|
+
});
|
|
926
|
+
});
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
it('should send gam data if adunit has elementid ortb2 fields', function () {
|
|
930
|
+
// update auction init mock to have the elementids in the adunit
|
|
931
|
+
// and change adUnitCode to be hashes
|
|
932
|
+
let auctionInit = utils.deepClone(MOCK.AUCTION_INIT);
|
|
933
|
+
auctionInit.adUnits[0].ortb2Imp.ext.data.elementid = [gptSlot0.getSlotElementId()];
|
|
934
|
+
auctionInit.adUnits[0].code = '1a2b3c4d';
|
|
935
|
+
|
|
936
|
+
// bid request
|
|
937
|
+
let bidRequested = utils.deepClone(MOCK.BID_REQUESTED);
|
|
938
|
+
bidRequested.bids[0].adUnitCode = '1a2b3c4d';
|
|
939
|
+
|
|
940
|
+
// bid response
|
|
941
|
+
let bidResponse = utils.deepClone(MOCK.BID_RESPONSE);
|
|
942
|
+
bidResponse.adUnitCode = '1a2b3c4d';
|
|
943
|
+
|
|
944
|
+
// bidder done
|
|
945
|
+
let bidderDone = utils.deepClone(MOCK.BIDDER_DONE);
|
|
946
|
+
bidderDone.bids[0].adUnitCode = '1a2b3c4d';
|
|
947
|
+
|
|
948
|
+
// bidder done
|
|
949
|
+
let bidWon = utils.deepClone(MOCK.BID_WON);
|
|
950
|
+
bidWon.adUnitCode = '1a2b3c4d';
|
|
951
|
+
|
|
952
|
+
// Run auction
|
|
953
|
+
events.emit(AUCTION_INIT, auctionInit);
|
|
954
|
+
events.emit(BID_REQUESTED, bidRequested);
|
|
955
|
+
events.emit(BID_RESPONSE, bidResponse);
|
|
956
|
+
events.emit(BIDDER_DONE, bidderDone);
|
|
957
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
958
|
+
|
|
959
|
+
// emmit gpt events and bidWon
|
|
960
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
961
|
+
|
|
962
|
+
events.emit(BID_WON, bidWon);
|
|
963
|
+
|
|
964
|
+
// tick the event delay time plus processing delay
|
|
965
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
966
|
+
|
|
967
|
+
expect(server.requests.length).to.equal(1);
|
|
968
|
+
let request = server.requests[0];
|
|
969
|
+
let message = JSON.parse(request.requestBody);
|
|
970
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
971
|
+
|
|
972
|
+
// new adUnitCodes in payload
|
|
973
|
+
expectedMessage.auctions[0].adUnits[0].adUnitCode = '1a2b3c4d';
|
|
974
|
+
expectedMessage.bidsWon[0].adUnitCode = '1a2b3c4d';
|
|
975
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
976
|
+
});
|
|
977
|
+
|
|
978
|
+
it('should delay the event call depending on analyticsEventDelay config', function () {
|
|
979
|
+
config.setConfig({
|
|
980
|
+
rubicon: {
|
|
981
|
+
analyticsEventDelay: 2000
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
performStandardAuction({ eventDelay: 0 });
|
|
985
|
+
|
|
986
|
+
// Should not be sent until delay
|
|
987
|
+
expect(server.requests.length).to.equal(0);
|
|
988
|
+
|
|
989
|
+
// tick the clock and it should fire
|
|
990
|
+
clock.tick(2000);
|
|
991
|
+
|
|
992
|
+
expect(server.requests.length).to.equal(1);
|
|
993
|
+
let request = server.requests[0];
|
|
994
|
+
let message = JSON.parse(request.requestBody);
|
|
995
|
+
|
|
996
|
+
// The timestamps should be changed from the default by (set eventDelay (2000) - eventDelay default (500))
|
|
997
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
998
|
+
expectedMessage.timestamps.eventTime = expectedMessage.timestamps.eventTime + 1500;
|
|
999
|
+
expectedMessage.timestamps.timeSincePageLoad = expectedMessage.timestamps.timeSincePageLoad + 1500;
|
|
1000
|
+
|
|
1001
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
['seatBidId', 'pbsBidId'].forEach(pbsParam => {
|
|
1005
|
+
it(`should overwrite prebid bidId with incoming PBS ${pbsParam}`, function () {
|
|
1006
|
+
// bid response
|
|
1007
|
+
let seatBidResponse = utils.deepClone(MOCK.BID_RESPONSE);
|
|
1008
|
+
seatBidResponse[pbsParam] = 'abc-123-do-re-me';
|
|
1009
|
+
|
|
1010
|
+
// Run auction
|
|
1011
|
+
events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
|
|
1012
|
+
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
|
|
1013
|
+
events.emit(BID_RESPONSE, seatBidResponse);
|
|
1014
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
1015
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
1016
|
+
|
|
1017
|
+
// emmit gpt events and bidWon
|
|
1018
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1019
|
+
|
|
1020
|
+
events.emit(BID_WON, MOCK.BID_WON);
|
|
1021
|
+
|
|
1022
|
+
// tick the event delay time plus processing delay
|
|
1023
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
1024
|
+
|
|
1025
|
+
expect(server.requests.length).to.equal(1);
|
|
1026
|
+
let request = server.requests[0];
|
|
1027
|
+
let message = JSON.parse(request.requestBody);
|
|
1028
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1029
|
+
|
|
1030
|
+
// new adUnitCodes in payload
|
|
1031
|
+
expectedMessage.auctions[0].adUnits[0].bids[0].bidId = 'abc-123-do-re-me';
|
|
1032
|
+
expectedMessage.auctions[0].adUnits[0].bids[0].oldBidId = '23fcd8cf4bf0d7';
|
|
1033
|
+
expectedMessage.bidsWon[0].bidId = 'abc-123-do-re-me';
|
|
1034
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
1035
|
+
});
|
|
1036
|
+
});
|
|
1037
|
+
|
|
1038
|
+
[0, '0'].forEach(pbsParam => {
|
|
1039
|
+
it(`should generate new bidId if incoming pbsBidId is ${pbsParam}`, function () {
|
|
1040
|
+
// bid response
|
|
1041
|
+
let seatBidResponse = utils.deepClone(MOCK.BID_RESPONSE);
|
|
1042
|
+
seatBidResponse.pbsBidId = pbsParam;
|
|
1043
|
+
|
|
1044
|
+
// Run auction
|
|
1045
|
+
events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
|
|
1046
|
+
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
|
|
1047
|
+
events.emit(BID_RESPONSE, seatBidResponse);
|
|
1048
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
1049
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
1050
|
+
|
|
1051
|
+
// emmit gpt events and bidWon
|
|
1052
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1053
|
+
|
|
1054
|
+
events.emit(BID_WON, MOCK.BID_WON);
|
|
1055
|
+
|
|
1056
|
+
// tick the event delay time plus processing delay
|
|
1057
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
1058
|
+
|
|
1059
|
+
expect(server.requests.length).to.equal(1);
|
|
1060
|
+
let request = server.requests[0];
|
|
1061
|
+
let message = JSON.parse(request.requestBody);
|
|
1062
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1063
|
+
|
|
1064
|
+
// new adUnitCodes in payload
|
|
1065
|
+
expectedMessage.auctions[0].adUnits[0].bids[0].bidId = STUBBED_UUID;
|
|
1066
|
+
expectedMessage.auctions[0].adUnits[0].bids[0].oldBidId = '23fcd8cf4bf0d7';
|
|
1067
|
+
expectedMessage.bidsWon[0].bidId = STUBBED_UUID;
|
|
1068
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
1069
|
+
});
|
|
1070
|
+
});
|
|
1071
|
+
|
|
1072
|
+
it(`should pick highest cpm if more than one bidResponse comes in`, function () {
|
|
1073
|
+
// Run auction
|
|
1074
|
+
events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
|
|
1075
|
+
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
|
|
1076
|
+
|
|
1077
|
+
const bidResp = utils.deepClone(MOCK.BID_RESPONSE);
|
|
1078
|
+
|
|
1079
|
+
// emit some bid responses
|
|
1080
|
+
[1.0, 5.5, 0.1].forEach(cpm => {
|
|
1081
|
+
events.emit(BID_RESPONSE, { ...bidResp, cpm });
|
|
1082
|
+
});
|
|
1083
|
+
|
|
1084
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
1085
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
1086
|
+
|
|
1087
|
+
// emmit gpt events and bidWon
|
|
1088
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1089
|
+
|
|
1090
|
+
events.emit(BID_WON, MOCK.BID_WON);
|
|
1091
|
+
|
|
1092
|
+
// tick the event delay time plus processing delay
|
|
1093
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
1094
|
+
|
|
1095
|
+
expect(server.requests.length).to.equal(1);
|
|
1096
|
+
let request = server.requests[0];
|
|
1097
|
+
let message = JSON.parse(request.requestBody);
|
|
1098
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1099
|
+
|
|
1100
|
+
// highest cpm in payload
|
|
1101
|
+
expectedMessage.auctions[0].adUnits[0].bids[0].bidResponse.bidPriceUSD = 5.5;
|
|
1102
|
+
expectedMessage.bidsWon[0].bidResponse.bidPriceUSD = 5.5;
|
|
1103
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
1104
|
+
});
|
|
1105
|
+
|
|
1106
|
+
it('should send bid won events by themselves if emitted after auction pba payload is sent', function () {
|
|
1107
|
+
performStandardAuction({ sendBidWon: false });
|
|
1108
|
+
|
|
1109
|
+
// Now send bidWon
|
|
1110
|
+
events.emit(BID_WON, MOCK.BID_WON);
|
|
1111
|
+
|
|
1112
|
+
// tick the event delay time plus processing delay
|
|
1113
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
1114
|
+
|
|
1115
|
+
// should see two server requests
|
|
1116
|
+
expect(server.requests.length).to.equal(2);
|
|
1117
|
+
|
|
1118
|
+
// first is normal analytics event without bidWon
|
|
1119
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1120
|
+
delete expectedMessage.bidsWon;
|
|
1121
|
+
|
|
1122
|
+
let message = JSON.parse(server.requests[0].requestBody);
|
|
1123
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
1124
|
+
|
|
1125
|
+
// second is just a bidWon (remove gam and auction event)
|
|
1126
|
+
message = JSON.parse(server.requests[1].requestBody);
|
|
1127
|
+
|
|
1128
|
+
let expectedMessage2 = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1129
|
+
delete expectedMessage2.auctions;
|
|
1130
|
+
delete expectedMessage2.gamRenders;
|
|
1131
|
+
|
|
1132
|
+
// second event should be event delay time after first one
|
|
1133
|
+
expectedMessage2.timestamps.eventTime = expectedMessage.timestamps.eventTime + rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay;
|
|
1134
|
+
expectedMessage2.timestamps.timeSincePageLoad = expectedMessage.timestamps.timeSincePageLoad + rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay;
|
|
1135
|
+
|
|
1136
|
+
// trigger is `batched-bidsWon`
|
|
1137
|
+
expectedMessage2.trigger = 'batched-bidsWon';
|
|
1138
|
+
|
|
1139
|
+
expect(message).to.deep.equal(expectedMessage2);
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1142
|
+
it('should send gamRender events by themselves if emitted after auction pba payload is sent', function () {
|
|
1143
|
+
// dont send extra events and hit the batch timeout
|
|
1144
|
+
performStandardAuction({ gptEvents: [], sendBidWon: false, eventDelay: rubiConf.analyticsBatchTimeout });
|
|
1145
|
+
|
|
1146
|
+
// Now send gptEvent and bidWon
|
|
1147
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1148
|
+
events.emit(BID_WON, MOCK.BID_WON);
|
|
1149
|
+
|
|
1150
|
+
// tick the event delay time plus processing delay
|
|
1151
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
1152
|
+
|
|
1153
|
+
// should see two server requests
|
|
1154
|
+
expect(server.requests.length).to.equal(2);
|
|
1155
|
+
|
|
1156
|
+
// first is normal analytics event without bidWon or gam
|
|
1157
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1158
|
+
delete expectedMessage.bidsWon;
|
|
1159
|
+
delete expectedMessage.gamRenders;
|
|
1160
|
+
|
|
1161
|
+
// timing changes a bit -> timestamps should be batchTimeout - event delay later
|
|
1162
|
+
const expectedExtraTime = rubiConf.analyticsBatchTimeout - rubiConf.analyticsEventDelay;
|
|
1163
|
+
expectedMessage.timestamps.eventTime = expectedMessage.timestamps.eventTime + expectedExtraTime;
|
|
1164
|
+
expectedMessage.timestamps.timeSincePageLoad = expectedMessage.timestamps.timeSincePageLoad + expectedExtraTime;
|
|
1165
|
+
|
|
1166
|
+
// since gam event did not fire, the trigger should be auctionEnd
|
|
1167
|
+
expectedMessage.trigger = 'auctionEnd';
|
|
1168
|
+
|
|
1169
|
+
let message = JSON.parse(server.requests[0].requestBody);
|
|
1170
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
1171
|
+
|
|
1172
|
+
// second is gam and bid won
|
|
1173
|
+
message = JSON.parse(server.requests[1].requestBody);
|
|
1174
|
+
|
|
1175
|
+
let expectedMessage2 = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1176
|
+
// second event should be event delay time after first one
|
|
1177
|
+
expectedMessage2.timestamps.eventTime = expectedMessage.timestamps.eventTime + rubiConf.analyticsEventDelay;
|
|
1178
|
+
expectedMessage2.timestamps.timeSincePageLoad = expectedMessage.timestamps.timeSincePageLoad + rubiConf.analyticsEventDelay;
|
|
1179
|
+
delete expectedMessage2.auctions;
|
|
1180
|
+
|
|
1181
|
+
// trigger should be `batched-bidsWon-gamRender`
|
|
1182
|
+
expectedMessage2.trigger = 'batched-bidsWon-gamRenders';
|
|
1183
|
+
|
|
1184
|
+
expect(message).to.deep.equal(expectedMessage2);
|
|
1185
|
+
});
|
|
1186
|
+
|
|
1187
|
+
it('should send all events solo if delay and batch set to 0', function () {
|
|
1188
|
+
const defaultDelay = rubiConf.analyticsEventDelay;
|
|
1189
|
+
config.setConfig({
|
|
1190
|
+
rubicon: {
|
|
1191
|
+
analyticsBatchTimeout: 0,
|
|
1192
|
+
analyticsEventDelay: 0,
|
|
1193
|
+
analyticsProcessDelay: 0
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
1196
|
+
|
|
1197
|
+
performStandardAuction({ eventDelay: 0 });
|
|
1198
|
+
|
|
1199
|
+
// should be 3 requests
|
|
1200
|
+
expect(server.requests.length).to.equal(3);
|
|
1201
|
+
|
|
1202
|
+
// grab expected 3 requests from default message
|
|
1203
|
+
let { auctions, gamRenders, bidsWon, ...rest } = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1204
|
+
|
|
1205
|
+
// rest of payload should have timestamps changed to be - default eventDelay since we changed it to 0
|
|
1206
|
+
rest.timestamps.eventTime = rest.timestamps.eventTime - defaultDelay;
|
|
1207
|
+
rest.timestamps.timeSincePageLoad = rest.timestamps.timeSincePageLoad - defaultDelay;
|
|
1208
|
+
|
|
1209
|
+
// loop through and assert events fired in correct order with correct stuff
|
|
1210
|
+
[
|
|
1211
|
+
{ expectedMessage: { auctions, ...rest }, trigger: 'solo-auction' },
|
|
1212
|
+
{ expectedMessage: { gamRenders, ...rest }, trigger: 'solo-gam' },
|
|
1213
|
+
{ expectedMessage: { bidsWon, ...rest }, trigger: 'solo-bidWon' },
|
|
1214
|
+
].forEach((stuff, requestNum) => {
|
|
1215
|
+
let message = JSON.parse(server.requests[requestNum].requestBody);
|
|
1216
|
+
stuff.expectedMessage.trigger = stuff.trigger;
|
|
1217
|
+
expect(message).to.deep.equal(stuff.expectedMessage);
|
|
1218
|
+
});
|
|
1219
|
+
});
|
|
1220
|
+
|
|
1221
|
+
it(`should correctly mark bids as timed out`, function () {
|
|
1222
|
+
// Run auction (simulate bidder timed out in 1000 ms)
|
|
1223
|
+
const auctionStart = Date.now() - 1000;
|
|
1224
|
+
events.emit(AUCTION_INIT, { ...MOCK.AUCTION_INIT, timestamp: auctionStart });
|
|
1225
|
+
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
|
|
1226
|
+
|
|
1227
|
+
// emit bid timeout
|
|
1228
|
+
events.emit(BID_TIMEOUT, [
|
|
1229
|
+
{
|
|
1230
|
+
auctionId: MOCK.AUCTION_INIT.auctionId,
|
|
1231
|
+
adUnitCode: MOCK.AUCTION_INIT.adUnits[0].code,
|
|
1232
|
+
bidId: MOCK.BID_REQUESTED.bids[0].bidId,
|
|
1233
|
+
transactionId: MOCK.AUCTION_INIT.adUnits[0].transactionId,
|
|
1234
|
+
}
|
|
1235
|
+
]);
|
|
1236
|
+
|
|
1237
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
1238
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
1239
|
+
|
|
1240
|
+
// emmit gpt events and bidWon
|
|
1241
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1242
|
+
|
|
1243
|
+
// tick the event delay time plus processing delay
|
|
1244
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
1245
|
+
|
|
1246
|
+
expect(server.requests.length).to.equal(1);
|
|
1247
|
+
let request = server.requests[0];
|
|
1248
|
+
let message = JSON.parse(request.requestBody);
|
|
1249
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1250
|
+
|
|
1251
|
+
// should see error time out bid
|
|
1252
|
+
expectedMessage.auctions[0].adUnits[0].bids[0].status = 'error';
|
|
1253
|
+
expectedMessage.auctions[0].adUnits[0].bids[0].error = {
|
|
1254
|
+
code: 'timeout-error',
|
|
1255
|
+
description: 'prebid.js timeout' // will help us diff if timeout was set by PBS or PBJS
|
|
1256
|
+
};
|
|
1257
|
+
|
|
1258
|
+
// should not see bidResponse or bidsWon
|
|
1259
|
+
delete expectedMessage.auctions[0].adUnits[0].bids[0].bidResponse;
|
|
1260
|
+
delete expectedMessage.bidsWon;
|
|
1261
|
+
|
|
1262
|
+
// adunit should be marked as error
|
|
1263
|
+
expectedMessage.auctions[0].adUnits[0].status = 'error';
|
|
1264
|
+
|
|
1265
|
+
// timed out in 1000 ms
|
|
1266
|
+
expectedMessage.auctions[0].adUnits[0].bids[0].clientLatencyMillis = 1000;
|
|
1267
|
+
|
|
1268
|
+
expectedMessage.auctions[0].auctionStart = auctionStart;
|
|
1269
|
+
|
|
1270
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
1271
|
+
});
|
|
1272
|
+
|
|
1273
|
+
[
|
|
1274
|
+
{ name: 'aupname', adUnitPath: 'adUnits.0.ortb2Imp.ext.data.aupname', eventPath: 'auctions.0.adUnits.0.pattern', input: '1234/mycoolsite/*&gpt_leaderboard&deviceType=mobile' },
|
|
1275
|
+
{ name: 'gpid', adUnitPath: 'adUnits.0.ortb2Imp.ext.gpid', eventPath: 'auctions.0.adUnits.0.gpid', input: '1234/gpid/path' },
|
|
1276
|
+
{ name: 'pbadslot', adUnitPath: 'adUnits.0.ortb2Imp.ext.data.pbadslot', eventPath: 'auctions.0.adUnits.0.pbAdSlot', input: '1234/pbadslot/path' }
|
|
1277
|
+
].forEach(test => {
|
|
1278
|
+
it(`should correctly pass ${test.name}`, function () {
|
|
1279
|
+
// bid response
|
|
1280
|
+
let auctionInit = utils.deepClone(MOCK.AUCTION_INIT);
|
|
1281
|
+
utils.deepSetValue(auctionInit, test.adUnitPath, test.input);
|
|
1282
|
+
|
|
1283
|
+
// Run auction
|
|
1284
|
+
events.emit(AUCTION_INIT, auctionInit);
|
|
1285
|
+
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
|
|
1286
|
+
events.emit(BID_RESPONSE, MOCK.BID_RESPONSE);
|
|
1287
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
1288
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
1289
|
+
|
|
1290
|
+
// emmit gpt events and bidWon
|
|
1291
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1292
|
+
|
|
1293
|
+
events.emit(BID_WON, MOCK.BID_WON);
|
|
1294
|
+
|
|
1295
|
+
// tick the event delay time plus processing delay
|
|
1296
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
1297
|
+
|
|
1298
|
+
expect(server.requests.length).to.equal(1);
|
|
1299
|
+
let request = server.requests[0];
|
|
1300
|
+
let message = JSON.parse(request.requestBody);
|
|
1301
|
+
|
|
1302
|
+
// pattern in payload
|
|
1303
|
+
expect(deepAccess(message, test.eventPath)).to.equal(test.input);
|
|
1304
|
+
});
|
|
1305
|
+
});
|
|
1306
|
+
|
|
1307
|
+
it('should pass bidderDetail for multibid auctions', function () {
|
|
1308
|
+
let bidResponse = utils.deepClone(MOCK.BID_RESPONSE);
|
|
1309
|
+
bidResponse.targetingBidder = 'rubi2';
|
|
1310
|
+
bidResponse.originalRequestId = bidResponse.requestId;
|
|
1311
|
+
bidResponse.requestId = '1a2b3c4d5e6f7g8h9';
|
|
1312
|
+
|
|
1313
|
+
events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
|
|
1314
|
+
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
|
|
1315
|
+
events.emit(BID_RESPONSE, bidResponse);
|
|
1316
|
+
events.emit(BID_RESPONSE, MOCK.BID_RESPONSE);
|
|
1317
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
1318
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
1319
|
+
|
|
1320
|
+
// emmit gpt events and bidWon
|
|
1321
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1322
|
+
|
|
1323
|
+
let bidWon = utils.deepClone(MOCK.BID_WON);
|
|
1324
|
+
bidWon.bidId = bidWon.requestId = '1a2b3c4d5e6f7g8h9';
|
|
1325
|
+
bidWon.bidderDetail = 'rubi2';
|
|
1326
|
+
events.emit(BID_WON, bidWon);
|
|
1327
|
+
|
|
1328
|
+
// tick the event delay time plus processing delay
|
|
1329
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
1330
|
+
|
|
1331
|
+
expect(server.requests.length).to.equal(1);
|
|
1332
|
+
|
|
1333
|
+
let message = JSON.parse(server.requests[0].requestBody);
|
|
1334
|
+
|
|
1335
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1336
|
+
|
|
1337
|
+
// expect an extra bid added
|
|
1338
|
+
expectedMessage.auctions[0].adUnits[0].bids.push({
|
|
1339
|
+
...ANALYTICS_MESSAGE.auctions[0].adUnits[0].bids[0],
|
|
1340
|
+
bidderDetail: 'rubi2',
|
|
1341
|
+
bidId: '1a2b3c4d5e6f7g8h9'
|
|
1342
|
+
});
|
|
1343
|
+
|
|
1344
|
+
// bid won is our extra bid
|
|
1345
|
+
expectedMessage.bidsWon[0].bidderDetail = 'rubi2';
|
|
1346
|
+
expectedMessage.bidsWon[0].bidId = '1a2b3c4d5e6f7g8h9';
|
|
1347
|
+
|
|
1348
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
1349
|
+
});
|
|
1350
|
+
|
|
1351
|
+
it('should pass bidderDetail for multibid auctions', function () {
|
|
1352
|
+
// Set the rates
|
|
1353
|
+
setConfig({
|
|
1354
|
+
adServerCurrency: 'JPY',
|
|
1355
|
+
rates: {
|
|
1356
|
+
USD: {
|
|
1357
|
+
JPY: 100
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
});
|
|
1361
|
+
|
|
1362
|
+
// set our bid response to JPY
|
|
1363
|
+
let bidResponse = utils.deepClone(MOCK.BID_RESPONSE);
|
|
1364
|
+
bidResponse.currency = 'JPY';
|
|
1365
|
+
bidResponse.cpm = 100;
|
|
1366
|
+
|
|
1367
|
+
// Now add the bidResponse hook which hooks on the currenct conversion function onto the bid response
|
|
1368
|
+
let innerBid;
|
|
1369
|
+
addBidResponseHook(function (adCodeId, bid) {
|
|
1370
|
+
innerBid = bid;
|
|
1371
|
+
}, 'elementId', bidResponse);
|
|
1372
|
+
|
|
1373
|
+
// Use the rubi analytics parseBidResponse Function to get the resulting cpm from the bid response!
|
|
1374
|
+
const bidResponseObj = parseBidResponse(innerBid);
|
|
1375
|
+
expect(bidResponseObj).to.have.property('bidPriceUSD');
|
|
1376
|
+
expect(bidResponseObj.bidPriceUSD).to.equal(1.0);
|
|
1377
|
+
});
|
|
1378
|
+
|
|
1379
|
+
it('should use the integration type provided in the config instead of the default', () => {
|
|
1380
|
+
config.setConfig({
|
|
1381
|
+
rubicon: {
|
|
1382
|
+
int_type: 'testType'
|
|
1383
|
+
}
|
|
1384
|
+
})
|
|
1385
|
+
|
|
1386
|
+
performStandardAuction();
|
|
1387
|
+
|
|
1388
|
+
expect(server.requests.length).to.equal(1);
|
|
1389
|
+
const request = server.requests[0];
|
|
1390
|
+
const message = JSON.parse(request.requestBody);
|
|
1391
|
+
expect(message.integration).to.equal('testType');
|
|
1392
|
+
});
|
|
1393
|
+
|
|
1394
|
+
it('should correctly pass bid.source when is s2s', () => {
|
|
1395
|
+
// Run auction
|
|
1396
|
+
events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
|
|
1397
|
+
|
|
1398
|
+
const bidReq = utils.deepClone(MOCK.BID_REQUESTED);
|
|
1399
|
+
bidReq.bids[0].src = 's2s';
|
|
1400
|
+
|
|
1401
|
+
events.emit(BID_REQUESTED, bidReq);
|
|
1402
|
+
events.emit(BID_RESPONSE, MOCK.BID_RESPONSE);
|
|
1403
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
1404
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
1405
|
+
|
|
1406
|
+
// emmit gpt events and bidWon
|
|
1407
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1408
|
+
events.emit(BID_WON, MOCK.BID_WON);
|
|
1409
|
+
|
|
1410
|
+
// tick the event delay time plus processing delay
|
|
1411
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
1412
|
+
|
|
1413
|
+
expect(server.requests.length).to.equal(1);
|
|
1414
|
+
let request = server.requests[0];
|
|
1415
|
+
let message = JSON.parse(request.requestBody);
|
|
1416
|
+
let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE);
|
|
1417
|
+
|
|
1418
|
+
// bid source should be 'server'
|
|
1419
|
+
expectedMessage.auctions[0].adUnits[0].bids[0].source = 'server';
|
|
1420
|
+
expectedMessage.bidsWon[0].source = 'server';
|
|
1421
|
+
expect(message).to.deep.equal(expectedMessage);
|
|
1422
|
+
});
|
|
1423
|
+
|
|
1424
|
+
describe('when handling bid caching', () => {
|
|
1425
|
+
let auctionInits, bidRequests, bidResponses, bidsWon;
|
|
1426
|
+
beforeEach(function () {
|
|
1427
|
+
// set timing stuff to 0 so we clearly know when things fire
|
|
1428
|
+
config.setConfig({
|
|
1429
|
+
useBidCache: true,
|
|
1430
|
+
rubicon: {
|
|
1431
|
+
analyticsEventDelay: 0,
|
|
1432
|
+
analyticsBatchTimeout: 0,
|
|
1433
|
+
analyticsProcessDelay: 0
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
|
|
1437
|
+
// setup 3 auctions
|
|
1438
|
+
auctionInits = [
|
|
1439
|
+
{ ...MOCK.AUCTION_INIT, auctionId: 'auctionId-1', adUnits: [{ ...MOCK.AUCTION_INIT.adUnits[0], transactionId: 'tid-1' }] },
|
|
1440
|
+
{ ...MOCK.AUCTION_INIT, auctionId: 'auctionId-2', adUnits: [{ ...MOCK.AUCTION_INIT.adUnits[0], transactionId: 'tid-2' }] },
|
|
1441
|
+
{ ...MOCK.AUCTION_INIT, auctionId: 'auctionId-3', adUnits: [{ ...MOCK.AUCTION_INIT.adUnits[0], transactionId: 'tid-3' }] }
|
|
1442
|
+
];
|
|
1443
|
+
bidRequests = [
|
|
1444
|
+
{ ...MOCK.BID_REQUESTED, auctionId: 'auctionId-1', bids: [{ ...MOCK.BID_REQUESTED.bids[0], bidId: 'bidId-1', transactionId: 'tid-1' }] },
|
|
1445
|
+
{ ...MOCK.BID_REQUESTED, auctionId: 'auctionId-2', bids: [{ ...MOCK.BID_REQUESTED.bids[0], bidId: 'bidId-2', transactionId: 'tid-2' }] },
|
|
1446
|
+
{ ...MOCK.BID_REQUESTED, auctionId: 'auctionId-3', bids: [{ ...MOCK.BID_REQUESTED.bids[0], bidId: 'bidId-3', transactionId: 'tid-3' }] }
|
|
1447
|
+
];
|
|
1448
|
+
bidResponses = [
|
|
1449
|
+
{ ...MOCK.BID_RESPONSE, auctionId: 'auctionId-1', transactionId: 'tid-1', requestId: 'bidId-1' },
|
|
1450
|
+
{ ...MOCK.BID_RESPONSE, auctionId: 'auctionId-2', transactionId: 'tid-2', requestId: 'bidId-2' },
|
|
1451
|
+
{ ...MOCK.BID_RESPONSE, auctionId: 'auctionId-3', transactionId: 'tid-3', requestId: 'bidId-3' },
|
|
1452
|
+
];
|
|
1453
|
+
bidsWon = [
|
|
1454
|
+
{ ...MOCK.BID_WON, auctionId: 'auctionId-1', transactionId: 'tid-1', bidId: 'bidId-1', requestId: 'bidId-1' },
|
|
1455
|
+
{ ...MOCK.BID_WON, auctionId: 'auctionId-2', transactionId: 'tid-2', bidId: 'bidId-2', requestId: 'bidId-2' },
|
|
1456
|
+
{ ...MOCK.BID_WON, auctionId: 'auctionId-3', transactionId: 'tid-3', bidId: 'bidId-3', requestId: 'bidId-3' },
|
|
1457
|
+
];
|
|
1458
|
+
});
|
|
1459
|
+
function runBasicAuction(auctionNum) {
|
|
1460
|
+
events.emit(AUCTION_INIT, auctionInits[auctionNum]);
|
|
1461
|
+
events.emit(BID_REQUESTED, bidRequests[auctionNum]);
|
|
1462
|
+
events.emit(BID_RESPONSE, bidResponses[auctionNum]);
|
|
1463
|
+
events.emit(BIDDER_DONE, { ...MOCK.BIDDER_DONE, auctionId: auctionInits[auctionNum].auctionId });
|
|
1464
|
+
events.emit(AUCTION_END, { ...MOCK.AUCTION_END, auctionId: auctionInits[auctionNum].auctionId });
|
|
1465
|
+
}
|
|
1466
|
+
it('should select earliest auction to attach to', () => {
|
|
1467
|
+
// get 3 auctions pending to send events
|
|
1468
|
+
runBasicAuction(0);
|
|
1469
|
+
runBasicAuction(1);
|
|
1470
|
+
runBasicAuction(2);
|
|
1471
|
+
|
|
1472
|
+
// emmit a gptEvent should attach to first auction
|
|
1473
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1474
|
+
|
|
1475
|
+
// should be 4 requests so far (3 auctions + 1 gamRender)
|
|
1476
|
+
expect(server.requests.length).to.equal(4);
|
|
1477
|
+
|
|
1478
|
+
// 4th should be gamRender and should have Auciton # 1's id's
|
|
1479
|
+
const message = JSON.parse(server.requests[3].requestBody);
|
|
1480
|
+
const expectedMessage = {
|
|
1481
|
+
...ANALYTICS_MESSAGE.gamRenders[0],
|
|
1482
|
+
auctionId: 'auctionId-1',
|
|
1483
|
+
transactionId: 'tid-1'
|
|
1484
|
+
};
|
|
1485
|
+
expect(message.gamRenders).to.deep.equal([expectedMessage]);
|
|
1486
|
+
|
|
1487
|
+
// emit bidWon from first auction
|
|
1488
|
+
events.emit(BID_WON, bidsWon[0]);
|
|
1489
|
+
|
|
1490
|
+
// another request which is bidWon
|
|
1491
|
+
expect(server.requests.length).to.equal(5);
|
|
1492
|
+
const message1 = JSON.parse(server.requests[4].requestBody);
|
|
1493
|
+
const expectedMessage1 = {
|
|
1494
|
+
...ANALYTICS_MESSAGE.bidsWon[0],
|
|
1495
|
+
sourceAuctionId: 'auctionId-1',
|
|
1496
|
+
renderAuctionId: 'auctionId-1',
|
|
1497
|
+
sourceTransactionId: 'tid-1',
|
|
1498
|
+
renderTransactionId: 'tid-1',
|
|
1499
|
+
transactionId: 'tid-1',
|
|
1500
|
+
bidId: 'bidId-1',
|
|
1501
|
+
};
|
|
1502
|
+
expect(message1.bidsWon).to.deep.equal([expectedMessage1]);
|
|
1503
|
+
});
|
|
1504
|
+
|
|
1505
|
+
[
|
|
1506
|
+
{ useBidCache: true, expectedRenderId: 3 },
|
|
1507
|
+
{ useBidCache: false, expectedRenderId: 2 }
|
|
1508
|
+
].forEach(test => {
|
|
1509
|
+
it(`should match bidWon to correct render auction if useBidCache is ${test.useBidCache}`, () => {
|
|
1510
|
+
config.setConfig({ useBidCache: test.useBidCache });
|
|
1511
|
+
// get 3 auctions pending to send events
|
|
1512
|
+
runBasicAuction(0);
|
|
1513
|
+
runBasicAuction(1);
|
|
1514
|
+
runBasicAuction(2);
|
|
1515
|
+
|
|
1516
|
+
// emmit 3 gpt Events, first two "empty"
|
|
1517
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, {
|
|
1518
|
+
slot: gptSlot0,
|
|
1519
|
+
isEmpty: true,
|
|
1520
|
+
});
|
|
1521
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, {
|
|
1522
|
+
slot: gptSlot0,
|
|
1523
|
+
isEmpty: true,
|
|
1524
|
+
});
|
|
1525
|
+
// last one is valid
|
|
1526
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1527
|
+
|
|
1528
|
+
// should be 6 requests so far (3 auctions + 3 gamRender)
|
|
1529
|
+
expect(server.requests.length).to.equal(6);
|
|
1530
|
+
|
|
1531
|
+
// 4th should be gamRender and should have Auciton # 1's id's
|
|
1532
|
+
const message = JSON.parse(server.requests[3].requestBody);
|
|
1533
|
+
const expectedMessage = {
|
|
1534
|
+
auctionId: 'auctionId-1',
|
|
1535
|
+
transactionId: 'tid-1',
|
|
1536
|
+
isSlotEmpty: true,
|
|
1537
|
+
adSlot: 'box'
|
|
1538
|
+
};
|
|
1539
|
+
expect(message.gamRenders).to.deep.equal([expectedMessage]);
|
|
1540
|
+
|
|
1541
|
+
// 5th should be gamRender and should have Auciton # 2's id's
|
|
1542
|
+
const message1 = JSON.parse(server.requests[4].requestBody);
|
|
1543
|
+
const expectedMessage1 = {
|
|
1544
|
+
auctionId: 'auctionId-2',
|
|
1545
|
+
transactionId: 'tid-2',
|
|
1546
|
+
isSlotEmpty: true,
|
|
1547
|
+
adSlot: 'box'
|
|
1548
|
+
};
|
|
1549
|
+
expect(message1.gamRenders).to.deep.equal([expectedMessage1]);
|
|
1550
|
+
|
|
1551
|
+
// 6th should be gamRender and should have Auciton # 3's id's
|
|
1552
|
+
const message2 = JSON.parse(server.requests[5].requestBody);
|
|
1553
|
+
const expectedMessage2 = {
|
|
1554
|
+
...ANALYTICS_MESSAGE.gamRenders[0],
|
|
1555
|
+
auctionId: 'auctionId-3',
|
|
1556
|
+
transactionId: 'tid-3'
|
|
1557
|
+
};
|
|
1558
|
+
expect(message2.gamRenders).to.deep.equal([expectedMessage2]);
|
|
1559
|
+
|
|
1560
|
+
// emit bidWon from second auction
|
|
1561
|
+
// it should pick out render information from 3rd auction and source from 1st
|
|
1562
|
+
events.emit(BID_WON, bidsWon[1]);
|
|
1563
|
+
|
|
1564
|
+
// another request which is bidWon
|
|
1565
|
+
expect(server.requests.length).to.equal(7);
|
|
1566
|
+
const message3 = JSON.parse(server.requests[6].requestBody);
|
|
1567
|
+
const expectedMessage3 = {
|
|
1568
|
+
...ANALYTICS_MESSAGE.bidsWon[0],
|
|
1569
|
+
sourceAuctionId: 'auctionId-2',
|
|
1570
|
+
renderAuctionId: `auctionId-${test.expectedRenderId}`,
|
|
1571
|
+
sourceTransactionId: 'tid-2',
|
|
1572
|
+
renderTransactionId: `tid-${test.expectedRenderId}`,
|
|
1573
|
+
transactionId: 'tid-2',
|
|
1574
|
+
bidId: 'bidId-2'
|
|
1575
|
+
};
|
|
1576
|
+
if (test.useBidCache) expectedMessage3.isCachedBid = true
|
|
1577
|
+
expect(message3.bidsWon).to.deep.equal([expectedMessage3]);
|
|
1578
|
+
});
|
|
1579
|
+
});
|
|
1580
|
+
|
|
1581
|
+
it('should still fire bidWon if no gam match found', () => {
|
|
1582
|
+
// get 3 auctions pending to send events
|
|
1583
|
+
runBasicAuction(0);
|
|
1584
|
+
runBasicAuction(1);
|
|
1585
|
+
runBasicAuction(2);
|
|
1586
|
+
|
|
1587
|
+
// emit bidWon from 3rd auction - it should still fire even though no associated gamRender found
|
|
1588
|
+
events.emit(BID_WON, bidsWon[2]);
|
|
1589
|
+
|
|
1590
|
+
// another request which is bidWon
|
|
1591
|
+
expect(server.requests.length).to.equal(4);
|
|
1592
|
+
const message1 = JSON.parse(server.requests[3].requestBody);
|
|
1593
|
+
const expectedMessage1 = {
|
|
1594
|
+
...ANALYTICS_MESSAGE.bidsWon[0],
|
|
1595
|
+
sourceAuctionId: 'auctionId-3',
|
|
1596
|
+
renderAuctionId: 'auctionId-3',
|
|
1597
|
+
sourceTransactionId: 'tid-3',
|
|
1598
|
+
renderTransactionId: 'tid-3',
|
|
1599
|
+
transactionId: 'tid-3',
|
|
1600
|
+
bidId: 'bidId-3',
|
|
1601
|
+
};
|
|
1602
|
+
expect(message1.bidsWon).to.deep.equal([expectedMessage1]);
|
|
1603
|
+
});
|
|
1604
|
+
});
|
|
1605
|
+
});
|
|
1606
|
+
|
|
1607
|
+
describe('billing events integration', () => {
|
|
1608
|
+
beforeEach(function () {
|
|
1609
|
+
magniteAdapter.enableAnalytics({
|
|
1610
|
+
options: {
|
|
1611
|
+
endpoint: '//localhost:9999/event',
|
|
1612
|
+
accountId: 1001
|
|
1613
|
+
}
|
|
1614
|
+
});
|
|
1615
|
+
// default dmBilling
|
|
1616
|
+
config.setConfig({
|
|
1617
|
+
rubicon: {
|
|
1618
|
+
dmBilling: {
|
|
1619
|
+
enabled: false,
|
|
1620
|
+
vendors: [],
|
|
1621
|
+
waitForAuction: true
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
})
|
|
1625
|
+
});
|
|
1626
|
+
afterEach(function () {
|
|
1627
|
+
magniteAdapter.disableAnalytics();
|
|
1628
|
+
});
|
|
1629
|
+
const basicBillingAuction = (billingEvents = []) => {
|
|
1630
|
+
events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
|
|
1631
|
+
events.emit(BID_REQUESTED, MOCK.BID_REQUESTED);
|
|
1632
|
+
|
|
1633
|
+
billingEvents.forEach(ev => events.emit(BILLABLE_EVENT, ev));
|
|
1634
|
+
|
|
1635
|
+
events.emit(BID_RESPONSE, MOCK.BID_RESPONSE);
|
|
1636
|
+
events.emit(BIDDER_DONE, MOCK.BIDDER_DONE);
|
|
1637
|
+
events.emit(AUCTION_END, MOCK.AUCTION_END);
|
|
1638
|
+
|
|
1639
|
+
mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params);
|
|
1640
|
+
events.emit(BID_WON, MOCK.BID_WON);
|
|
1641
|
+
|
|
1642
|
+
// tick the event delay time plus processing delay
|
|
1643
|
+
clock.tick(rubiConf.analyticsEventDelay + rubiConf.analyticsProcessDelay);
|
|
1644
|
+
}
|
|
1645
|
+
it('should ignore billing events when not enabled', () => {
|
|
1646
|
+
basicBillingAuction([{
|
|
1647
|
+
vendor: 'vendorName',
|
|
1648
|
+
type: 'auction',
|
|
1649
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965'
|
|
1650
|
+
}]);
|
|
1651
|
+
expect(server.requests.length).to.equal(1);
|
|
1652
|
+
const request = server.requests[0];
|
|
1653
|
+
const message = JSON.parse(request.requestBody);
|
|
1654
|
+
expect(message.billableEvents).to.be.undefined;
|
|
1655
|
+
});
|
|
1656
|
+
it('should ignore billing events when enabled but vendor is not whitelisted', () => {
|
|
1657
|
+
// off by default
|
|
1658
|
+
config.setConfig({
|
|
1659
|
+
rubicon: {
|
|
1660
|
+
dmBilling: {
|
|
1661
|
+
enabled: true
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
});
|
|
1665
|
+
basicBillingAuction([{
|
|
1666
|
+
vendor: 'vendorName',
|
|
1667
|
+
type: 'auction',
|
|
1668
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965'
|
|
1669
|
+
}]);
|
|
1670
|
+
expect(server.requests.length).to.equal(1);
|
|
1671
|
+
const request = server.requests[0];
|
|
1672
|
+
const message = JSON.parse(request.requestBody);
|
|
1673
|
+
expect(message.billableEvents).to.be.undefined;
|
|
1674
|
+
});
|
|
1675
|
+
it('should ignore billing events if billingId is not defined or billingId is not a string', () => {
|
|
1676
|
+
// off by default
|
|
1677
|
+
config.setConfig({
|
|
1678
|
+
rubicon: {
|
|
1679
|
+
dmBilling: {
|
|
1680
|
+
enabled: true,
|
|
1681
|
+
vendors: ['vendorName']
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
});
|
|
1685
|
+
basicBillingAuction([
|
|
1686
|
+
{
|
|
1687
|
+
vendor: 'vendorName',
|
|
1688
|
+
type: 'auction',
|
|
1689
|
+
},
|
|
1690
|
+
{
|
|
1691
|
+
vendor: 'vendorName',
|
|
1692
|
+
type: 'auction',
|
|
1693
|
+
billingId: true
|
|
1694
|
+
},
|
|
1695
|
+
{
|
|
1696
|
+
vendor: 'vendorName',
|
|
1697
|
+
type: 'auction',
|
|
1698
|
+
billingId: 1233434
|
|
1699
|
+
},
|
|
1700
|
+
{
|
|
1701
|
+
vendor: 'vendorName',
|
|
1702
|
+
type: 'auction',
|
|
1703
|
+
billingId: null
|
|
1704
|
+
}
|
|
1705
|
+
]);
|
|
1706
|
+
expect(server.requests.length).to.equal(1);
|
|
1707
|
+
const request = server.requests[0];
|
|
1708
|
+
const message = JSON.parse(request.requestBody);
|
|
1709
|
+
expect(message.billableEvents).to.be.undefined;
|
|
1710
|
+
});
|
|
1711
|
+
it('should pass along billing event in same payload if same auctionId', () => {
|
|
1712
|
+
// off by default
|
|
1713
|
+
config.setConfig({
|
|
1714
|
+
rubicon: {
|
|
1715
|
+
dmBilling: {
|
|
1716
|
+
enabled: true,
|
|
1717
|
+
vendors: ['vendorName']
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
});
|
|
1721
|
+
basicBillingAuction([{
|
|
1722
|
+
vendor: 'vendorName',
|
|
1723
|
+
type: 'pageView',
|
|
1724
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965',
|
|
1725
|
+
auctionId: MOCK.AUCTION_INIT.auctionId
|
|
1726
|
+
}]);
|
|
1727
|
+
expect(server.requests.length).to.equal(1);
|
|
1728
|
+
const request = server.requests[0];
|
|
1729
|
+
const message = JSON.parse(request.requestBody);
|
|
1730
|
+
expect(message).to.haveOwnProperty('auctions');
|
|
1731
|
+
expect(message.billableEvents).to.deep.equal([{
|
|
1732
|
+
accountId: 1001,
|
|
1733
|
+
vendor: 'vendorName',
|
|
1734
|
+
type: 'pageView',
|
|
1735
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965',
|
|
1736
|
+
auctionId: MOCK.AUCTION_INIT.auctionId
|
|
1737
|
+
}]);
|
|
1738
|
+
});
|
|
1739
|
+
it('should pass NOT pass along billing event in same payload if no auctionId', () => {
|
|
1740
|
+
// off by default
|
|
1741
|
+
config.setConfig({
|
|
1742
|
+
rubicon: {
|
|
1743
|
+
dmBilling: {
|
|
1744
|
+
enabled: true,
|
|
1745
|
+
vendors: ['vendorName']
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
});
|
|
1749
|
+
basicBillingAuction([{
|
|
1750
|
+
vendor: 'vendorName',
|
|
1751
|
+
type: 'auction',
|
|
1752
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965',
|
|
1753
|
+
}]);
|
|
1754
|
+
expect(server.requests.length).to.equal(2);
|
|
1755
|
+
|
|
1756
|
+
// first is the billing event
|
|
1757
|
+
let message = JSON.parse(server.requests[0].requestBody);
|
|
1758
|
+
expect(message).to.not.haveOwnProperty('auctions');
|
|
1759
|
+
expect(message.billableEvents).to.deep.equal([{
|
|
1760
|
+
accountId: 1001,
|
|
1761
|
+
vendor: 'vendorName',
|
|
1762
|
+
type: 'auction',
|
|
1763
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965'
|
|
1764
|
+
}]);
|
|
1765
|
+
|
|
1766
|
+
// second is auctions
|
|
1767
|
+
message = JSON.parse(server.requests[1].requestBody);
|
|
1768
|
+
expect(message).to.haveOwnProperty('auctions');
|
|
1769
|
+
expect(message).to.not.haveOwnProperty('billableEvents');
|
|
1770
|
+
});
|
|
1771
|
+
it('should pass along multiple billing events but filter out duplicates', () => {
|
|
1772
|
+
// off by default
|
|
1773
|
+
config.setConfig({
|
|
1774
|
+
rubicon: {
|
|
1775
|
+
dmBilling: {
|
|
1776
|
+
enabled: true,
|
|
1777
|
+
vendors: ['vendorName']
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
});
|
|
1781
|
+
basicBillingAuction([
|
|
1782
|
+
{
|
|
1783
|
+
vendor: 'vendorName',
|
|
1784
|
+
type: 'auction',
|
|
1785
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965',
|
|
1786
|
+
auctionId: MOCK.AUCTION_INIT.auctionId
|
|
1787
|
+
},
|
|
1788
|
+
{
|
|
1789
|
+
vendor: 'vendorName',
|
|
1790
|
+
type: 'impression',
|
|
1791
|
+
billingId: '743db6e3-21f2-44d4-917f-cb3488c6076f',
|
|
1792
|
+
auctionId: MOCK.AUCTION_INIT.auctionId
|
|
1793
|
+
},
|
|
1794
|
+
{
|
|
1795
|
+
vendor: 'vendorName',
|
|
1796
|
+
type: 'auction',
|
|
1797
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965',
|
|
1798
|
+
auctionId: MOCK.AUCTION_INIT.auctionId
|
|
1799
|
+
}
|
|
1800
|
+
]);
|
|
1801
|
+
expect(server.requests.length).to.equal(1);
|
|
1802
|
+
const request = server.requests[0];
|
|
1803
|
+
const message = JSON.parse(request.requestBody);
|
|
1804
|
+
expect(message).to.haveOwnProperty('auctions');
|
|
1805
|
+
expect(message.billableEvents).to.deep.equal([
|
|
1806
|
+
{
|
|
1807
|
+
accountId: 1001,
|
|
1808
|
+
vendor: 'vendorName',
|
|
1809
|
+
type: 'auction',
|
|
1810
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965',
|
|
1811
|
+
auctionId: MOCK.AUCTION_INIT.auctionId
|
|
1812
|
+
},
|
|
1813
|
+
{
|
|
1814
|
+
accountId: 1001,
|
|
1815
|
+
vendor: 'vendorName',
|
|
1816
|
+
type: 'impression',
|
|
1817
|
+
billingId: '743db6e3-21f2-44d4-917f-cb3488c6076f',
|
|
1818
|
+
auctionId: MOCK.AUCTION_INIT.auctionId
|
|
1819
|
+
}
|
|
1820
|
+
]);
|
|
1821
|
+
});
|
|
1822
|
+
it('should pass along event right away if no pending auction', () => {
|
|
1823
|
+
// off by default
|
|
1824
|
+
config.setConfig({
|
|
1825
|
+
rubicon: {
|
|
1826
|
+
analyticsEventDelay: 0,
|
|
1827
|
+
dmBilling: {
|
|
1828
|
+
enabled: true,
|
|
1829
|
+
vendors: ['vendorName']
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
});
|
|
1833
|
+
|
|
1834
|
+
events.emit(BILLABLE_EVENT, {
|
|
1835
|
+
vendor: 'vendorName',
|
|
1836
|
+
type: 'auction',
|
|
1837
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965'
|
|
1838
|
+
});
|
|
1839
|
+
expect(server.requests.length).to.equal(1);
|
|
1840
|
+
const request = server.requests[0];
|
|
1841
|
+
const message = JSON.parse(request.requestBody);
|
|
1842
|
+
expect(message).to.not.haveOwnProperty('auctions');
|
|
1843
|
+
expect(message.billableEvents).to.deep.equal([
|
|
1844
|
+
{
|
|
1845
|
+
accountId: 1001,
|
|
1846
|
+
vendor: 'vendorName',
|
|
1847
|
+
type: 'auction',
|
|
1848
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965'
|
|
1849
|
+
}
|
|
1850
|
+
]);
|
|
1851
|
+
});
|
|
1852
|
+
it('should pass along event right away if pending auction but not waiting', () => {
|
|
1853
|
+
// off by default
|
|
1854
|
+
config.setConfig({
|
|
1855
|
+
rubicon: {
|
|
1856
|
+
dmBilling: {
|
|
1857
|
+
enabled: true,
|
|
1858
|
+
vendors: ['vendorName'],
|
|
1859
|
+
waitForAuction: false
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
});
|
|
1863
|
+
// should fire right away, and then auction later
|
|
1864
|
+
basicBillingAuction([{
|
|
1865
|
+
vendor: 'vendorName',
|
|
1866
|
+
type: 'auction',
|
|
1867
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965'
|
|
1868
|
+
}]);
|
|
1869
|
+
expect(server.requests.length).to.equal(2);
|
|
1870
|
+
const billingRequest = server.requests[0];
|
|
1871
|
+
const billingMessage = JSON.parse(billingRequest.requestBody);
|
|
1872
|
+
expect(billingMessage).to.not.haveOwnProperty('auctions');
|
|
1873
|
+
expect(billingMessage.billableEvents).to.deep.equal([
|
|
1874
|
+
{
|
|
1875
|
+
accountId: 1001,
|
|
1876
|
+
vendor: 'vendorName',
|
|
1877
|
+
type: 'auction',
|
|
1878
|
+
billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965'
|
|
1879
|
+
}
|
|
1880
|
+
]);
|
|
1881
|
+
// auction event after
|
|
1882
|
+
const auctionRequest = server.requests[1];
|
|
1883
|
+
const auctionMessage = JSON.parse(auctionRequest.requestBody);
|
|
1884
|
+
// should not double pass events!
|
|
1885
|
+
expect(auctionMessage).to.not.haveOwnProperty('billableEvents');
|
|
1886
|
+
});
|
|
1887
|
+
});
|
|
1888
|
+
|
|
1889
|
+
it('getHostNameFromReferer correctly grabs hostname from an input URL', function () {
|
|
1890
|
+
let inputUrl = 'https://www.prebid.org/some/path?pbjs_debug=true';
|
|
1891
|
+
expect(getHostNameFromReferer(inputUrl)).to.equal('www.prebid.org');
|
|
1892
|
+
inputUrl = 'https://www.prebid.com/some/path?pbjs_debug=true';
|
|
1893
|
+
expect(getHostNameFromReferer(inputUrl)).to.equal('www.prebid.com');
|
|
1894
|
+
inputUrl = 'https://prebid.org/some/path?pbjs_debug=true';
|
|
1895
|
+
expect(getHostNameFromReferer(inputUrl)).to.equal('prebid.org');
|
|
1896
|
+
inputUrl = 'http://xn--p8j9a0d9c9a.xn--q9jyb4c/';
|
|
1897
|
+
expect(typeof getHostNameFromReferer(inputUrl)).to.equal('string');
|
|
1898
|
+
|
|
1899
|
+
// not non-UTF char's in query / path which break if noDecodeWholeURL not set
|
|
1900
|
+
inputUrl = 'https://prebid.org/search_results/%95x%8Em%92%CA/?category=000';
|
|
1901
|
+
expect(getHostNameFromReferer(inputUrl)).to.equal('prebid.org');
|
|
1902
|
+
});
|
|
1903
|
+
|
|
1904
|
+
describe(`handle currency conversions`, () => {
|
|
1905
|
+
const origConvertCurrency = getGlobal().convertCurrency;
|
|
1906
|
+
afterEach(() => {
|
|
1907
|
+
if (origConvertCurrency != null) {
|
|
1908
|
+
getGlobal().convertCurrency = origConvertCurrency;
|
|
1909
|
+
} else {
|
|
1910
|
+
delete getGlobal().convertCurrency;
|
|
1911
|
+
}
|
|
1912
|
+
});
|
|
1913
|
+
|
|
1914
|
+
it(`should convert successfully`, () => {
|
|
1915
|
+
getGlobal().convertCurrency = () => 1.0;
|
|
1916
|
+
const bidCopy = utils.deepClone(MOCK.BID_RESPONSE);
|
|
1917
|
+
bidCopy.currency = 'JPY';
|
|
1918
|
+
bidCopy.cpm = 100;
|
|
1919
|
+
|
|
1920
|
+
const bidResponseObj = parseBidResponse(bidCopy);
|
|
1921
|
+
expect(bidResponseObj.conversionError).to.equal(undefined);
|
|
1922
|
+
expect(bidResponseObj.ogCurrency).to.equal(undefined);
|
|
1923
|
+
expect(bidResponseObj.ogPrice).to.equal(undefined);
|
|
1924
|
+
expect(bidResponseObj.bidPriceUSD).to.equal(1.0);
|
|
1925
|
+
});
|
|
1926
|
+
|
|
1927
|
+
it(`should catch error and set to zero with conversionError flag true`, () => {
|
|
1928
|
+
getGlobal().convertCurrency = () => {
|
|
1929
|
+
throw new Error('I am an error');
|
|
1930
|
+
};
|
|
1931
|
+
const bidCopy = utils.deepClone(MOCK.BID_RESPONSE);
|
|
1932
|
+
bidCopy.currency = 'JPY';
|
|
1933
|
+
bidCopy.cpm = 100;
|
|
1934
|
+
|
|
1935
|
+
const bidResponseObj = parseBidResponse(bidCopy);
|
|
1936
|
+
expect(bidResponseObj.conversionError).to.equal(true);
|
|
1937
|
+
expect(bidResponseObj.ogCurrency).to.equal('JPY');
|
|
1938
|
+
expect(bidResponseObj.ogPrice).to.equal(100);
|
|
1939
|
+
expect(bidResponseObj.bidPriceUSD).to.equal(0);
|
|
1940
|
+
});
|
|
1941
|
+
});
|
|
1942
|
+
});
|