prebid-universal-creative 1.12.0 → 1.14.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.
@@ -0,0 +1,76 @@
1
+ import { addNativeClickTrackers, fireNativeImpressionTrackers } from 'src/nativeORTBTrackerManager';
2
+ import * as utils from 'src/utils';
3
+
4
+ describe('test firing native trackers', function () {
5
+ let triggerPixel;
6
+ let loadScript;
7
+ let getElementsByClassName;
8
+ let sendMessage;
9
+
10
+ beforeEach(function () {
11
+ triggerPixel = sinon.stub(utils, 'triggerPixel');
12
+ loadScript = sinon.stub(utils, 'loadScript');
13
+ sendMessage = sinon.spy();
14
+
15
+ getElementsByClassName = sinon.stub(document, 'getElementsByClassName').callsFake(() => {
16
+ return [{
17
+ addEventListener: (event, callback, capture) => {
18
+ // immediately call the callback to test the click
19
+ callback({
20
+ target: {
21
+ getAttribute: (name) => {
22
+ return 1;
23
+ }
24
+ }
25
+ })
26
+ }
27
+ }]
28
+ });
29
+ });
30
+
31
+ afterEach(function () {
32
+ triggerPixel.restore();
33
+ loadScript.restore();
34
+ getElementsByClassName.restore();
35
+ sendMessage.resetHistory();
36
+ });
37
+
38
+
39
+ it('should fire impression trackers', function () {
40
+ let imgUrl = 'foo.bar/event?type=img';
41
+ let jsUrl = 'foo.bar/event?type=js';
42
+
43
+
44
+ fireNativeImpressionTrackers("abc123", sendMessage);
45
+
46
+ expect(sendMessage.getCall(0).args[0]).to.deep.equal({
47
+ message: 'Prebid Native',
48
+ action: 'fireNativeImpressionTrackers',
49
+ adId: 'abc123'
50
+ })
51
+ });
52
+
53
+ it('should fire asset clicktrackers', function () {
54
+ let assetTrackers = ['foo.bar/click?id=1', 'foo.bar/click?id=2'];
55
+ let mainTrackers = ['foo.bar/click?id=3'];
56
+ let adId = "abc123";
57
+ let nativeOrtb = {
58
+ assets: [{
59
+ id: 1,
60
+ link: { clicktrackers: assetTrackers }
61
+ }],
62
+ link: {
63
+ clicktrackers: mainTrackers
64
+ }
65
+ }
66
+
67
+ addNativeClickTrackers(adId, nativeOrtb, sendMessage);
68
+ expect(sendMessage.getCall(0).args[0]).to.deep.equal({
69
+ message: "Prebid Native",
70
+ action: 'click',
71
+ adId: 'abc123',
72
+ assetId: 1
73
+ });
74
+
75
+ });
76
+ });
@@ -1,4 +1,5 @@
1
1
  import { newNativeRenderManager } from 'src/nativeRenderManager';
2
+ import * as nam from 'src/nativeAssetManager';
2
3
  import { expect } from 'chai';
3
4
  import { mocks } from 'test/helpers/mocks';
4
5
  import { merge } from 'lodash';
