prebid.js 6.6.0 → 6.7.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/integrationExamples/gpt/amp/creative.html +11 -33
- package/modules/adbookpspBidAdapter.js +27 -10
- package/modules/adhashBidAdapter.js +3 -3
- package/modules/colossussspBidAdapter.js +12 -8
- package/modules/colossussspBidAdapter.md +15 -1
- package/modules/compassBidAdapter.js +1 -1
- package/modules/consumableBidAdapter.md +1 -1
- package/modules/gnetBidAdapter.js +3 -3
- package/modules/gnetBidAdapter.md +4 -4
- package/modules/gumgumBidAdapter.js +4 -4
- package/modules/jwplayerRtdProvider.js +71 -6
- package/modules/jwplayerRtdProvider.md +27 -11
- package/modules/kargoBidAdapter.js +2 -2
- package/modules/pilotxBidAdapter.js +147 -0
- package/modules/pilotxBidAdapter.md +50 -0
- package/modules/rtdModule/index.js +8 -10
- package/modules/rubiconAnalyticsAdapter.js +3 -2
- package/modules/seedingAllianceBidAdapter.js +3 -3
- package/modules/sharethroughBidAdapter.js +12 -17
- package/modules/synacormediaBidAdapter.js +31 -10
- package/modules/viewability.js +177 -0
- package/modules/viewability.md +87 -0
- package/package.json +1 -1
- package/src/secureCreatives.js +3 -2
- package/test/spec/modules/adbookpspBidAdapter_spec.js +17 -3
- package/test/spec/modules/adhashBidAdapter_spec.js +2 -2
- package/test/spec/modules/colossussspBidAdapter_spec.js +5 -2
- package/test/spec/modules/gnetBidAdapter_spec.js +6 -6
- package/test/spec/modules/jwplayerRtdProvider_spec.js +195 -2
- package/test/spec/modules/kargoBidAdapter_spec.js +1 -1
- package/test/spec/modules/pilotxBidAdapter_spec.js +244 -0
- package/test/spec/modules/realTimeDataModule_spec.js +51 -2
- package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +30 -0
- package/test/spec/modules/sharethroughBidAdapter_spec.js +91 -6
- package/test/spec/modules/synacormediaBidAdapter_spec.js +70 -0
- package/test/spec/modules/viewability_spec.js +280 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { expect } from 'chai';
|
|
2
|
+
import * as sinon from 'sinon';
|
|
2
3
|
import { sharethroughAdapterSpec, sharethroughInternal } from 'modules/sharethroughBidAdapter.js';
|
|
3
4
|
import { newBidder } from 'src/adapters/bidderFactory.js';
|
|
4
5
|
import { config } from 'src/config';
|
|
@@ -157,7 +158,6 @@ describe('sharethrough adapter spec', function () {
|
|
|
157
158
|
startdelay: 42,
|
|
158
159
|
skipmin: 10,
|
|
159
160
|
skipafter: 20,
|
|
160
|
-
placement: 1,
|
|
161
161
|
delivery: 1,
|
|
162
162
|
companiontype: 'companion type',
|
|
163
163
|
companionad: 'companion ad',
|
|
@@ -205,6 +205,7 @@ describe('sharethrough adapter spec', function () {
|
|
|
205
205
|
expect(openRtbReq.cur).to.deep.equal(['USD']);
|
|
206
206
|
expect(openRtbReq.tmax).to.equal(242);
|
|
207
207
|
|
|
208
|
+
expect(Object.keys(openRtbReq.site)).to.have.length(3);
|
|
208
209
|
expect(openRtbReq.site.domain).not.to.be.undefined;
|
|
209
210
|
expect(openRtbReq.site.page).not.to.be.undefined;
|
|
210
211
|
expect(openRtbReq.site.ref).to.equal('https://referer.com');
|
|
@@ -256,6 +257,17 @@ describe('sharethrough adapter spec', function () {
|
|
|
256
257
|
});
|
|
257
258
|
});
|
|
258
259
|
|
|
260
|
+
describe('no referer provided', () => {
|
|
261
|
+
beforeEach(() => {
|
|
262
|
+
bidderRequest = {};
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should set referer to undefined', () => {
|
|
266
|
+
const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data;
|
|
267
|
+
expect(openRtbReq.site.ref).to.be.undefined;
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
259
271
|
describe('regulation', () => {
|
|
260
272
|
describe('gdpr', () => {
|
|
261
273
|
it('should populate request accordingly when gdpr applies', () => {
|
|
@@ -419,17 +431,90 @@ describe('sharethrough adapter spec', function () {
|
|
|
419
431
|
expect(videoImp.startdelay).to.equal(0);
|
|
420
432
|
expect(videoImp.skipmin).to.equal(0);
|
|
421
433
|
expect(videoImp.skipafter).to.equal(0);
|
|
422
|
-
expect(videoImp.placement).to.
|
|
434
|
+
expect(videoImp.placement).to.equal(1);
|
|
423
435
|
expect(videoImp.delivery).to.be.undefined;
|
|
424
436
|
expect(videoImp.companiontype).to.be.undefined;
|
|
425
437
|
expect(videoImp.companionad).to.be.undefined;
|
|
426
438
|
});
|
|
427
439
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
440
|
+
describe('outstream', () => {
|
|
441
|
+
it('should use placement value if provided', () => {
|
|
442
|
+
bidRequests[1].mediaTypes.video.context = 'outstream';
|
|
443
|
+
bidRequests[1].mediaTypes.video.placement = 3;
|
|
444
|
+
|
|
445
|
+
const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[1];
|
|
446
|
+
const videoImp = builtRequest.data.imp[0].video;
|
|
447
|
+
|
|
448
|
+
expect(videoImp.placement).to.equal(3);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('should default placement to 4 if not provided', () => {
|
|
452
|
+
bidRequests[1].mediaTypes.video.context = 'outstream';
|
|
453
|
+
|
|
454
|
+
const builtRequest = spec.buildRequests(bidRequests, bidderRequest)[1];
|
|
455
|
+
const videoImp = builtRequest.data.imp[0].video;
|
|
456
|
+
|
|
457
|
+
expect(videoImp.placement).to.equal(4);
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
describe('first party data', () => {
|
|
463
|
+
const firstPartyData = {
|
|
464
|
+
site: {
|
|
465
|
+
name: 'example',
|
|
466
|
+
keywords: 'power tools, drills',
|
|
467
|
+
search: 'drill',
|
|
468
|
+
content: {
|
|
469
|
+
userrating: '4',
|
|
470
|
+
},
|
|
471
|
+
ext: {
|
|
472
|
+
data: {
|
|
473
|
+
pageType: 'article',
|
|
474
|
+
category: 'repair',
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
user: {
|
|
479
|
+
yob: 1985,
|
|
480
|
+
gender: 'm',
|
|
481
|
+
ext: {
|
|
482
|
+
data: {
|
|
483
|
+
registered: true,
|
|
484
|
+
interests: ['cars'],
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
let configStub;
|
|
491
|
+
|
|
492
|
+
beforeEach(() => {
|
|
493
|
+
configStub = sinon.stub(config, 'getConfig');
|
|
494
|
+
configStub.withArgs('ortb2').returns(firstPartyData);
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
afterEach(() => {
|
|
498
|
+
configStub.restore();
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
it('should include first party data in open rtb request, site section', () => {
|
|
502
|
+
const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data;
|
|
503
|
+
|
|
504
|
+
expect(openRtbReq.site.name).to.equal(firstPartyData.site.name);
|
|
505
|
+
expect(openRtbReq.site.keywords).to.equal(firstPartyData.site.keywords);
|
|
506
|
+
expect(openRtbReq.site.search).to.equal(firstPartyData.site.search);
|
|
507
|
+
expect(openRtbReq.site.content).to.deep.equal(firstPartyData.site.content);
|
|
508
|
+
expect(openRtbReq.site.ext).to.deep.equal(firstPartyData.site.ext);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
it('should include first party data in open rtb request, user section', () => {
|
|
512
|
+
const openRtbReq = spec.buildRequests(bidRequests, bidderRequest)[0].data;
|
|
431
513
|
|
|
432
|
-
expect(
|
|
514
|
+
expect(openRtbReq.user.yob).to.equal(firstPartyData.user.yob);
|
|
515
|
+
expect(openRtbReq.user.gender).to.equal(firstPartyData.user.gender);
|
|
516
|
+
expect(openRtbReq.user.ext.data).to.deep.equal(firstPartyData.user.ext.data);
|
|
517
|
+
expect(openRtbReq.user.ext.eids).not.to.be.undefined;
|
|
433
518
|
});
|
|
434
519
|
});
|
|
435
520
|
});
|
|
@@ -1231,4 +1231,74 @@ describe('synacormediaBidAdapter ', function () {
|
|
|
1231
1231
|
expect(usersyncs).to.be.an('array').that.is.empty;
|
|
1232
1232
|
});
|
|
1233
1233
|
});
|
|
1234
|
+
|
|
1235
|
+
describe('Bid Requests with price module should use if available', function () {
|
|
1236
|
+
let validVideoBidRequest = {
|
|
1237
|
+
bidder: 'synacormedia',
|
|
1238
|
+
params: {
|
|
1239
|
+
bidfloor: '0.50',
|
|
1240
|
+
seatId: 'prebid',
|
|
1241
|
+
placementId: 'demo1',
|
|
1242
|
+
pos: 1,
|
|
1243
|
+
video: {}
|
|
1244
|
+
},
|
|
1245
|
+
renderer: {
|
|
1246
|
+
url: '../syncOutstreamPlayer.js'
|
|
1247
|
+
},
|
|
1248
|
+
mediaTypes: {
|
|
1249
|
+
video: {
|
|
1250
|
+
playerSize: [[300, 250]],
|
|
1251
|
+
context: 'outstream'
|
|
1252
|
+
}
|
|
1253
|
+
},
|
|
1254
|
+
adUnitCode: 'div-1',
|
|
1255
|
+
transactionId: '0869f34e-090b-4b20-84ee-46ff41405a39',
|
|
1256
|
+
sizes: [[300, 250]],
|
|
1257
|
+
bidId: '22b3a2268d9f0e',
|
|
1258
|
+
bidderRequestId: '1d195910597e13',
|
|
1259
|
+
auctionId: '3375d336-2aea-4ee7-804c-6d26b621ad20',
|
|
1260
|
+
src: 'client',
|
|
1261
|
+
bidRequestsCount: 1,
|
|
1262
|
+
bidderRequestsCount: 1,
|
|
1263
|
+
bidderWinsCount: 0
|
|
1264
|
+
};
|
|
1265
|
+
|
|
1266
|
+
let validBannerBidRequest = {
|
|
1267
|
+
bidId: '9876abcd',
|
|
1268
|
+
sizes: [[300, 250]],
|
|
1269
|
+
params: {
|
|
1270
|
+
bidfloor: '0.50',
|
|
1271
|
+
seatId: 'prebid',
|
|
1272
|
+
placementId: '1234',
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
|
|
1276
|
+
let bidderRequest = {
|
|
1277
|
+
refererInfo: {
|
|
1278
|
+
referer: 'http://localhost:9999/'
|
|
1279
|
+
},
|
|
1280
|
+
bidderCode: 'synacormedia',
|
|
1281
|
+
auctionId: 'f8a75621-d672-4cbb-9275-3db7d74fb110'
|
|
1282
|
+
};
|
|
1283
|
+
|
|
1284
|
+
it('should return valid bidfloor using price module for banner/video impression', function () {
|
|
1285
|
+
let bannerRequest = spec.buildRequests([validBannerBidRequest], bidderRequest);
|
|
1286
|
+
let videoRequest = spec.buildRequests([validVideoBidRequest], bidderRequest);
|
|
1287
|
+
|
|
1288
|
+
expect(bannerRequest.data.imp[0].bidfloor).to.equal(0.5);
|
|
1289
|
+
expect(videoRequest.data.imp[0].bidfloor).to.equal(0.5);
|
|
1290
|
+
|
|
1291
|
+
let priceModuleFloor = 3;
|
|
1292
|
+
let floorResponse = { currency: 'USD', floor: priceModuleFloor };
|
|
1293
|
+
|
|
1294
|
+
validBannerBidRequest.getFloor = () => { return floorResponse; };
|
|
1295
|
+
validVideoBidRequest.getFloor = () => { return floorResponse; };
|
|
1296
|
+
|
|
1297
|
+
bannerRequest = spec.buildRequests([validBannerBidRequest], bidderRequest);
|
|
1298
|
+
videoRequest = spec.buildRequests([validVideoBidRequest], bidderRequest);
|
|
1299
|
+
|
|
1300
|
+
expect(bannerRequest.data.imp[0].bidfloor).to.equal(priceModuleFloor);
|
|
1301
|
+
expect(videoRequest.data.imp[0].bidfloor).to.equal(priceModuleFloor);
|
|
1302
|
+
});
|
|
1303
|
+
});
|
|
1234
1304
|
});
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import * as sinon from 'sinon';
|
|
3
|
+
import * as utils from 'src/utils.js';
|
|
4
|
+
import * as viewability from 'modules/viewability.js';
|
|
5
|
+
|
|
6
|
+
describe('viewability test', () => {
|
|
7
|
+
describe('start measurement', () => {
|
|
8
|
+
let sandbox;
|
|
9
|
+
let intersectionObserverStub;
|
|
10
|
+
let setTimeoutStub;
|
|
11
|
+
let observeCalled;
|
|
12
|
+
let unobserveCalled;
|
|
13
|
+
let ti = 1;
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
observeCalled = false;
|
|
16
|
+
unobserveCalled = false;
|
|
17
|
+
sandbox = sinon.sandbox.create();
|
|
18
|
+
|
|
19
|
+
let fakeIntersectionObserver = (stateChange, options) => {
|
|
20
|
+
return {
|
|
21
|
+
observe: (element) => {
|
|
22
|
+
observeCalled = true;
|
|
23
|
+
stateChange([{ isIntersecting: true }]);
|
|
24
|
+
},
|
|
25
|
+
unobserve: (element) => {
|
|
26
|
+
unobserveCalled = true;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
intersectionObserverStub = sandbox.stub(window, 'IntersectionObserver').callsFake(fakeIntersectionObserver);
|
|
32
|
+
setTimeoutStub = sandbox.stub(window, 'setTimeout').callsFake((callback, timeout) => {
|
|
33
|
+
callback();
|
|
34
|
+
return ti++;
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
sandbox.restore();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should trigger appropriate callbacks', () => {
|
|
43
|
+
viewability.startMeasurement('0', {}, { method: 'img', value: 'http://my.tracker/123' }, { inViewThreshold: 0.5, timeInView: 1000 });
|
|
44
|
+
|
|
45
|
+
sinon.assert.called(intersectionObserverStub);
|
|
46
|
+
sinon.assert.called(setTimeoutStub);
|
|
47
|
+
expect(observeCalled).to.equal(true);
|
|
48
|
+
expect(unobserveCalled).to.equal(true);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should trigger img tracker', () => {
|
|
52
|
+
let triggerPixelSpy = sandbox.spy(utils, ['triggerPixel']);
|
|
53
|
+
viewability.startMeasurement('1', {}, { method: 'img', value: 'http://my.tracker/123' }, { inViewThreshold: 0.5, timeInView: 1000 });
|
|
54
|
+
expect(triggerPixelSpy.callCount).to.equal(1);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should trigger js tracker', () => {
|
|
58
|
+
let insertHtmlIntoIframeSpy = sandbox.spy(utils, ['insertHtmlIntoIframe']);
|
|
59
|
+
viewability.startMeasurement('2', {}, { method: 'js', value: 'http://my.tracker/123.js' }, { inViewThreshold: 0.5, timeInView: 1000 });
|
|
60
|
+
expect(insertHtmlIntoIframeSpy.callCount).to.equal(1);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should trigger callback tracker', () => {
|
|
64
|
+
let callbackFired = false;
|
|
65
|
+
viewability.startMeasurement('3', {}, { method: 'callback', value: () => { callbackFired = true; } }, { inViewThreshold: 0.5, timeInView: 1000 });
|
|
66
|
+
expect(callbackFired).to.equal(true);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should check for vid uniqueness', () => {
|
|
70
|
+
let logWarnSpy = sandbox.spy(utils, 'logWarn');
|
|
71
|
+
viewability.startMeasurement('4', {}, { method: 'js', value: 'http://my.tracker/123.js' }, { inViewThreshold: 0.5, timeInView: 1000 });
|
|
72
|
+
expect(logWarnSpy.callCount).to.equal(0);
|
|
73
|
+
|
|
74
|
+
viewability.startMeasurement('4', {}, { method: 'js', value: 'http://my.tracker/123.js' }, { inViewThreshold: 0.5, timeInView: 1000 });
|
|
75
|
+
expect(logWarnSpy.callCount).to.equal(1);
|
|
76
|
+
expect(logWarnSpy.calledWith(`${viewability.MODULE_NAME}: must provide an unregistered vid`, '4')).to.equal(true);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should check for valid criteria', () => {
|
|
80
|
+
let logWarnSpy = sandbox.spy(utils, 'logWarn');
|
|
81
|
+
viewability.startMeasurement('5', {}, { method: 'js', value: 'http://my.tracker/123.js' }, { timeInView: 1000 });
|
|
82
|
+
expect(logWarnSpy.callCount).to.equal(1);
|
|
83
|
+
expect(logWarnSpy.calledWith(`${viewability.MODULE_NAME}: missing criteria`, { timeInView: 1000 })).to.equal(true);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should check for valid tracker', () => {
|
|
87
|
+
let logWarnSpy = sandbox.spy(utils, 'logWarn');
|
|
88
|
+
viewability.startMeasurement('6', {}, { method: 'callback', value: 'string' }, { inViewThreshold: 0.5, timeInView: 1000 });
|
|
89
|
+
expect(logWarnSpy.callCount).to.equal(1);
|
|
90
|
+
expect(logWarnSpy.calledWith(`${viewability.MODULE_NAME}: invalid tracker`, { method: 'callback', value: 'string' })).to.equal(true);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should check if element provided', () => {
|
|
94
|
+
let logWarnSpy = sandbox.spy(utils, 'logWarn');
|
|
95
|
+
viewability.startMeasurement('7', undefined, { method: 'js', value: 'http://my.tracker/123.js' }, { timeInView: 1000 });
|
|
96
|
+
expect(logWarnSpy.callCount).to.equal(1);
|
|
97
|
+
expect(logWarnSpy.calledWith(`${viewability.MODULE_NAME}: no html element provided`)).to.equal(true);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('stop measurement', () => {
|
|
102
|
+
let sandbox;
|
|
103
|
+
let intersectionObserverStub;
|
|
104
|
+
let setTimeoutStub;
|
|
105
|
+
let clearTimeoutStub;
|
|
106
|
+
let observeCalled;
|
|
107
|
+
let unobserveCalled;
|
|
108
|
+
let stateChangeBackup;
|
|
109
|
+
let ti = 1;
|
|
110
|
+
beforeEach(() => {
|
|
111
|
+
observeCalled = false;
|
|
112
|
+
unobserveCalled = false;
|
|
113
|
+
sandbox = sinon.sandbox.create();
|
|
114
|
+
|
|
115
|
+
let fakeIntersectionObserver = (stateChange, options) => {
|
|
116
|
+
return {
|
|
117
|
+
observe: (element) => {
|
|
118
|
+
stateChangeBackup = stateChange;
|
|
119
|
+
observeCalled = true;
|
|
120
|
+
stateChange([{ isIntersecting: true }]);
|
|
121
|
+
},
|
|
122
|
+
unobserve: (element) => {
|
|
123
|
+
unobserveCalled = true;
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
intersectionObserverStub = sandbox.stub(window, 'IntersectionObserver').callsFake(fakeIntersectionObserver);
|
|
129
|
+
setTimeoutStub = sandbox.stub(window, 'setTimeout').callsFake((callback, timeout) => {
|
|
130
|
+
// skipping the callback
|
|
131
|
+
return ti++;
|
|
132
|
+
});
|
|
133
|
+
clearTimeoutStub = sandbox.stub(window, 'clearTimeout').callsFake((timeoutId) => { });
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
afterEach(() => {
|
|
137
|
+
sandbox.restore();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should clear the timeout', () => {
|
|
141
|
+
viewability.startMeasurement('10', {}, { method: 'img', value: 'http://my.tracker/123' }, { inViewThreshold: 0.5, timeInView: 1000 });
|
|
142
|
+
stateChangeBackup([{ isIntersecting: false }]);
|
|
143
|
+
sinon.assert.called(intersectionObserverStub);
|
|
144
|
+
sinon.assert.called(setTimeoutStub);
|
|
145
|
+
sinon.assert.called(clearTimeoutStub);
|
|
146
|
+
expect(observeCalled).to.equal(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should unobserve', () => {
|
|
150
|
+
viewability.startMeasurement('11', {}, { method: 'img', value: 'http://my.tracker/123' }, { inViewThreshold: 0.5, timeInView: 1000 });
|
|
151
|
+
sinon.assert.called(intersectionObserverStub);
|
|
152
|
+
sinon.assert.called(setTimeoutStub);
|
|
153
|
+
expect(observeCalled).to.equal(true);
|
|
154
|
+
expect(unobserveCalled).to.equal(false);
|
|
155
|
+
|
|
156
|
+
viewability.stopMeasurement('11');
|
|
157
|
+
expect(unobserveCalled).to.equal(true);
|
|
158
|
+
sinon.assert.called(clearTimeoutStub);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should check for vid existence', () => {
|
|
162
|
+
let logWarnSpy = sandbox.spy(utils, 'logWarn');
|
|
163
|
+
viewability.stopMeasurement('100');
|
|
164
|
+
expect(logWarnSpy.callCount).to.equal(1);
|
|
165
|
+
expect(logWarnSpy.calledWith(`${viewability.MODULE_NAME}: must provide a registered vid`, '100')).to.equal(true);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe('handle creative messages', () => {
|
|
170
|
+
let sandbox;
|
|
171
|
+
let intersectionObserverStub;
|
|
172
|
+
let setTimeoutStub;
|
|
173
|
+
let observeCalled;
|
|
174
|
+
let unobserveCalled;
|
|
175
|
+
let ti = 1;
|
|
176
|
+
let getElementsByTagStub;
|
|
177
|
+
let getElementByIdStub;
|
|
178
|
+
|
|
179
|
+
let fakeContentWindow = {};
|
|
180
|
+
beforeEach(() => {
|
|
181
|
+
observeCalled = false;
|
|
182
|
+
unobserveCalled = false;
|
|
183
|
+
sandbox = sinon.sandbox.create();
|
|
184
|
+
|
|
185
|
+
let fakeIntersectionObserver = (stateChange, options) => {
|
|
186
|
+
return {
|
|
187
|
+
observe: (element) => {
|
|
188
|
+
observeCalled = true;
|
|
189
|
+
stateChange([{ isIntersecting: true }]);
|
|
190
|
+
},
|
|
191
|
+
unobserve: (element) => {
|
|
192
|
+
unobserveCalled = true;
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
intersectionObserverStub = sandbox.stub(window, 'IntersectionObserver').callsFake(fakeIntersectionObserver);
|
|
198
|
+
setTimeoutStub = sandbox.stub(window, 'setTimeout').callsFake((callback, timeout) => {
|
|
199
|
+
callback();
|
|
200
|
+
return ti++;
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
getElementsByTagStub = sandbox.stub(document, 'getElementsByTagName').callsFake((tagName) => {
|
|
204
|
+
return [{
|
|
205
|
+
contentWindow: fakeContentWindow,
|
|
206
|
+
}];
|
|
207
|
+
});
|
|
208
|
+
getElementByIdStub = sandbox.stub(document, 'getElementById').callsFake((id) => {
|
|
209
|
+
return {};
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
afterEach(() => {
|
|
214
|
+
sandbox.restore();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should find element by contentWindow', () => {
|
|
218
|
+
let viewabilityRecord = {
|
|
219
|
+
vid: 1000,
|
|
220
|
+
tracker: {
|
|
221
|
+
value: 'http://my.tracker/123',
|
|
222
|
+
method: 'img',
|
|
223
|
+
},
|
|
224
|
+
criteria: { inViewThreshold: 0.5, timeInView: 1000 },
|
|
225
|
+
message: 'Prebid Viewability',
|
|
226
|
+
action: 'startMeasurement',
|
|
227
|
+
};
|
|
228
|
+
let data = JSON.stringify(viewabilityRecord);
|
|
229
|
+
|
|
230
|
+
viewability.receiveMessage({
|
|
231
|
+
data: data,
|
|
232
|
+
source: fakeContentWindow,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
sinon.assert.called(getElementsByTagStub);
|
|
236
|
+
sinon.assert.called(intersectionObserverStub);
|
|
237
|
+
sinon.assert.called(setTimeoutStub);
|
|
238
|
+
expect(observeCalled).to.equal(true);
|
|
239
|
+
expect(unobserveCalled).to.equal(true);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('should find element by id', () => {
|
|
243
|
+
let viewabilityRecord = {
|
|
244
|
+
vid: 1001,
|
|
245
|
+
tracker: {
|
|
246
|
+
value: 'http://my.tracker/123',
|
|
247
|
+
method: 'img',
|
|
248
|
+
},
|
|
249
|
+
criteria: { inViewThreshold: 0.5, timeInView: 1000 },
|
|
250
|
+
message: 'Prebid Viewability',
|
|
251
|
+
action: 'startMeasurement',
|
|
252
|
+
elementId: '1',
|
|
253
|
+
};
|
|
254
|
+
let data = JSON.stringify(viewabilityRecord);
|
|
255
|
+
viewability.receiveMessage({
|
|
256
|
+
data: data,
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
sinon.assert.called(getElementByIdStub);
|
|
260
|
+
sinon.assert.called(intersectionObserverStub);
|
|
261
|
+
sinon.assert.called(setTimeoutStub);
|
|
262
|
+
expect(observeCalled).to.equal(true);
|
|
263
|
+
expect(unobserveCalled).to.equal(true);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('should stop measurement', () => {
|
|
267
|
+
let viewabilityRecord = {
|
|
268
|
+
vid: 1001,
|
|
269
|
+
message: 'Prebid Viewability',
|
|
270
|
+
action: 'stopMeasurement',
|
|
271
|
+
};
|
|
272
|
+
let data = JSON.stringify(viewabilityRecord);
|
|
273
|
+
viewability.receiveMessage({
|
|
274
|
+
data: data,
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
expect(unobserveCalled).to.equal(true);
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
});
|