prebid.js 6.5.0 → 6.9.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/.eslintrc.js +8 -1
- package/integrationExamples/gpt/amp/creative.html +11 -33
- package/integrationExamples/gpt/weboramaRtdProvider_example.html +154 -115
- package/integrationExamples/gpt/x-domain/creative.html +63 -29
- package/modules/.submodules.json +2 -1
- package/modules/adagioBidAdapter.js +0 -8
- package/modules/adagioBidAdapter.md +1 -1
- package/modules/adbookpspBidAdapter.js +27 -10
- package/modules/adhashBidAdapter.js +3 -3
- package/modules/adkernelBidAdapter.js +2 -1
- package/modules/admanBidAdapter.js +10 -4
- package/modules/adomikAnalyticsAdapter.js +23 -11
- package/modules/adqueryIdSystem.js +103 -0
- package/modules/adqueryIdSystem.md +35 -0
- package/modules/appnexusBidAdapter.js +14 -2
- package/modules/asealBidAdapter.js +58 -0
- package/modules/asealBidAdapter.md +52 -0
- package/modules/bliinkBidAdapter.js +2 -1
- package/modules/brandmetricsRtdProvider.js +168 -0
- package/modules/brandmetricsRtdProvider.md +40 -0
- package/modules/colossussspBidAdapter.js +12 -8
- package/modules/colossussspBidAdapter.md +15 -1
- package/modules/compassBidAdapter.js +10 -3
- package/modules/consumableBidAdapter.md +1 -1
- package/modules/conversantBidAdapter.js +7 -0
- package/modules/criteoBidAdapter.js +10 -1
- package/modules/criteoIdSystem.js +29 -7
- package/modules/currency.js +26 -1
- package/modules/displayioBidAdapter.js +157 -0
- package/modules/displayioBidAdapter.md +148 -0
- package/modules/e_volutionBidAdapter.js +158 -0
- package/modules/glimpseBidAdapter.js +66 -44
- package/modules/gnetBidAdapter.js +3 -3
- package/modules/gnetBidAdapter.md +4 -4
- package/modules/gumgumBidAdapter.js +56 -42
- package/modules/idImportLibrary.js +45 -8
- package/modules/idImportLibrary.md +4 -0
- package/modules/improvedigitalBidAdapter.js +29 -2
- package/modules/interactiveOffersBidAdapter.js +9 -6
- package/modules/jwplayerRtdProvider.js +71 -6
- package/modules/jwplayerRtdProvider.md +27 -11
- package/modules/kargoBidAdapter.js +2 -2
- package/modules/lunamediahbBidAdapter.js +32 -4
- package/modules/nextMillenniumBidAdapter.js +3 -1
- package/modules/oguryBidAdapter.js +14 -14
- package/modules/onetagBidAdapter.js +4 -2
- package/modules/pilotxBidAdapter.js +147 -0
- package/modules/pilotxBidAdapter.md +50 -0
- package/modules/priceFloors.js +2 -1
- package/modules/proxistoreBidAdapter.js +0 -2
- package/modules/pubmaticAnalyticsAdapter.js +16 -0
- package/modules/richaudienceBidAdapter.js +10 -4
- package/modules/riseBidAdapter.js +18 -7
- package/modules/rtbhouseBidAdapter.js +14 -4
- package/modules/rtdModule/index.js +14 -15
- package/modules/rubiconAnalyticsAdapter.js +8 -2
- package/modules/seedingAllianceBidAdapter.js +3 -3
- package/modules/sharethroughBidAdapter.js +12 -17
- package/modules/showheroes-bsBidAdapter.js +13 -2
- package/modules/sortableAnalyticsAdapter.js +5 -4
- package/modules/sovrnBidAdapter.js +93 -18
- package/modules/sovrnBidAdapter.md +80 -2
- package/modules/synacormediaBidAdapter.js +31 -10
- package/modules/tappxBidAdapter.js +8 -5
- package/modules/teadsBidAdapter.js +1 -2
- package/modules/undertoneBidAdapter.js +17 -1
- package/modules/userId/eids.js +7 -1
- package/modules/userId/userId.md +8 -0
- package/modules/viewability.js +177 -0
- package/modules/viewability.md +87 -0
- package/modules/weboramaRtdProvider.js +264 -34
- package/modules/weboramaRtdProvider.md +110 -40
- package/modules/welectBidAdapter.js +106 -0
- package/modules/yahoosspBidAdapter.js +2 -0
- package/package.json +2 -1
- package/src/adRendering.js +38 -0
- package/src/adloader.js +2 -1
- package/src/auction.js +103 -73
- package/src/bidderSettings.js +69 -0
- package/src/hook.js +5 -1
- package/src/prebid.js +19 -21
- package/src/secureCreatives.js +131 -47
- package/src/targeting.js +3 -2
- package/src/utils.js +13 -10
- package/test/helpers/syncPromise.js +71 -0
- package/test/spec/auctionmanager_spec.js +179 -15
- package/test/spec/modules/adagioBidAdapter_spec.js +0 -10
- package/test/spec/modules/adbookpspBidAdapter_spec.js +17 -3
- package/test/spec/modules/adhashBidAdapter_spec.js +2 -2
- package/test/spec/modules/admanBidAdapter_spec.js +2 -2
- package/test/spec/modules/adomikAnalyticsAdapter_spec.js +3 -1
- package/test/spec/modules/adqueryIdSystem_spec.js +74 -0
- package/test/spec/modules/appnexusBidAdapter_spec.js +27 -0
- package/test/spec/modules/asealBidAdapter_spec.js +144 -0
- package/test/spec/modules/bliinkBidAdapter_spec.js +2 -0
- package/test/spec/modules/brandmetricsRtdProvider_spec.js +191 -0
- package/test/spec/modules/colossussspBidAdapter_spec.js +5 -2
- package/test/spec/modules/compassBidAdapter_spec.js +1 -0
- package/test/spec/modules/conversantBidAdapter_spec.js +54 -2
- package/test/spec/modules/criteoBidAdapter_spec.js +21 -0
- package/test/spec/modules/criteoIdSystem_spec.js +6 -3
- package/test/spec/modules/currency_spec.js +21 -6
- package/test/spec/modules/displayioBidAdapter_spec.js +239 -0
- package/test/spec/modules/e_volutionBidAdapter_spec.js +242 -0
- package/test/spec/modules/eids_spec.js +15 -0
- package/test/spec/modules/glimpseBidAdapter_spec.js +0 -18
- package/test/spec/modules/gnetBidAdapter_spec.js +6 -6
- package/test/spec/modules/gumgumBidAdapter_spec.js +46 -0
- package/test/spec/modules/idImportLibrary_spec.js +197 -10
- package/test/spec/modules/improvedigitalBidAdapter_spec.js +61 -0
- package/test/spec/modules/jwplayerRtdProvider_spec.js +195 -2
- package/test/spec/modules/kargoBidAdapter_spec.js +1 -1
- package/test/spec/modules/loglyliftBidAdapter_spec.js +1 -1
- package/test/spec/modules/lunamediahbBidAdapter_spec.js +27 -1
- package/test/spec/modules/nextMillenniumBidAdapter_spec.js +1 -1
- package/test/spec/modules/oguryBidAdapter_spec.js +69 -3
- package/test/spec/modules/pilotxBidAdapter_spec.js +244 -0
- package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +13 -1
- package/test/spec/modules/realTimeDataModule_spec.js +67 -5
- package/test/spec/modules/richaudienceBidAdapter_spec.js +40 -0
- package/test/spec/modules/riseBidAdapter_spec.js +31 -5
- package/test/spec/modules/rtbhouseBidAdapter_spec.js +20 -0
- package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +61 -1
- package/test/spec/modules/sharethroughBidAdapter_spec.js +91 -6
- package/test/spec/modules/showheroes-bsBidAdapter_spec.js +2 -0
- package/test/spec/modules/sortableAnalyticsAdapter_spec.js +2 -3
- package/test/spec/modules/sovrnBidAdapter_spec.js +413 -333
- package/test/spec/modules/synacormediaBidAdapter_spec.js +70 -0
- package/test/spec/modules/tappxBidAdapter_spec.js +0 -19
- package/test/spec/modules/teadsBidAdapter_spec.js +14 -59
- package/test/spec/modules/undertoneBidAdapter_spec.js +55 -2
- package/test/spec/modules/userId_spec.js +68 -19
- package/test/spec/modules/viewability_spec.js +280 -0
- package/test/spec/modules/weboramaRtdProvider_spec.js +536 -20
- package/test/spec/modules/welectBidAdapter_spec.js +211 -0
- package/test/spec/modules/yahoosspBidAdapter_spec.js +10 -0
- package/test/spec/unit/core/bidderSettings_spec.js +123 -0
- package/test/spec/unit/pbjs_api_spec.js +21 -8
- package/test/spec/unit/secureCreatives_spec.js +143 -24
package/src/secureCreatives.js
CHANGED
|
@@ -4,22 +4,47 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import events from './events.js';
|
|
7
|
-
import {
|
|
7
|
+
import {fireNativeTrackers, getAllAssetsMessage, getAssetMessage} from './native.js';
|
|
8
8
|
import constants from './constants.json';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import {deepAccess, isApnGetTagDefined, isGptPubadsDefined, logError, logWarn, replaceAuctionPrice} from './utils.js';
|
|
10
|
+
import {auctionManager} from './auctionManager.js';
|
|
11
11
|
import find from 'core-js-pure/features/array/find.js';
|
|
12
|
-
import { isRendererRequired
|
|
12
|
+
import {executeRenderer, isRendererRequired} from './Renderer.js';
|
|
13
13
|
import includes from 'core-js-pure/features/array/includes.js';
|
|
14
|
-
import {
|
|
14
|
+
import {config} from './config.js';
|
|
15
|
+
import {emitAdRenderFail, emitAdRenderSucceeded} from './adRendering.js';
|
|
15
16
|
|
|
16
17
|
const BID_WON = constants.EVENTS.BID_WON;
|
|
17
18
|
const STALE_RENDER = constants.EVENTS.STALE_RENDER;
|
|
18
19
|
|
|
20
|
+
const HANDLER_MAP = {
|
|
21
|
+
'Prebid Request': handleRenderRequest,
|
|
22
|
+
'Prebid Native': handleNativeRequest,
|
|
23
|
+
'Prebid Event': handleEventRequest,
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
export function listenMessagesFromCreative() {
|
|
20
27
|
window.addEventListener('message', receiveMessage, false);
|
|
21
28
|
}
|
|
22
29
|
|
|
30
|
+
export function getReplier(ev) {
|
|
31
|
+
if (ev.origin == null && ev.ports.length === 0) {
|
|
32
|
+
return function () {
|
|
33
|
+
const msg = 'Cannot post message to a frame with null origin. Please update creatives to use MessageChannel, see https://github.com/prebid/Prebid.js/issues/7870'
|
|
34
|
+
logError(msg)
|
|
35
|
+
throw new Error(msg);
|
|
36
|
+
}
|
|
37
|
+
} else if (ev.ports.length > 0) {
|
|
38
|
+
return function (message) {
|
|
39
|
+
ev.ports[0].postMessage(JSON.stringify(message));
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
return function (message) {
|
|
43
|
+
ev.source.postMessage(JSON.stringify(message), ev.origin);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
23
48
|
export function receiveMessage(ev) {
|
|
24
49
|
var key = ev.message ? 'message' : 'data';
|
|
25
50
|
var data = {};
|
|
@@ -29,70 +54,128 @@ export function receiveMessage(ev) {
|
|
|
29
54
|
return;
|
|
30
55
|
}
|
|
31
56
|
|
|
32
|
-
if (data && data.adId) {
|
|
57
|
+
if (data && data.adId && data.message) {
|
|
33
58
|
const adObject = find(auctionManager.getBidsReceived(), function (bid) {
|
|
34
59
|
return bid.adId === data.adId;
|
|
35
60
|
});
|
|
61
|
+
if (HANDLER_MAP.hasOwnProperty(data.message)) {
|
|
62
|
+
HANDLER_MAP[data.message](getReplier(ev), data, adObject);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
36
66
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
67
|
+
function handleRenderRequest(reply, data, adObject) {
|
|
68
|
+
if (adObject == null) {
|
|
69
|
+
emitAdRenderFail({
|
|
70
|
+
reason: constants.AD_RENDER_FAILED_REASON.CANNOT_FIND_AD,
|
|
71
|
+
message: `Cannot find ad '${data.adId}' for cross-origin render request`,
|
|
72
|
+
id: data.adId
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (adObject.status === constants.BID_STATUS.RENDERED) {
|
|
77
|
+
logWarn(`Ad id ${adObject.adId} has been rendered before`);
|
|
78
|
+
events.emit(STALE_RENDER, adObject);
|
|
79
|
+
if (deepAccess(config.getConfig('auctionOptions'), 'suppressStaleRender')) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
_sendAdToCreative(adObject, reply);
|
|
86
|
+
} catch (e) {
|
|
87
|
+
emitAdRenderFail({
|
|
88
|
+
reason: constants.AD_RENDER_FAILED_REASON.EXCEPTION,
|
|
89
|
+
message: e.message,
|
|
90
|
+
id: data.adId,
|
|
91
|
+
bid: adObject
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
45
95
|
|
|
46
|
-
|
|
96
|
+
// save winning bids
|
|
97
|
+
auctionManager.addWinningBid(adObject);
|
|
47
98
|
|
|
48
|
-
|
|
49
|
-
|
|
99
|
+
events.emit(BID_WON, adObject);
|
|
100
|
+
}
|
|
50
101
|
|
|
102
|
+
function handleNativeRequest(reply, data, adObject) {
|
|
103
|
+
// handle this script from native template in an ad server
|
|
104
|
+
// window.parent.postMessage(JSON.stringify({
|
|
105
|
+
// message: 'Prebid Native',
|
|
106
|
+
// adId: '%%PATTERN:hb_adid%%'
|
|
107
|
+
// }), '*');
|
|
108
|
+
if (adObject == null) {
|
|
109
|
+
logError(`Cannot find ad '${data.adId}' for x-origin event request`);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
switch (data.action) {
|
|
113
|
+
case 'assetRequest':
|
|
114
|
+
reply(getAssetMessage(data, adObject));
|
|
115
|
+
break;
|
|
116
|
+
case 'allAssetRequest':
|
|
117
|
+
reply(getAllAssetsMessage(data, adObject));
|
|
118
|
+
break;
|
|
119
|
+
case 'resizeNativeHeight':
|
|
120
|
+
adObject.height = data.height;
|
|
121
|
+
adObject.width = data.width;
|
|
122
|
+
resizeRemoteCreative(adObject);
|
|
123
|
+
break;
|
|
124
|
+
default:
|
|
125
|
+
const trackerType = fireNativeTrackers(data, adObject);
|
|
126
|
+
if (trackerType === 'click') {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
auctionManager.addWinningBid(adObject);
|
|
51
130
|
events.emit(BID_WON, adObject);
|
|
52
|
-
|
|
131
|
+
}
|
|
132
|
+
}
|
|
53
133
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
134
|
+
function handleEventRequest(reply, data, adObject) {
|
|
135
|
+
if (adObject == null) {
|
|
136
|
+
logError(`Cannot find ad '${data.adId}' for x-origin event request`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (adObject.status !== constants.BID_STATUS.RENDERED) {
|
|
140
|
+
logWarn(`Received x-origin event request without corresponding render request for ad '${data.adId}'`);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
switch (data.event) {
|
|
144
|
+
case constants.EVENTS.AD_RENDER_FAILED:
|
|
145
|
+
emitAdRenderFail({
|
|
146
|
+
bid: adObject,
|
|
147
|
+
id: data.adId,
|
|
148
|
+
reason: data.info.reason,
|
|
149
|
+
message: data.info.message
|
|
150
|
+
});
|
|
151
|
+
break;
|
|
152
|
+
case constants.EVENTS.AD_RENDER_SUCCEEDED:
|
|
153
|
+
emitAdRenderSucceeded({
|
|
154
|
+
doc: null,
|
|
155
|
+
bid: adObject,
|
|
156
|
+
id: data.adId
|
|
157
|
+
});
|
|
158
|
+
break;
|
|
159
|
+
default:
|
|
160
|
+
logError(`Received x-origin event request for unsupported event: '${data.event}' (adId: '${data.adId}')`)
|
|
78
161
|
}
|
|
79
162
|
}
|
|
80
163
|
|
|
81
|
-
export function _sendAdToCreative(adObject,
|
|
164
|
+
export function _sendAdToCreative(adObject, reply) {
|
|
82
165
|
const { adId, ad, adUrl, width, height, renderer, cpm } = adObject;
|
|
83
166
|
// rendering for outstream safeframe
|
|
84
167
|
if (isRendererRequired(renderer)) {
|
|
85
168
|
executeRenderer(renderer, adObject);
|
|
86
169
|
} else if (adId) {
|
|
87
170
|
resizeRemoteCreative(adObject);
|
|
88
|
-
|
|
171
|
+
reply({
|
|
89
172
|
message: 'Prebid Response',
|
|
90
173
|
ad: replaceAuctionPrice(ad, cpm),
|
|
91
174
|
adUrl: replaceAuctionPrice(adUrl, cpm),
|
|
92
175
|
adId,
|
|
93
176
|
width,
|
|
94
177
|
height
|
|
95
|
-
})
|
|
178
|
+
});
|
|
96
179
|
}
|
|
97
180
|
}
|
|
98
181
|
|
|
@@ -127,11 +210,12 @@ function resizeRemoteCreative({ adId, adUnitCode, width, height }) {
|
|
|
127
210
|
}
|
|
128
211
|
|
|
129
212
|
function getDfpElementId(adId) {
|
|
130
|
-
|
|
213
|
+
const slot = find(window.googletag.pubads().getSlots(), slot => {
|
|
131
214
|
return find(slot.getTargetingKeys(), key => {
|
|
132
215
|
return includes(slot.getTargeting(key), adId);
|
|
133
216
|
});
|
|
134
|
-
})
|
|
217
|
+
});
|
|
218
|
+
return slot ? slot.getSlotElementId() : null;
|
|
135
219
|
}
|
|
136
220
|
|
|
137
221
|
function getAstElementId(adUnitCode) {
|
package/src/targeting.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, groupBy, isAdUnitCodeMatchingSlot, timestamp,
|
|
3
|
-
deepAccess, deepClone, logError, logWarn, logInfo, isFn, isArray, logMessage, isStr,
|
|
3
|
+
deepAccess, deepClone, logError, logWarn, logInfo, isFn, isArray, logMessage, isStr,
|
|
4
4
|
} from './utils.js';
|
|
5
5
|
import { config } from './config.js';
|
|
6
6
|
import { NATIVE_TARGETING_KEYS } from './native.js';
|
|
@@ -8,6 +8,7 @@ import { auctionManager } from './auctionManager.js';
|
|
|
8
8
|
import { sizeSupported } from './sizeMapping.js';
|
|
9
9
|
import { ADPOD } from './mediaTypes.js';
|
|
10
10
|
import { hook } from './hook.js';
|
|
11
|
+
import { bidderSettings } from './bidderSettings.js';
|
|
11
12
|
import includes from 'core-js-pure/features/array/includes.js';
|
|
12
13
|
import find from 'core-js-pure/features/array/find.js';
|
|
13
14
|
|
|
@@ -459,7 +460,7 @@ export function newTargeting(auctionManager) {
|
|
|
459
460
|
const adUnitCodes = getAdUnitCodes(adUnitCode);
|
|
460
461
|
return bidsReceived
|
|
461
462
|
.filter(bid => includes(adUnitCodes, bid.adUnitCode))
|
|
462
|
-
.filter(bid => (
|
|
463
|
+
.filter(bid => (bidderSettings.get(bid.bidderCode, 'allowZeroCpmBids') === true) ? bid.cpm >= 0 : bid.cpm > 0)
|
|
463
464
|
.map(bid => bid.adUnitCode)
|
|
464
465
|
.filter(uniques)
|
|
465
466
|
.map(adUnitCode => bidsReceived
|
package/src/utils.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import { config } from './config.js';
|
|
3
|
-
import { getGlobal } from './prebidGlobal.js';
|
|
4
3
|
import clone from 'just-clone';
|
|
5
4
|
import find from 'core-js-pure/features/array/find.js';
|
|
6
5
|
import includes from 'core-js-pure/features/array/includes.js';
|
|
@@ -22,7 +21,17 @@ let consoleLogExists = Boolean(consoleExists && window.console.log);
|
|
|
22
21
|
let consoleInfoExists = Boolean(consoleExists && window.console.info);
|
|
23
22
|
let consoleWarnExists = Boolean(consoleExists && window.console.warn);
|
|
24
23
|
let consoleErrorExists = Boolean(consoleExists && window.console.error);
|
|
25
|
-
|
|
24
|
+
|
|
25
|
+
const emitEvent = (function () {
|
|
26
|
+
// lazy load events to avoid circular import
|
|
27
|
+
let ev;
|
|
28
|
+
return function() {
|
|
29
|
+
if (ev == null) {
|
|
30
|
+
ev = require('./events.js');
|
|
31
|
+
}
|
|
32
|
+
return ev.emit.apply(ev, arguments);
|
|
33
|
+
}
|
|
34
|
+
})();
|
|
26
35
|
|
|
27
36
|
// this allows stubbing of utility functions that are used internally by other utility functions
|
|
28
37
|
export const internal = {
|
|
@@ -265,14 +274,14 @@ export function logWarn() {
|
|
|
265
274
|
if (debugTurnedOn() && consoleWarnExists) {
|
|
266
275
|
console.warn.apply(console, decorateLog(arguments, 'WARNING:'));
|
|
267
276
|
}
|
|
268
|
-
|
|
277
|
+
emitEvent(CONSTANTS.EVENTS.AUCTION_DEBUG, {type: 'WARNING', arguments: arguments});
|
|
269
278
|
}
|
|
270
279
|
|
|
271
280
|
export function logError() {
|
|
272
281
|
if (debugTurnedOn() && consoleErrorExists) {
|
|
273
282
|
console.error.apply(console, decorateLog(arguments, 'ERROR:'));
|
|
274
283
|
}
|
|
275
|
-
|
|
284
|
+
emitEvent(CONSTANTS.EVENTS.AUCTION_DEBUG, {type: 'ERROR', arguments: arguments});
|
|
276
285
|
}
|
|
277
286
|
|
|
278
287
|
function decorateLog(args, prefix) {
|
|
@@ -1333,9 +1342,3 @@ export function cyrb53Hash(str, seed = 0) {
|
|
|
1333
1342
|
h2 = imul(h2 ^ (h2 >>> 16), 2246822507) ^ imul(h1 ^ (h1 >>> 13), 3266489909);
|
|
1334
1343
|
return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString();
|
|
1335
1344
|
}
|
|
1336
|
-
|
|
1337
|
-
export function isAllowZeroCpmBidsEnabled(bidderCode) {
|
|
1338
|
-
const bidderSettings = getGlobal().bidderSettings;
|
|
1339
|
-
return ((bidderSettings[bidderCode] && bidderSettings[bidderCode].allowZeroCpmBids === true) ||
|
|
1340
|
-
(bidderSettings.standard && bidderSettings.standard.allowZeroCpmBids === true));
|
|
1341
|
-
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const orig = {};
|
|
2
|
+
['resolve', 'reject', 'all', 'race', 'allSettled'].forEach((k) => orig[k] = Promise[k].bind(Promise))
|
|
3
|
+
|
|
4
|
+
// Callbacks attached through Promise.resolve(value).then(...) will usually
|
|
5
|
+
// not execute immediately even if `value` is immediately available. This
|
|
6
|
+
// breaks tests that were written before promises even though they are semantically still valid.
|
|
7
|
+
// They can be made to work by making promises quasi-synchronous.
|
|
8
|
+
|
|
9
|
+
export function SyncPromise(value, fail = false) {
|
|
10
|
+
if (value instanceof SyncPromise) {
|
|
11
|
+
return value;
|
|
12
|
+
} else if (typeof value === 'object' && typeof value.then === 'function') {
|
|
13
|
+
return orig.resolve(value);
|
|
14
|
+
} else {
|
|
15
|
+
Object.assign(this, {
|
|
16
|
+
then: function (cb, err) {
|
|
17
|
+
const handler = fail ? err : cb;
|
|
18
|
+
if (handler != null) {
|
|
19
|
+
return new SyncPromise(handler(value));
|
|
20
|
+
} else {
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
catch: function (cb) {
|
|
25
|
+
if (fail) {
|
|
26
|
+
return new SyncPromise(cb(value))
|
|
27
|
+
} else {
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
finally: function (cb) {
|
|
32
|
+
cb();
|
|
33
|
+
return this;
|
|
34
|
+
},
|
|
35
|
+
__value: fail ? {status: 'rejected', reason: value} : {status: 'fulfilled', value}
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Object.assign(SyncPromise, {
|
|
41
|
+
resolve: (val) => new SyncPromise(val),
|
|
42
|
+
reject: (val) => new SyncPromise(val, true),
|
|
43
|
+
race: (promises) => promises.find((p) => p instanceof SyncPromise) || orig.race(promises),
|
|
44
|
+
allSettled: (promises) => {
|
|
45
|
+
if (promises.every((p) => p instanceof SyncPromise)) {
|
|
46
|
+
return new SyncPromise(promises.map((p) => p.__value))
|
|
47
|
+
} else {
|
|
48
|
+
return orig.allSettled(promises);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
all: (promises) => {
|
|
52
|
+
if (promises.every((p) => p instanceof SyncPromise)) {
|
|
53
|
+
return SyncPromise.allSettled(promises).then((result) => {
|
|
54
|
+
const err = result.find((r) => r.status === 'rejected');
|
|
55
|
+
if (err != null) {
|
|
56
|
+
return new SyncPromise(err.reason, true);
|
|
57
|
+
} else {
|
|
58
|
+
return new SyncPromise(result.map((r) => r.value))
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
} else {
|
|
62
|
+
return orig.all(promises);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
export function synchronizePromise(sandbox) {
|
|
68
|
+
Object.keys(orig).forEach((k) => {
|
|
69
|
+
sandbox.stub(window.Promise, k).callsFake(SyncPromise[k]);
|
|
70
|
+
})
|
|
71
|
+
}
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
AUCTION_COMPLETED,
|
|
5
5
|
adjustBids,
|
|
6
6
|
getMediaTypeGranularity,
|
|
7
|
+
getPriceByGranularity,
|
|
8
|
+
addBidResponse
|
|
7
9
|
} from 'src/auction.js';
|
|
8
10
|
import CONSTANTS from 'src/constants.json';
|
|
9
11
|
import * as auctionModule from 'src/auction.js';
|
|
@@ -14,6 +16,10 @@ import * as store from 'src/videoCache.js';
|
|
|
14
16
|
import * as ajaxLib from 'src/ajax.js';
|
|
15
17
|
import find from 'core-js-pure/features/array/find.js';
|
|
16
18
|
import { server } from 'test/mocks/xhr.js';
|
|
19
|
+
import {expect} from 'chai';
|
|
20
|
+
import {hook} from '../../src/hook.js';
|
|
21
|
+
import 'src/debugging.js'
|
|
22
|
+
import {synchronizePromise} from '../helpers/syncPromise.js'; // some of these tests require debugging hooks to be loaded
|
|
17
23
|
|
|
18
24
|
var assert = require('assert');
|
|
19
25
|
|
|
@@ -124,6 +130,27 @@ function mockAjaxBuilder() {
|
|
|
124
130
|
}
|
|
125
131
|
|
|
126
132
|
describe('auctionmanager.js', function () {
|
|
133
|
+
let promiseSandbox;
|
|
134
|
+
|
|
135
|
+
before(() => {
|
|
136
|
+
// hooks are global and their side effects depend on what has been loaded... not ideal for unit tests
|
|
137
|
+
[
|
|
138
|
+
auctionModule.addBidResponse,
|
|
139
|
+
auctionModule.addBidderRequests,
|
|
140
|
+
auctionModule.bidsBackCallback
|
|
141
|
+
].forEach((h) => h.getHooks().remove())
|
|
142
|
+
hook.ready();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
beforeEach(() => {
|
|
146
|
+
promiseSandbox = sinon.createSandbox();
|
|
147
|
+
synchronizePromise(promiseSandbox);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
afterEach(() => {
|
|
151
|
+
promiseSandbox.restore();
|
|
152
|
+
})
|
|
153
|
+
|
|
127
154
|
describe('getKeyValueTargetingPairs', function () {
|
|
128
155
|
const DEFAULT_BID = {
|
|
129
156
|
cpm: 5.578,
|
|
@@ -1255,16 +1282,41 @@ describe('auctionmanager.js', function () {
|
|
|
1255
1282
|
});
|
|
1256
1283
|
});
|
|
1257
1284
|
|
|
1285
|
+
describe('getPriceByGranularity', () => {
|
|
1286
|
+
beforeEach(() => {
|
|
1287
|
+
config.setConfig({
|
|
1288
|
+
mediaTypePriceGranularity: {
|
|
1289
|
+
video: 'medium',
|
|
1290
|
+
banner: 'low'
|
|
1291
|
+
}
|
|
1292
|
+
});
|
|
1293
|
+
})
|
|
1294
|
+
|
|
1295
|
+
afterEach(() => {
|
|
1296
|
+
config.resetConfig();
|
|
1297
|
+
})
|
|
1298
|
+
|
|
1299
|
+
it('evaluates undef granularity on each call', () => {
|
|
1300
|
+
const gpbg = getPriceByGranularity();
|
|
1301
|
+
expect(gpbg({
|
|
1302
|
+
mediaType: 'video', pbMg: 'medium'
|
|
1303
|
+
}, {
|
|
1304
|
+
'mediaTypes': {video: {id: '1'}}
|
|
1305
|
+
})).to.equal('medium');
|
|
1306
|
+
expect(gpbg({
|
|
1307
|
+
mediaType: 'banner',
|
|
1308
|
+
pbLg: 'low'
|
|
1309
|
+
}, {
|
|
1310
|
+
'mediaTypes': {banner: {}}
|
|
1311
|
+
})).to.equal('low');
|
|
1312
|
+
});
|
|
1313
|
+
})
|
|
1314
|
+
|
|
1258
1315
|
describe('auctionCallbacks', function() {
|
|
1259
1316
|
let bids = TEST_BIDS;
|
|
1260
1317
|
let bidRequests;
|
|
1261
1318
|
let doneSpy;
|
|
1262
|
-
let auction
|
|
1263
|
-
getBidRequests: () => bidRequests,
|
|
1264
|
-
getAuctionId: () => '1',
|
|
1265
|
-
addBidReceived: () => true,
|
|
1266
|
-
getTimeout: () => 1000
|
|
1267
|
-
}
|
|
1319
|
+
let auction;
|
|
1268
1320
|
|
|
1269
1321
|
beforeEach(() => {
|
|
1270
1322
|
doneSpy = sinon.spy();
|
|
@@ -1272,12 +1324,21 @@ describe('auctionmanager.js', function () {
|
|
|
1272
1324
|
cache: {
|
|
1273
1325
|
url: 'https://prebid.adnxs.com/pbc/v1/cache'
|
|
1274
1326
|
}
|
|
1275
|
-
})
|
|
1327
|
+
});
|
|
1328
|
+
const start = Date.now();
|
|
1329
|
+
auction = {
|
|
1330
|
+
getBidRequests: () => bidRequests,
|
|
1331
|
+
getAuctionId: () => '1',
|
|
1332
|
+
addBidReceived: () => true,
|
|
1333
|
+
getTimeout: () => 1000,
|
|
1334
|
+
getAuctionStart: () => start,
|
|
1335
|
+
}
|
|
1276
1336
|
});
|
|
1277
1337
|
|
|
1278
1338
|
afterEach(() => {
|
|
1279
1339
|
doneSpy.resetHistory();
|
|
1280
1340
|
config.resetConfig();
|
|
1341
|
+
bidRequests = null;
|
|
1281
1342
|
});
|
|
1282
1343
|
|
|
1283
1344
|
it('should call auction done after bid is added to auction for mediaType banner', function () {
|
|
@@ -1328,19 +1389,114 @@ describe('auctionmanager.js', function () {
|
|
|
1328
1389
|
const responseBody = `{"responses":[{"uuid":"${uuid}"}]}`;
|
|
1329
1390
|
server.requests[0].respond(200, { 'Content-Type': 'application/json' }, responseBody);
|
|
1330
1391
|
assert.equal(doneSpy.callCount, 1);
|
|
1331
|
-
})
|
|
1392
|
+
});
|
|
1393
|
+
|
|
1394
|
+
describe('when addBidResponse hook returns promises', () => {
|
|
1395
|
+
let resolvers, callbacks, bids;
|
|
1396
|
+
|
|
1397
|
+
function hook(next, ...args) {
|
|
1398
|
+
next.bail(new Promise((resolve, reject) => {
|
|
1399
|
+
resolvers.resolve.push(resolve);
|
|
1400
|
+
resolvers.reject.push(reject);
|
|
1401
|
+
}).finally(() => next(...args)));
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
function invokeCallbacks() {
|
|
1405
|
+
bids.forEach((bid, i) => callbacks.addBidResponse.call(bidRequests[i], ADUNIT_CODE, bid));
|
|
1406
|
+
bidRequests.forEach(bidRequest => callbacks.adapterDone.call(bidRequest));
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
function delay(ms = 0) {
|
|
1410
|
+
return new Promise((resolve) => {
|
|
1411
|
+
setTimeout(resolve, ms)
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
beforeEach(() => {
|
|
1416
|
+
promiseSandbox.restore();
|
|
1417
|
+
bids = [
|
|
1418
|
+
mockBid({bidderCode: BIDDER_CODE1}),
|
|
1419
|
+
mockBid({bidderCode: BIDDER_CODE})
|
|
1420
|
+
]
|
|
1421
|
+
bidRequests = bids.map((b) => mockBidRequest(b));
|
|
1422
|
+
resolvers = {resolve: [], reject: []};
|
|
1423
|
+
addBidResponse.before(hook);
|
|
1424
|
+
callbacks = auctionCallbacks(doneSpy, auction);
|
|
1425
|
+
Object.assign(auction, {
|
|
1426
|
+
addNoBid: sinon.spy()
|
|
1427
|
+
});
|
|
1428
|
+
});
|
|
1429
|
+
|
|
1430
|
+
afterEach(() => {
|
|
1431
|
+
addBidResponse.getHooks({hook: hook}).remove();
|
|
1432
|
+
});
|
|
1433
|
+
|
|
1434
|
+
Object.entries({
|
|
1435
|
+
'all succeed': ['resolve', 'resolve'],
|
|
1436
|
+
'some fail': ['resolve', 'reject'],
|
|
1437
|
+
'all fail': ['reject', 'reject']
|
|
1438
|
+
}).forEach(([test, results]) => {
|
|
1439
|
+
describe(`(and ${test})`, () => {
|
|
1440
|
+
it('should wait for them to complete before calling auctionDone', () => {
|
|
1441
|
+
invokeCallbacks();
|
|
1442
|
+
return delay().then(() => {
|
|
1443
|
+
expect(doneSpy.called).to.be.false;
|
|
1444
|
+
expect(auction.addNoBid.called).to.be.false;
|
|
1445
|
+
resolvers[results[0]][0]();
|
|
1446
|
+
return delay();
|
|
1447
|
+
}).then(() => {
|
|
1448
|
+
expect(doneSpy.called).to.be.false;
|
|
1449
|
+
expect(auction.addNoBid.called).to.be.false;
|
|
1450
|
+
resolvers[results[1]][1]();
|
|
1451
|
+
return delay();
|
|
1452
|
+
}).then(() => {
|
|
1453
|
+
expect(doneSpy.called).to.be.true;
|
|
1454
|
+
});
|
|
1455
|
+
});
|
|
1456
|
+
});
|
|
1457
|
+
});
|
|
1458
|
+
|
|
1459
|
+
Object.entries({
|
|
1460
|
+
bidder: (timeout) => {
|
|
1461
|
+
bidRequests.forEach((r) => r.timeout = timeout);
|
|
1462
|
+
auction.getTimeout = () => timeout + 10000
|
|
1463
|
+
},
|
|
1464
|
+
auction: (timeout) => {
|
|
1465
|
+
auction.getTimeout = () => timeout;
|
|
1466
|
+
bidRequests.forEach((r) => r.timeout = timeout + 10000)
|
|
1467
|
+
}
|
|
1468
|
+
}).forEach(([test, setTimeout]) => {
|
|
1469
|
+
it(`should respect ${test} timeout if they never complete`, () => {
|
|
1470
|
+
const start = Date.now() - 2900;
|
|
1471
|
+
auction.getAuctionStart = () => start;
|
|
1472
|
+
setTimeout(3000);
|
|
1473
|
+
invokeCallbacks();
|
|
1474
|
+
return delay().then(() => {
|
|
1475
|
+
expect(doneSpy.called).to.be.false;
|
|
1476
|
+
return delay(100);
|
|
1477
|
+
}).then(() => {
|
|
1478
|
+
expect(doneSpy.called).to.be.true;
|
|
1479
|
+
});
|
|
1480
|
+
});
|
|
1481
|
+
|
|
1482
|
+
it(`should not wait if ${test} has already timed out`, () => {
|
|
1483
|
+
const start = Date.now() - 2000;
|
|
1484
|
+
auction.getAuctionStart = () => start;
|
|
1485
|
+
setTimeout(1000);
|
|
1486
|
+
invokeCallbacks();
|
|
1487
|
+
return delay().then(() => {
|
|
1488
|
+
expect(doneSpy.called).to.be.true;
|
|
1489
|
+
});
|
|
1490
|
+
});
|
|
1491
|
+
})
|
|
1492
|
+
});
|
|
1332
1493
|
});
|
|
1333
1494
|
|
|
1334
1495
|
describe('auctionOptions', function() {
|
|
1335
1496
|
let bidRequests;
|
|
1336
1497
|
let doneSpy;
|
|
1337
1498
|
let clock;
|
|
1338
|
-
let auction
|
|
1339
|
-
getBidRequests: () => bidRequests,
|
|
1340
|
-
getAuctionId: () => '1',
|
|
1341
|
-
addBidReceived: () => true,
|
|
1342
|
-
getTimeout: () => 1000
|
|
1343
|
-
}
|
|
1499
|
+
let auction;
|
|
1344
1500
|
let requiredBidder = BIDDER_CODE;
|
|
1345
1501
|
let requiredBidder1 = BIDDER_CODE1;
|
|
1346
1502
|
let secondaryBidder = 'doNotWaitForMe';
|
|
@@ -1352,7 +1508,15 @@ describe('auctionmanager.js', function () {
|
|
|
1352
1508
|
'auctionOptions': {
|
|
1353
1509
|
secondaryBidders: [ secondaryBidder ]
|
|
1354
1510
|
}
|
|
1355
|
-
})
|
|
1511
|
+
});
|
|
1512
|
+
const start = Date.now();
|
|
1513
|
+
auction = {
|
|
1514
|
+
getBidRequests: () => bidRequests,
|
|
1515
|
+
getAuctionId: () => '1',
|
|
1516
|
+
addBidReceived: () => true,
|
|
1517
|
+
getTimeout: () => 1000,
|
|
1518
|
+
getAuctionStart: () => start,
|
|
1519
|
+
}
|
|
1356
1520
|
});
|
|
1357
1521
|
|
|
1358
1522
|
afterEach(() => {
|
|
@@ -244,16 +244,6 @@ describe('Adagio bid adapter', () => {
|
|
|
244
244
|
expect(spec.isBidRequestValid(bid03)).to.equal(false);
|
|
245
245
|
expect(spec.isBidRequestValid(bid04)).to.equal(false);
|
|
246
246
|
});
|
|
247
|
-
|
|
248
|
-
it('should return false when refererInfo.reachedTop is false', function() {
|
|
249
|
-
sandbox.spy(utils, 'logWarn');
|
|
250
|
-
sandbox.stub(adagio, 'getRefererInfo').returns({ reachedTop: false });
|
|
251
|
-
const bid = new BidRequestBuilder().withParams().build();
|
|
252
|
-
|
|
253
|
-
expect(spec.isBidRequestValid(bid)).to.equal(false);
|
|
254
|
-
sinon.assert.callCount(utils.logWarn, 1);
|
|
255
|
-
sinon.assert.calledWith(utils.logWarn, 'Adagio: the main page url is unreachabled.');
|
|
256
|
-
});
|
|
257
247
|
});
|
|
258
248
|
|
|
259
249
|
describe('buildRequests()', function() {
|