prebid.js 5.19.0 → 5.20.3
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/.circleci/config.yml +4 -5
- package/modules/adxcgBidAdapter.js +311 -359
- package/modules/airgridRtdProvider.js +1 -1
- package/modules/appnexusBidAdapter.js +9 -3
- package/modules/atsAnalyticsAdapter.js +67 -46
- package/modules/atsAnalyticsAdapter.md +1 -0
- package/modules/betweenBidAdapter.js +2 -1
- package/modules/browsiRtdProvider.js +106 -18
- package/modules/cleanioRtdProvider.js +192 -0
- package/modules/cleanioRtdProvider.md +59 -0
- package/modules/deltaprojectsBidAdapter.js +252 -0
- package/modules/deltaprojectsBidAdapter.md +32 -0
- package/modules/gridBidAdapter.js +1 -0
- package/modules/ipromBidAdapter.js +79 -0
- package/modules/ixBidAdapter.js +7 -1
- package/modules/jixieBidAdapter.js +8 -2
- package/modules/justpremiumBidAdapter.js +6 -1
- package/modules/kinessoIdSystem.js +1 -1
- package/modules/livewrappedAnalyticsAdapter.js +5 -0
- package/modules/multibid/index.js +3 -3
- package/modules/nativoBidAdapter.js +5 -1
- package/modules/openxBidAdapter.js +1 -1
- package/modules/operaadsBidAdapter.js +21 -1
- package/modules/otmBidAdapter.js +146 -0
- package/modules/otmBidAdapter.md +27 -26
- package/modules/outbrainBidAdapter.js +5 -0
- package/modules/playwireBidAdapter.md +61 -0
- package/modules/pubmaticBidAdapter.js +1 -1
- package/modules/rtdModule/index.js +2 -2
- package/modules/sonobiBidAdapter.js +7 -0
- package/modules/sortableBidAdapter.js +1 -0
- package/modules/teadsBidAdapter.js +3 -0
- package/modules/trustxBidAdapter.js +8 -6
- package/modules/ventesBidAdapter.js +370 -0
- package/modules/ventesBidAdapter.md +94 -0
- package/modules/yahoosspBidAdapter.js +6 -6
- package/package.json +1 -1
- package/src/auction.js +11 -11
- package/src/prebid.js +20 -4
- package/src/targeting.js +8 -0
- package/test/fixtures/fixtures.js +2 -1
- package/test/spec/modules/adxcgBidAdapter_spec.js +827 -571
- package/test/spec/modules/appnexusBidAdapter_spec.js +16 -1
- package/test/spec/modules/atsAnalyticsAdapter_spec.js +42 -9
- package/test/spec/modules/browsiRtdProvider_spec.js +62 -7
- package/test/spec/modules/cleanioRtdProvider_spec.js +188 -0
- package/test/spec/modules/deltaprojectsBidAdapter_spec.js +399 -0
- package/test/spec/modules/eplanningBidAdapter_spec.js +8 -8
- package/test/spec/modules/ipromBidAdapter_spec.js +195 -0
- package/test/spec/modules/ixBidAdapter_spec.js +3 -3
- package/test/spec/modules/jixieBidAdapter_spec.js +13 -11
- package/test/spec/modules/justpremiumBidAdapter_spec.js +9 -2
- package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +23 -4
- package/test/spec/modules/multibid_spec.js +31 -31
- package/test/spec/modules/openxBidAdapter_spec.js +0 -26
- package/test/spec/modules/operaadsBidAdapter_spec.js +38 -6
- package/test/spec/modules/otmBidAdapter_spec.js +67 -0
- package/test/spec/modules/outbrainBidAdapter_spec.js +18 -0
- package/test/spec/modules/pubmaticBidAdapter_spec.js +40 -0
- package/test/spec/modules/sonobiBidAdapter_spec.js +34 -1
- package/test/spec/modules/sortableBidAdapter_spec.js +11 -0
- package/test/spec/modules/teadsBidAdapter_spec.js +132 -0
- package/test/spec/modules/trustxBidAdapter_spec.js +3 -3
- package/test/spec/modules/ventesBidAdapter_spec.js +845 -0
- package/test/spec/unit/core/adapterManager_spec.js +7 -3
- package/test/spec/unit/core/targeting_spec.js +93 -0
- package/test/spec/unit/pbjs_api_spec.js +3 -1
|
@@ -1047,7 +1047,8 @@ describe('AppNexusAdapter', function () {
|
|
|
1047
1047
|
'trackers': [
|
|
1048
1048
|
{
|
|
1049
1049
|
'impression_urls': [
|
|
1050
|
-
'https://lax1-ib.adnxs.com/impression'
|
|
1050
|
+
'https://lax1-ib.adnxs.com/impression',
|
|
1051
|
+
'https://www.test.com/tracker'
|
|
1051
1052
|
],
|
|
1052
1053
|
'video_events': {}
|
|
1053
1054
|
}
|
|
@@ -1334,6 +1335,20 @@ describe('AppNexusAdapter', function () {
|
|
|
1334
1335
|
expect(Object.keys(result[0].meta)).to.include.members(['advertiserId']);
|
|
1335
1336
|
});
|
|
1336
1337
|
|
|
1338
|
+
it('should add brand id', function() {
|
|
1339
|
+
let responseBrandId = deepClone(response);
|
|
1340
|
+
responseBrandId.tags[0].ads[0].brand_id = 123;
|
|
1341
|
+
|
|
1342
|
+
let bidderRequest = {
|
|
1343
|
+
bids: [{
|
|
1344
|
+
bidId: '3db3773286ee59',
|
|
1345
|
+
adUnitCode: 'code'
|
|
1346
|
+
}]
|
|
1347
|
+
}
|
|
1348
|
+
let result = spec.interpretResponse({ body: responseBrandId }, {bidderRequest});
|
|
1349
|
+
expect(Object.keys(result[0].meta)).to.include.members(['brandId']);
|
|
1350
|
+
});
|
|
1351
|
+
|
|
1337
1352
|
it('should add advertiserDomains', function() {
|
|
1338
1353
|
let responseAdvertiserId = deepClone(response);
|
|
1339
1354
|
responseAdvertiserId.tags[0].ads[0].adomain = ['123'];
|
|
@@ -12,11 +12,15 @@ let constants = require('src/constants.json');
|
|
|
12
12
|
|
|
13
13
|
export const storage = getStorageManager();
|
|
14
14
|
let sandbox;
|
|
15
|
+
let clock;
|
|
16
|
+
let now = new Date();
|
|
17
|
+
|
|
15
18
|
describe('ats analytics adapter', function () {
|
|
16
19
|
beforeEach(function () {
|
|
17
20
|
sinon.stub(events, 'getEvents').returns([]);
|
|
18
21
|
storage.setCookie('_lr_env_src_ats', 'true', 'Thu, 01 Jan 1970 00:00:01 GMT');
|
|
19
22
|
sandbox = sinon.sandbox.create();
|
|
23
|
+
clock = sandbox.useFakeTimers(now.getTime());
|
|
20
24
|
});
|
|
21
25
|
|
|
22
26
|
afterEach(function () {
|
|
@@ -25,18 +29,20 @@ describe('ats analytics adapter', function () {
|
|
|
25
29
|
atsAnalyticsAdapter.disableAnalytics();
|
|
26
30
|
Math.random.restore();
|
|
27
31
|
sandbox.restore();
|
|
32
|
+
clock.restore();
|
|
28
33
|
});
|
|
29
34
|
|
|
30
35
|
describe('track', function () {
|
|
31
36
|
it('builds and sends request and response data', function () {
|
|
32
37
|
sinon.stub(Math, 'random').returns(0.99);
|
|
33
|
-
sinon.stub(atsAnalyticsAdapter, 'shouldFireRequest').returns(true);
|
|
34
38
|
sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25');
|
|
35
|
-
|
|
39
|
+
|
|
36
40
|
now.setTime(now.getTime() + 3600000);
|
|
37
41
|
storage.setCookie('_lr_env_src_ats', 'true', now.toUTCString());
|
|
38
42
|
storage.setCookie('_lr_sampling_rate', '10', now.toUTCString());
|
|
39
43
|
|
|
44
|
+
this.timeout(2100);
|
|
45
|
+
|
|
40
46
|
let initOptions = {
|
|
41
47
|
pid: '10433394'
|
|
42
48
|
};
|
|
@@ -62,7 +68,7 @@ describe('ats analytics adapter', function () {
|
|
|
62
68
|
'refererInfo': {
|
|
63
69
|
'referer': 'https://example.com/dev'
|
|
64
70
|
},
|
|
65
|
-
'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7'
|
|
71
|
+
'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7'
|
|
66
72
|
};
|
|
67
73
|
// prepare general auction - response
|
|
68
74
|
let bidResponse = {
|
|
@@ -90,7 +96,7 @@ describe('ats analytics adapter', function () {
|
|
|
90
96
|
let expectedAfterBid = {
|
|
91
97
|
'Data': [{
|
|
92
98
|
'has_envelope': true,
|
|
93
|
-
'adapter_version':
|
|
99
|
+
'adapter_version': 3,
|
|
94
100
|
'bidder': 'appnexus',
|
|
95
101
|
'bid_id': '30c77d079cdf17',
|
|
96
102
|
'auction_id': 'a5b849e5-87d7-4205-8300-d063084fcfb7',
|
|
@@ -103,10 +109,30 @@ describe('ats analytics adapter', function () {
|
|
|
103
109
|
'response_time_stamp': '2020-02-03T14:23:11.978Z',
|
|
104
110
|
'currency': 'USD',
|
|
105
111
|
'cpm': 0.5,
|
|
106
|
-
'net_revenue': true
|
|
112
|
+
'net_revenue': true,
|
|
113
|
+
'bid_won': true
|
|
107
114
|
}]
|
|
108
115
|
};
|
|
109
116
|
|
|
117
|
+
let wonRequest = {
|
|
118
|
+
'adId': '2eddfdc0c791dc',
|
|
119
|
+
'mediaType': 'banner',
|
|
120
|
+
'requestId': '30c77d079cdf17',
|
|
121
|
+
'cpm': 0.5,
|
|
122
|
+
'creativeId': 29681110,
|
|
123
|
+
'currency': 'USD',
|
|
124
|
+
'netRevenue': true,
|
|
125
|
+
'ttl': 300,
|
|
126
|
+
'auctionId': 'a5b849e5-87d7-4205-8300-d063084fcfb7',
|
|
127
|
+
'statusMessage': 'Bid available',
|
|
128
|
+
'responseTimestamp': 1633525319061,
|
|
129
|
+
'requestTimestamp': 1633525319258,
|
|
130
|
+
'bidder': 'appnexus',
|
|
131
|
+
'adUnitCode': 'div-gpt-ad-1438287399331-0',
|
|
132
|
+
'size': '300x250',
|
|
133
|
+
'status': 'rendered'
|
|
134
|
+
};
|
|
135
|
+
|
|
110
136
|
// lets simulate that some bidders timeout
|
|
111
137
|
let bidTimeoutArgsV1 = [
|
|
112
138
|
{
|
|
@@ -148,6 +174,14 @@ describe('ats analytics adapter', function () {
|
|
|
148
174
|
|
|
149
175
|
// Step 5: Send auction end event
|
|
150
176
|
events.emit(constants.EVENTS.AUCTION_END, {});
|
|
177
|
+
// Step 6: Send bid won event
|
|
178
|
+
events.emit(constants.EVENTS.BID_WON, wonRequest);
|
|
179
|
+
|
|
180
|
+
sandbox.stub($$PREBID_GLOBAL$$, 'getAllWinningBids').callsFake((key) => {
|
|
181
|
+
return [wonRequest]
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
clock.tick(2000);
|
|
151
185
|
|
|
152
186
|
let requests = server.requests.filter(req => {
|
|
153
187
|
return req.url.indexOf(analyticsUrl) > -1;
|
|
@@ -156,13 +190,12 @@ describe('ats analytics adapter', function () {
|
|
|
156
190
|
expect(requests.length).to.equal(1);
|
|
157
191
|
|
|
158
192
|
let realAfterBid = JSON.parse(requests[0].requestBody);
|
|
159
|
-
|
|
193
|
+
|
|
194
|
+
// Step 7: assert real data after bid and expected data
|
|
160
195
|
expect(realAfterBid['Data']).to.deep.equal(expectedAfterBid['Data']);
|
|
161
196
|
|
|
162
197
|
// check that the publisher ID is configured via options
|
|
163
198
|
expect(atsAnalyticsAdapter.context.pid).to.equal(initOptions.pid);
|
|
164
|
-
|
|
165
|
-
atsAnalyticsAdapter.shouldFireRequest.restore();
|
|
166
199
|
})
|
|
167
200
|
it('check browser is safari', function () {
|
|
168
201
|
sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25');
|
|
@@ -204,7 +237,7 @@ describe('ats analytics adapter', function () {
|
|
|
204
237
|
sinon.stub(atsAnalyticsAdapter, 'getUserAgent').returns('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/536.25 (KHTML, like Gecko) Version/6.0 Safari/536.25');
|
|
205
238
|
sinon.stub(Math, 'random').returns(0.99);
|
|
206
239
|
// publisher can try to pass anything they want but we will set sampling rate to 100, which means we will have 1% of requests
|
|
207
|
-
let result = atsAnalyticsAdapter.shouldFireRequest(
|
|
240
|
+
let result = atsAnalyticsAdapter.shouldFireRequest(8);
|
|
208
241
|
expect(result).to.equal(true);
|
|
209
242
|
})
|
|
210
243
|
it('should not fire analytics request if math random is something other then 0.99', function () {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as browsiRTD from '../../../modules/browsiRtdProvider.js';
|
|
2
2
|
import {makeSlot} from '../integration/faker/googletag.js';
|
|
3
|
+
import * as utils from '../../../src/utils'
|
|
3
4
|
|
|
4
5
|
describe('browsi Real time data sub module', function () {
|
|
5
6
|
const conf = {
|
|
@@ -29,11 +30,11 @@ describe('browsi Real time data sub module', function () {
|
|
|
29
30
|
});
|
|
30
31
|
|
|
31
32
|
it('should match placement with ad unit', function () {
|
|
32
|
-
const slot = makeSlot({code: '/
|
|
33
|
+
const slot = makeSlot({code: '/123/abc', divId: 'browsiAd_1'});
|
|
33
34
|
|
|
34
|
-
const test1 = browsiRTD.isIdMatchingAdUnit(slot, ['/
|
|
35
|
-
const test2 = browsiRTD.isIdMatchingAdUnit(slot, ['/
|
|
36
|
-
const test3 = browsiRTD.isIdMatchingAdUnit(slot, ['/
|
|
35
|
+
const test1 = browsiRTD.isIdMatchingAdUnit(slot, ['/123/abc']); // true
|
|
36
|
+
const test2 = browsiRTD.isIdMatchingAdUnit(slot, ['/123/abc', '/456/def']); // true
|
|
37
|
+
const test3 = browsiRTD.isIdMatchingAdUnit(slot, ['/123/def']); // false
|
|
37
38
|
const test4 = browsiRTD.isIdMatchingAdUnit(slot, []); // true
|
|
38
39
|
|
|
39
40
|
expect(test1).to.equal(true);
|
|
@@ -43,12 +44,12 @@ describe('browsi Real time data sub module', function () {
|
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
it('should return correct macro values', function () {
|
|
46
|
-
const slot = makeSlot({code: '/
|
|
47
|
+
const slot = makeSlot({code: '/123/abc', divId: 'browsiAd_1'});
|
|
47
48
|
|
|
48
49
|
slot.setTargeting('test', ['test', 'value']);
|
|
49
50
|
// slot getTargeting doesn't act like GPT so we can't expect real value
|
|
50
51
|
const macroResult = browsiRTD.getMacroId({p: '<AD_UNIT>/<KEY_test>'}, slot);
|
|
51
|
-
expect(macroResult).to.equal('/
|
|
52
|
+
expect(macroResult).to.equal('/123/abc/NA');
|
|
52
53
|
|
|
53
54
|
const macroResultB = browsiRTD.getMacroId({}, slot);
|
|
54
55
|
expect(macroResultB).to.equal('browsiAd_1');
|
|
@@ -72,7 +73,7 @@ describe('browsi Real time data sub module', function () {
|
|
|
72
73
|
it('should return prediction from server', function () {
|
|
73
74
|
makeSlot({code: 'hasPrediction', divId: 'hasPrediction'});
|
|
74
75
|
const data = {
|
|
75
|
-
p: {'hasPrediction': {
|
|
76
|
+
p: {'hasPrediction': {ps: {0: 0.234}}},
|
|
76
77
|
kn: 'bv',
|
|
77
78
|
pmd: undefined
|
|
78
79
|
};
|
|
@@ -80,4 +81,58 @@ describe('browsi Real time data sub module', function () {
|
|
|
80
81
|
expect(browsiRTD.browsiSubmodule.getTargetingData(['hasPrediction'])).to.eql({hasPrediction: {bv: '0.20'}});
|
|
81
82
|
})
|
|
82
83
|
})
|
|
84
|
+
|
|
85
|
+
describe('should return matching prediction', function () {
|
|
86
|
+
const predictions = {
|
|
87
|
+
0: 0.123,
|
|
88
|
+
1: 0.254,
|
|
89
|
+
3: 0,
|
|
90
|
+
4: 0.8
|
|
91
|
+
}
|
|
92
|
+
const singlePrediction = {
|
|
93
|
+
0: 0.123
|
|
94
|
+
}
|
|
95
|
+
it('should return raw value if valid', function () {
|
|
96
|
+
expect(browsiRTD.getCurrentData(predictions, 0)).to.equal(0.123);
|
|
97
|
+
expect(browsiRTD.getCurrentData(predictions, 1)).to.equal(0.254);
|
|
98
|
+
})
|
|
99
|
+
it('should return 0 for prediction = 0', function () {
|
|
100
|
+
expect(browsiRTD.getCurrentData(predictions, 3)).to.equal(0);
|
|
101
|
+
})
|
|
102
|
+
it('should return -1 for invalid params', function () {
|
|
103
|
+
expect(browsiRTD.getCurrentData(null, 3)).to.equal(-1);
|
|
104
|
+
expect(browsiRTD.getCurrentData(predictions, null)).to.equal(-1);
|
|
105
|
+
})
|
|
106
|
+
it('should return prediction according to object keys length ', function () {
|
|
107
|
+
expect(browsiRTD.getCurrentData(singlePrediction, 0)).to.equal(0.123);
|
|
108
|
+
expect(browsiRTD.getCurrentData(singlePrediction, 1)).to.equal(-1);
|
|
109
|
+
expect(browsiRTD.getCurrentData(singlePrediction, 2)).to.equal(-1);
|
|
110
|
+
expect(browsiRTD.getCurrentData(predictions, 4)).to.equal(0.8);
|
|
111
|
+
expect(browsiRTD.getCurrentData(predictions, 5)).to.equal(0.8);
|
|
112
|
+
expect(browsiRTD.getCurrentData(predictions, 8)).to.equal(0.8);
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
describe('should set bid request data', function () {
|
|
116
|
+
const data = {
|
|
117
|
+
p: {
|
|
118
|
+
'adUnit1': {ps: {0: 0.234}},
|
|
119
|
+
'adUnit2': {ps: {0: 0.134}}},
|
|
120
|
+
kn: 'bv',
|
|
121
|
+
pmd: undefined
|
|
122
|
+
};
|
|
123
|
+
browsiRTD.setData(data);
|
|
124
|
+
const fakeAdUnits = [
|
|
125
|
+
{
|
|
126
|
+
code: 'adUnit1'
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
code: 'adUnit2'
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
browsiRTD.browsiSubmodule.getBidRequestData({adUnits: fakeAdUnits}, () => {}, {}, null);
|
|
133
|
+
it('should set ad unit params with prediction values', function () {
|
|
134
|
+
expect(utils.deepAccess(fakeAdUnits[0], 'ortb2Imp.ext.data.browsi')).to.eql({bv: '0.20'});
|
|
135
|
+
expect(utils.deepAccess(fakeAdUnits[1], 'ortb2Imp.ext.data.browsi')).to.eql({bv: '0.10'});
|
|
136
|
+
})
|
|
137
|
+
})
|
|
83
138
|
});
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as utils from '../../../src/utils.js';
|
|
2
|
+
import * as hook from '../../../src/hook.js'
|
|
3
|
+
|
|
4
|
+
import { __TEST__ } from '../../../modules/cleanioRtdProvider.js';
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
readConfig,
|
|
8
|
+
ConfigError,
|
|
9
|
+
pageInitStepPreloadScript,
|
|
10
|
+
pageInitStepProtectPage,
|
|
11
|
+
bidWrapStepAugmentHtml,
|
|
12
|
+
bidWrapStepProtectByWrapping,
|
|
13
|
+
beforeInit,
|
|
14
|
+
} = __TEST__;
|
|
15
|
+
|
|
16
|
+
sinon.assert.expose(chai.assert, { prefix: 'sinon' });
|
|
17
|
+
|
|
18
|
+
const fakeScriptURL = 'https://example.com/script.js';
|
|
19
|
+
|
|
20
|
+
function makeFakeBidResponse() {
|
|
21
|
+
return {
|
|
22
|
+
ad: '<body>hello ad</body>',
|
|
23
|
+
bidderCode: 'BIDDER',
|
|
24
|
+
creativeId: 'CREATIVE',
|
|
25
|
+
cpm: 1.23,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe('clean.io RTD module', function () {
|
|
30
|
+
describe('readConfig()', function() {
|
|
31
|
+
it('should throw ConfigError on invalid configurations', function() {
|
|
32
|
+
expect(() => readConfig({})).to.throw(ConfigError);
|
|
33
|
+
expect(() => readConfig({ params: {} })).to.throw(ConfigError);
|
|
34
|
+
expect(() => readConfig({ params: { protectionMode: 'bids' } })).to.throw(ConfigError);
|
|
35
|
+
expect(() => readConfig({ params: { cdnUrl: 'abc' } })).to.throw(ConfigError);
|
|
36
|
+
expect(() => readConfig({ params: { cdnUrl: 'abc', protectionMode: 'bids' } })).to.throw(ConfigError);
|
|
37
|
+
expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: '123' } })).to.throw(ConfigError);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should accept valid configurations', function() {
|
|
41
|
+
expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'full' } })).to.not.throw();
|
|
42
|
+
expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids' } })).to.not.throw();
|
|
43
|
+
expect(() => readConfig({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids-nowait' } })).to.not.throw();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('Module initialization step', function() {
|
|
48
|
+
let insertElementStub;
|
|
49
|
+
beforeEach(function() {
|
|
50
|
+
insertElementStub = sinon.stub(utils, 'insertElement');
|
|
51
|
+
});
|
|
52
|
+
afterEach(function() {
|
|
53
|
+
utils.insertElement.restore();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('pageInitStepPreloadScript() should insert link/preload element', function() {
|
|
57
|
+
pageInitStepPreloadScript(fakeScriptURL);
|
|
58
|
+
|
|
59
|
+
sinon.assert.calledOnce(insertElementStub);
|
|
60
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'LINK'));
|
|
61
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.rel === 'preload'));
|
|
62
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.as === 'script'));
|
|
63
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.href === fakeScriptURL));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('pageInitStepProtectPage() should insert script element', function() {
|
|
67
|
+
pageInitStepProtectPage(fakeScriptURL);
|
|
68
|
+
|
|
69
|
+
sinon.assert.calledOnce(insertElementStub);
|
|
70
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'SCRIPT'));
|
|
71
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.type === 'text/javascript'));
|
|
72
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.src === fakeScriptURL));
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
function ensurePrependToBidResponse(fakeBidResponse) {
|
|
77
|
+
expect(fakeBidResponse).to.have.own.property('ad').which.is.a('string');
|
|
78
|
+
expect(fakeBidResponse.ad).to.contain('<!-- pbad://creativeId=CREATIVE&bidderCode=BIDDER&cpm=1.23 -->');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function ensureWrapBidResponse(fakeBidResponse, scriptUrl) {
|
|
82
|
+
expect(fakeBidResponse).to.have.own.property('ad').which.is.a('string');
|
|
83
|
+
expect(fakeBidResponse.ad).to.contain(`src="${scriptUrl}"`);
|
|
84
|
+
expect(fakeBidResponse.ad).to.contain('agent.put(ad)');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
describe('Bid processing step', function() {
|
|
88
|
+
it('bidWrapStepAugmentHtml() should prepend bid-specific information in a comment', function() {
|
|
89
|
+
const fakeBidResponse = makeFakeBidResponse();
|
|
90
|
+
bidWrapStepAugmentHtml(fakeBidResponse);
|
|
91
|
+
ensurePrependToBidResponse(fakeBidResponse);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('bidWrapStepProtectByWrapping() should wrap payload into a script tag', function() {
|
|
95
|
+
const fakeBidResponse = makeFakeBidResponse();
|
|
96
|
+
bidWrapStepProtectByWrapping(fakeScriptURL, 0, fakeBidResponse);
|
|
97
|
+
ensureWrapBidResponse(fakeBidResponse, fakeScriptURL);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('Sumbodule execution', function() {
|
|
102
|
+
let submoduleStub;
|
|
103
|
+
let insertElementStub;
|
|
104
|
+
beforeEach(function () {
|
|
105
|
+
submoduleStub = sinon.stub(hook, 'submodule');
|
|
106
|
+
insertElementStub = sinon.stub(utils, 'insertElement');
|
|
107
|
+
});
|
|
108
|
+
afterEach(function () {
|
|
109
|
+
utils.insertElement.restore();
|
|
110
|
+
submoduleStub.restore();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
function getModule() {
|
|
114
|
+
beforeInit();
|
|
115
|
+
|
|
116
|
+
expect(submoduleStub.calledOnceWith('realTimeData')).to.equal(true);
|
|
117
|
+
|
|
118
|
+
const registeredSubmoduleDefinition = submoduleStub.getCall(0).args[1];
|
|
119
|
+
expect(registeredSubmoduleDefinition).to.be.an('object');
|
|
120
|
+
expect(registeredSubmoduleDefinition).to.have.own.property('name', 'clean.io');
|
|
121
|
+
expect(registeredSubmoduleDefinition).to.have.own.property('init').that.is.a('function');
|
|
122
|
+
expect(registeredSubmoduleDefinition).to.have.own.property('onBidResponseEvent').that.is.a('function');
|
|
123
|
+
|
|
124
|
+
return registeredSubmoduleDefinition;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
it('should register clean.io RTD submodule provider', function () {
|
|
128
|
+
getModule();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should refuse initialization with incorrect parameters', function () {
|
|
132
|
+
const { init } = getModule();
|
|
133
|
+
expect(init({ params: { cdnUrl: 'abc', protectionMode: 'full' } }, {})).to.equal(false); // too short distribution name
|
|
134
|
+
sinon.assert.notCalled(insertElementStub);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should iniitalize in full (page) protection mode', function () {
|
|
138
|
+
const { init, onBidResponseEvent } = getModule();
|
|
139
|
+
expect(init({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'full' } }, {})).to.equal(true);
|
|
140
|
+
sinon.assert.calledOnce(insertElementStub);
|
|
141
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'SCRIPT'));
|
|
142
|
+
|
|
143
|
+
const fakeBidResponse = makeFakeBidResponse();
|
|
144
|
+
onBidResponseEvent(fakeBidResponse, {}, {});
|
|
145
|
+
ensurePrependToBidResponse(fakeBidResponse);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should iniitalize in bids (frame) protection mode', function () {
|
|
149
|
+
const { init, onBidResponseEvent } = getModule();
|
|
150
|
+
expect(init({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids' } }, {})).to.equal(true);
|
|
151
|
+
sinon.assert.calledOnce(insertElementStub);
|
|
152
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'LINK'));
|
|
153
|
+
|
|
154
|
+
const fakeBidResponse = makeFakeBidResponse();
|
|
155
|
+
onBidResponseEvent(fakeBidResponse, {}, {});
|
|
156
|
+
ensureWrapBidResponse(fakeBidResponse, 'https://abc1234567890.cloudfront.net/script.js');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('should respect preload status in bids-nowait protection mode', function () {
|
|
160
|
+
const { init, onBidResponseEvent } = getModule();
|
|
161
|
+
expect(init({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'bids-nowait' } }, {})).to.equal(true);
|
|
162
|
+
sinon.assert.calledOnce(insertElementStub);
|
|
163
|
+
sinon.assert.calledWith(insertElementStub, sinon.match(elem => elem.tagName === 'LINK'));
|
|
164
|
+
const preloadLink = insertElementStub.getCall(0).args[0];
|
|
165
|
+
expect(preloadLink).to.have.property('onload').which.is.a('function');
|
|
166
|
+
expect(preloadLink).to.have.property('onerror').which.is.a('function');
|
|
167
|
+
|
|
168
|
+
const fakeBidResponse1 = makeFakeBidResponse();
|
|
169
|
+
onBidResponseEvent(fakeBidResponse1, {}, {});
|
|
170
|
+
ensurePrependToBidResponse(fakeBidResponse1);
|
|
171
|
+
|
|
172
|
+
// Simulate successful preloading
|
|
173
|
+
preloadLink.onload();
|
|
174
|
+
|
|
175
|
+
const fakeBidResponse2 = makeFakeBidResponse();
|
|
176
|
+
onBidResponseEvent(fakeBidResponse2, {}, {});
|
|
177
|
+
ensureWrapBidResponse(fakeBidResponse2, 'https://abc1234567890.cloudfront.net/script.js');
|
|
178
|
+
|
|
179
|
+
// Simulate error
|
|
180
|
+
preloadLink.onerror();
|
|
181
|
+
|
|
182
|
+
// Now we should fallback to just prepending
|
|
183
|
+
const fakeBidResponse3 = makeFakeBidResponse();
|
|
184
|
+
onBidResponseEvent(fakeBidResponse3, {}, {});
|
|
185
|
+
ensurePrependToBidResponse(fakeBidResponse3);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
});
|