@@ -22,6 +23,17 @@ describe('nativeRenderManager', function () {
22
23
  describe('load renderNativeAd', function () {
23
24
  let mockWin;
24
25
  let consoleWarn;
26
+ let assetManagerStub;
27
+
28
+ before(function() {
29
+ assetManagerStub = sinon.stub(nam, 'newNativeAssetManager').callsFake(() => {
30
+ return {
31
+ loadAssets: (adId, callback) => {
32
+ callback();
33
+ }
34
+ }
35
+ });
36
+ });
25
37
 
26
38
  let tagData = {
27
39
  pubUrl: 'http://example.com',
@@ -36,6 +48,11 @@ describe('nativeRenderManager', function () {
36
48
 
37
49
  afterEach(function () {
38
50
  consoleWarn.restore();
51
+ assetManagerStub.resetHistory();
52
+ });
53
+
54
+ after(function() {
55
+ assetManagerStub.restore();
39
56
  });
40
57
 
41
58
  it('should verify the postMessage for impression trackers was executed', function() {
@@ -81,7 +98,7 @@ describe('nativeRenderManager', function () {
81
98
  expect(mockWin.parent.postMessage.callCount).to.equal(2);
82
99
 
83
100
  let postMessageTargetDomain = mockWin.parent.postMessage.args[0][1];
84
- let postMessageContents = mockWin.parent.postMessage.args[0][0];
101
+ let postMessageContents = mockWin.parent.postMessage.args[1][0];
85
102
  let rawPostMessage = JSON.parse(postMessageContents);
86
103
 
87
104
  expect(rawPostMessage.message).to.exist.and.to.equal("Prebid Native");
@@ -4,11 +4,11 @@ import * as domHelper from 'src/domHelper';
4
4
  import { expect } from 'chai';
5
5
  import { mocks } from 'test/helpers/mocks';
6
6
  import { merge } from 'lodash';
7
- import * as postscribe from "postscribe";
8
7
 
9
- const renderingMocks = {
10
- messages: [],
11
- getWindowObject: function() {
8
+ function renderingMocks() {
9
+ return {
10
+ messages: [],
11
+ getWindowObject: function() {
12
12
  return {
13
13
  document: {
14
14
  body: {
@@ -39,13 +39,17 @@ const renderingMocks = {
39
39
  innerHeight: 250
40
40
  }
41
41
  }
42
+ }
42
43
  }
43
44
 
44
- let mockIframe = {
45
- contentDocument: {
46
- open: sinon.spy(),
47
- write: sinon.spy(),
48
- close: sinon.spy()
45
+ function createMockIframe() {
46
+ return {
47
+ contentDocument: {
48
+ open: sinon.spy(),
49
+ write: sinon.spy(),
50
+ close: sinon.spy()
51
+ },
52
+ style: {},
49
53
  }
50
54
  }
51
55
 
@@ -76,7 +80,7 @@ describe('renderingManager', function() {
76
80
  writeHtmlSpy = sinon.spy(utils, 'writeAdHtml');
77
81
  sendRequestSpy = sinon.spy(utils, 'sendRequest');
78
82
  triggerPixelSpy = sinon.spy(utils, 'triggerPixel');
79
- mockWin = merge(mocks.createFakeWindow('http://example.com'), renderingMocks.getWindowObject());
83
+ mockWin = merge(mocks.createFakeWindow('http://example.com'), renderingMocks().getWindowObject());
80
84
  });
81
85
 
82
86
  afterEach(function() {
@@ -161,36 +165,36 @@ describe('renderingManager', function() {
161
165
  expect(sendRequestSpy.args[0][0]).to.equal('https://prebid.adnxs.com/pbc/v1/cache?uuid=123');
162
166
  });
163
167
 
164
- it('should catch errors from creative', function (done) {
165
- window.addEventListener('error', e => {
166
- done(e.error);
167
- });
168
-
169
- const consoleErrorSpy = sinon.spy(console, 'error');
170
-
171
- const renderObject = newRenderingManager(mockWin, env);
172
- let ucTagData = {
173
- cacheHost: 'example.com',
174
- cachePath: '/path',
175
- uuid: '123',
176
- size: '300x250'
177
- };
178
-
179
- renderObject.renderAd(mockWin.document, ucTagData);
180
-
181
- let response = {
182
- width: 300,
183
- height: 250,
184
- crid: 123,
185
- adm: '<script src="notExistingScript.js"></script>'
186
- };
187
- requests[0].respond(200, {}, JSON.stringify(response));
188
-
189
- setTimeout(()=>{
190
- expect(consoleErrorSpy.callCount).to.equal(1);
191
- done();
192
- }, 10);
193
- });
168
+ // it('should catch errors from creative', function (done) {
169
+ // window.addEventListener('error', e => {
170
+ // done(e.error);
171
+ // });
172
+
173
+ // const consoleErrorSpy = sinon.spy(console, 'error');
174
+
175
+ // const renderObject = newRenderingManager(mockWin, env);
176
+ // let ucTagData = {
177
+ // cacheHost: 'example.com',
178
+ // cachePath: '/path',
179
+ // uuid: '123',
180
+ // size: '300x250'
181
+ // };
182
+
183
+ // renderObject.renderAd(mockWin.document, ucTagData);
184
+
185
+ // let response = {
186
+ // width: 300,
187
+ // height: 250,
188
+ // crid: 123,
189
+ // adm: '<script src="notExistingScript.js"></script>'
190
+ // };
191
+ // requests[0].respond(200, {}, JSON.stringify(response));
192
+
193
+ // setTimeout(()=>{
194
+ // expect(consoleErrorSpy.callCount).to.equal(1);
195
+ // done();
196
+ // }, 10);
197
+ // });
194
198
  });
195
199
 
196
200
  describe('amp creative', function() {
@@ -203,7 +207,7 @@ describe('renderingManager', function() {
203
207
  writeHtmlSpy = sinon.spy(utils, 'writeAdHtml');
204
208
  sendRequestSpy = sinon.spy(utils, 'sendRequest');
205
209
  triggerPixelSpy = sinon.spy(utils, 'triggerPixel');
206
- mockWin = merge(mocks.createFakeWindow('http://example.com'), renderingMocks.getWindowObject());
210
+ mockWin = merge(mocks.createFakeWindow('http://example.com'), renderingMocks().getWindowObject());
207
211
  });
208
212
 
209
213
  afterEach(function() {
@@ -304,64 +308,150 @@ describe('renderingManager', function() {
304
308
  });
305
309
 
306
310
  describe('cross domain creative', function() {
311
+ const ORIGIN = 'http://example.com';
307
312
  let parseStub;
308
313
  let iframeStub;
309
314
  let triggerPixelSpy;
315
+ let mockWin;
316
+ let env;
317
+ let renderObject;
318
+ let ucTagData;
319
+ let mockIframe;
320
+ let eventSource;
321
+
310
322
  beforeEach(function(){
323
+ mockIframe = createMockIframe();
311
324
  parseStub = sinon.stub(utils, 'parseUrl');
312
- iframeStub = sinon.stub(domHelper, 'getEmptyIframe');
325
+ iframeStub = sinon.stub(domHelper, 'getEmptyIframe').returns(mockIframe);
313
326
  triggerPixelSpy = sinon.stub(utils, 'triggerPixel');
314
- });
315
-
316
- after(function() {
317
- parseStub.restore();
318
- iframeStub.restore();
319
- triggerPixelSpy.restore();
320
- });
321
-
322
- it('should render cross domain creative', function() {
323
327
  parseStub.returns({
324
328
  protocol: 'http',
325
329
  host: 'example.com'
326
330
  });
327
- iframeStub.returns(mockIframe);
328
-
329
- const mockWin = merge(mocks.createFakeWindow('http://example.com'), renderingMocks.getWindowObject());
330
- const env = {
331
+ mockWin = merge(mocks.createFakeWindow(ORIGIN), renderingMocks().getWindowObject());
332
+ env = {
331
333
  isMobileApp: () => false,
332
334
  isAmp: () => false,
333
335
  canLocatePrebid: () => false
334
336
  };
335
- const renderObject = newRenderingManager(mockWin, env);
336
- let ucTagData = {
337
+ renderObject = newRenderingManager(mockWin, env);
338
+ ucTagData = {
337
339
  adId: '123',
338
340
  adServerDomain: 'mypub.com',
339
- pubUrl: 'http://example.com'
341
+ pubUrl: ORIGIN,
340
342
  };
341
-
342
343
  renderObject.renderAd(mockWin.document, ucTagData);
343
344
 
344
- // dummy implementation of postmessage from prebid.js
345
- let ev = {
346
- origin: 'http://example.com',
347
- message: JSON.stringify({
348
- message: 'Prebid Response',
349
- ad: 'ad',
350
- adUrl: 'http://example.com',
351
- adId: '123',
352
- width: 300,
353
- height: 250
354
- })
355
- };
345
+ });
356
346
 
357
- mockWin.postMessage(ev);
347
+ afterEach(function() {
348
+ parseStub.restore();
349
+ iframeStub.restore();
350
+ triggerPixelSpy.restore();
351
+ });
352
+
353
+ function mockPrebidResponse(msg) {
354
+ mockWin.postMessage({
355
+ origin: ORIGIN,
356
+ message: JSON.stringify(Object.assign({message: 'Prebid Response'}, msg))
357
+ });
358
+ }
359
+
360
+ it('should render cross domain creative', function() {
361
+ mockPrebidResponse({
362
+ ad: 'ad',
363
+ adUrl: ORIGIN,
364
+ adId: '123',
365
+ width: 300,
366
+ height: 250
367
+ });
358
368
  expect(mockIframe.contentDocument.write.args[0][0]).to.equal("ad");
359
369
  });
370
+
371
+ describe('should signal event', () => {
372
+ const RENDER_FAILED = 'adRenderFailed',
373
+ RENDER_SUCCESS = 'adRenderSucceeded';
374
+
375
+ function expectEventMessage(expected) {
376
+ const actual = JSON.parse(mockWin.parent.postMessage.args[1][0]);
377
+ sinon.assert.match(actual, Object.assign({message: 'Prebid Event'}, expected));
378
+ }
379
+
380
+ describe('AD_RENDER_FAILED', () => {
381
+ it('on video ads', () => {
382
+ mockPrebidResponse({
383
+ ad: 'ad',
384
+ adId: '123',
385
+ mediaType: 'video'
386
+ });
387
+ expectEventMessage({
388
+ adId: '123',
389
+ event: RENDER_FAILED,
390
+ info: {
391
+ reason: 'preventWritingOnMainDocument'
392
+ }
393
+ })
394
+ });
395
+
396
+ it('on ads that have no markup or adUrl', () => {
397
+ mockPrebidResponse({
398
+ adId: '123',
399
+ })
400
+ expectEventMessage({
401
+ adId: '123',
402
+ event: RENDER_FAILED,
403
+ info: {
404
+ reason: 'noAd'
405
+ }
406
+ });
407
+ });
408
+
409
+ it('on exceptions', () => {
410
+ iframeStub.callsFake(() => {
411
+ throw new Error()
412
+ });
413
+ mockPrebidResponse({
414
+ adId: '123',
415
+ ad: 'ad',
416
+ adUrl: ORIGIN,
417
+ });
418
+ expectEventMessage({
419
+ adId: '123',
420
+ event: RENDER_FAILED,
421
+ info: {
422
+ reason: 'exception'
423
+ }
424
+ });
425
+ })
426
+ });
427
+ describe('should post AD_RENDER_SUCCEEDED', () => {
428
+ it('on ad with markup', () => {
429
+ mockPrebidResponse({
430
+ adId: '123',
431
+ ad: 'markup'
432
+ });
433
+ expectEventMessage({
434
+ adId: '123',
435
+ event: RENDER_SUCCESS
436
+ });
437
+ });
438
+ it('on ad with adUrl', () => {
439
+ mockPrebidResponse({
440
+ adId: '123',
441
+ adUrl: 'url'
442
+ });
443
+ expectEventMessage({
444
+ adId: '123',
445
+ event: RENDER_SUCCESS
446
+ });
447
+ })
448
+ })
449
+ });
360
450
  });
361
451
 
362
452
  describe('legacy creative', function() {
363
453
  it('should render legacy creative', function() {
364
- const mockWin = merge(mocks.createFakeWindow('http://example.com'), renderingMocks.getWindowObject());
454
+ const mockWin = merge(mocks.createFakeWindow('http://example.com'), renderingMocks().getWindowObject());
365
455
  const env = {
366
456
  isMobileApp: () => false,
367
457
  isAmp: () => false,