prebid-universal-creative 1.15.0 → 1.17.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/.circleci/config.yml +44 -30
- package/.github/workflows/codeql.yml +98 -0
- package/.github/workflows/issue_tracker.yml +32 -16
- package/README.md +4 -2
- package/dist/amp.js +3 -3
- package/dist/banner.js +3 -3
- package/dist/caf7688498213fb0c19f.max.js +1046 -0
- package/dist/creative.js +3 -3
- package/dist/load-cookie-with-consent.html +1 -1
- package/dist/load-cookie.html +1 -1
- package/dist/mobile.js +3 -3
- package/dist/native-render.js +3 -3
- package/dist/native-trk.js +3 -3
- package/dist/native.js +3 -3
- package/dist/uid.js +2 -2
- package/dist/video.js +3 -3
- package/gulpfile.js +15 -31
- package/integ-test/fixtures/test.js +79 -0
- package/integ-test/pages/amp.html +80 -0
- package/integ-test/pages/banner.html +96 -0
- package/integ-test/pages/native_legacy.html +107 -0
- package/integ-test/spec/amp_spec.js +111 -0
- package/integ-test/spec/banner_spec.js +85 -0
- package/integ-test/spec/native_legacy_spec.js +213 -0
- package/karma.conf.maker.js +4 -6
- package/package.json +10 -16
- package/playwright.config.js +108 -0
- package/src/adHtmlRender.js +11 -0
- package/src/cookieSync.js +3 -0
- package/src/cookieSyncWithConsent.js +3 -0
- package/src/domHelper.js +25 -15
- package/src/dynamicRenderer.js +56 -0
- package/src/messaging.js +23 -2
- package/src/mobileAndAmpRender.js +17 -20
- package/src/nativeAssetManager.js +134 -80
- package/src/nativeORTBTrackerManager.js +3 -3
- package/src/nativeRenderManager.js +44 -72
- package/src/nativeTrackerManager.js +2 -2
- package/src/renderingManager.js +17 -18
- package/src/utils.js +0 -9
- package/test/helpers/mocks.js +1 -0
- package/test/spec/dynamicRenderer_spec.js +167 -0
- package/test/spec/messaging_spec.js +98 -3
- package/test/spec/mobileAndAmpRender_spec.js +53 -63
- package/test/spec/nativeAssetManager_spec.js +290 -93
- package/test/spec/nativeORTBTrackerManager_spec.js +3 -19
- package/test/spec/nativeRenderManager_spec.js +77 -56
- package/test/spec/renderingManager_spec.js +20 -6
- package/webpack.conf.js +0 -1
- package/.nvmrc +0 -1
- package/dist/creative.max.js +0 -3101
- package/src/postscribeRender.js +0 -8
- package/test/e2e/specs/hello_world_banner_non_sf.spec.js +0 -14
- package/test/e2e/specs/outstream_non_sf.spec.js +0 -14
- package/test/e2e/specs/outstream_sf.spec.js +0 -14
- package/wdio.conf.js +0 -50
@@ -1,8 +1,11 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
import {
|
1
|
+
import {expect} from 'chai';
|
2
|
+
import {merge} from 'lodash';
|
3
|
+
import {newNativeAssetManager} from 'src/nativeAssetManager';
|
4
|
+
import {mocks} from 'test/helpers/mocks';
|
5
5
|
import * as utils from 'src/utils';
|
6
|
+
import * as dynamic from 'src/dynamicRenderer.js';
|
7
|
+
import {prebidMessenger} from '../../src/messaging.js';
|
8
|
+
import {MIN_RENDERER_VERSION} from "src/dynamicRenderer.js";
|
6
9
|
|
7
10
|
const ORIGIN = 'https://origin.com'
|
8
11
|
const AD_ID = 'abc123';
|
@@ -40,11 +43,16 @@ const mockDocument = {
|
|
40
43
|
};
|
41
44
|
|
42
45
|
// creates mock postmessage response from prebid's native.js:getAssetMessage
|
43
|
-
function createResponder(assets,url,template) {
|
46
|
+
function createResponder(assets,url,template, clickUrlUnesc = '') {
|
44
47
|
return function(type, listener) {
|
45
48
|
if (type !== 'message') { return; }
|
46
49
|
|
47
|
-
const data = {
|
50
|
+
const data = {
|
51
|
+
message: 'assetResponse',
|
52
|
+
adId: AD_ID, assets,
|
53
|
+
adTemplate:template,
|
54
|
+
rendererUrl:url,
|
55
|
+
};
|
48
56
|
listener({ data: JSON.stringify(data), origin: ORIGIN});
|
49
57
|
};
|
50
58
|
}
|
@@ -84,14 +92,40 @@ function generateRenderer(assets) {
|
|
84
92
|
}
|
85
93
|
|
86
94
|
describe('nativeAssetManager', () => {
|
87
|
-
let win;
|
95
|
+
let win, sandbox;
|
88
96
|
|
89
|
-
function makeManager() {
|
90
|
-
return newNativeAssetManager(win,
|
97
|
+
function makeManager(args, mkMessenger = prebidMessenger) {
|
98
|
+
return newNativeAssetManager(win, {
|
99
|
+
pubUrl: ORIGIN,
|
100
|
+
...args
|
101
|
+
}, mkMessenger);
|
91
102
|
}
|
92
103
|
|
93
104
|
beforeEach(() => {
|
94
105
|
win = merge(mocks.createFakeWindow(), mockDocument.getWindowObject());
|
106
|
+
sandbox = sinon.createSandbox();
|
107
|
+
});
|
108
|
+
|
109
|
+
afterEach(() => {
|
110
|
+
sandbox.restore();
|
111
|
+
})
|
112
|
+
|
113
|
+
it(`should run dynamic renderer`, () => {
|
114
|
+
const data = {
|
115
|
+
renderer: 'mock-renderer',
|
116
|
+
rendererVersion: MIN_RENDERER_VERSION,
|
117
|
+
native: 'data'
|
118
|
+
}
|
119
|
+
sandbox.stub(dynamic, 'runDynamicRenderer');
|
120
|
+
const sendMessage = sinon.stub().callsFake((msg, reply) => {
|
121
|
+
reply({data: JSON.stringify(Object.assign({adId: '123', message: 'assetResponse'}, data))});
|
122
|
+
})
|
123
|
+
win.pbNativeData = {
|
124
|
+
requestAllAssets: true
|
125
|
+
};
|
126
|
+
const mgr = makeManager({}, () => sendMessage);
|
127
|
+
mgr.loadAssets('123');
|
128
|
+
sinon.assert.calledWith(dynamic.runDynamicRenderer, '123', sinon.match(data));
|
95
129
|
});
|
96
130
|
|
97
131
|
describe('safe frames enabled', () => {
|
@@ -112,10 +146,10 @@ describe('nativeAssetManager', () => {
|
|
112
146
|
{ key: 'body', value: 'new value' },
|
113
147
|
{ key: 'clickUrl', value: 'http://www.example.com' },
|
114
148
|
]);
|
115
|
-
|
149
|
+
|
116
150
|
const nativeAssetManager = makeManager();
|
117
151
|
nativeAssetManager.loadAssets(AD_ID);
|
118
|
-
|
152
|
+
|
119
153
|
expect(win.document.body.innerHTML).to.include('<p>new value</p>');
|
120
154
|
expect(win.document.body.innerHTML).to.include(`
|
121
155
|
<a href="http://www.example.com">Click Here</a>
|
@@ -123,17 +157,17 @@ describe('nativeAssetManager', () => {
|
|
123
157
|
// title was not a requested asset so this should stay as is
|
124
158
|
expect(win.document.body.innerHTML).to.include('<h1>hb_native_title</h1>');
|
125
159
|
});
|
126
|
-
|
160
|
+
|
127
161
|
it('replaces all occurrences of the placeholder if it appears more than once', () => {
|
128
162
|
win.document.body.innerHTML = `
|
129
163
|
<a href="hb_native_linkurl:${AD_ID}">Click Here</a>
|
130
164
|
<a href="hb_native_linkurl:${AD_ID}">Or Here</a>
|
131
165
|
`;
|
132
166
|
win.addEventListener = createResponder([{ key: 'clickUrl', value: 'http://www.example.com' }]);
|
133
|
-
|
167
|
+
|
134
168
|
const nativeAssetManager = makeManager();
|
135
169
|
nativeAssetManager.loadAssets(AD_ID);
|
136
|
-
|
170
|
+
|
137
171
|
expect(win.document.body.innerHTML).to.include(`
|
138
172
|
<a href="http://www.example.com">Click Here</a>
|
139
173
|
`);
|
@@ -141,23 +175,22 @@ describe('nativeAssetManager', () => {
|
|
141
175
|
<a href="http://www.example.com">Or Here</a>
|
142
176
|
`);
|
143
177
|
});
|
144
|
-
|
178
|
+
|
145
179
|
it('attaches and removes message listeners', (done) => {
|
146
180
|
win.document.body.innerHTML = `<h1>hb_native_title:${AD_ID}</h1>`;
|
147
181
|
const responder = createResponder();
|
148
182
|
win.addEventListener = function (evType, listener) {
|
149
183
|
setTimeout(() => responder(evType, listener), 0);
|
150
184
|
}
|
151
|
-
|
185
|
+
|
152
186
|
const nativeAssetManager = makeManager();
|
153
187
|
nativeAssetManager.loadAssets(AD_ID);
|
154
188
|
setTimeout(() => {
|
155
|
-
expect(win.parent.postMessage.callCount).to.equal(1);
|
156
189
|
expect(win.removeEventListener.callCount).to.equal(1);
|
157
190
|
done();
|
158
191
|
}, 0);
|
159
192
|
});
|
160
|
-
|
193
|
+
|
161
194
|
it('replaces native placeholders with their asset values from adTemplate', () => {
|
162
195
|
const html = `<script>
|
163
196
|
let nativeTag = {};
|
@@ -172,7 +205,7 @@ describe('nativeAssetManager', () => {
|
|
172
205
|
adId : AD_ID,
|
173
206
|
adTemplate : '<div class=\"sponsored-post\">\r\n <div class=\"thumbnail\"><\/div>\r\n <div class=\"content\">\r\n <h1>\r\n <a href=\"##hb_native_linkurl##\" target=\"_blank\" class=\"pb-click\">##hb_native_title##<\/a>\r\n <\/h1>\r\n <p>##hb_native_body##<\/p>\r\n \t<div class=\"attribution\">\r\n \t<img class=\"pb-icon\" src=\"##hb_native_image##\" alt=\"icon\" height=\"150\" width=\"50\">\r\n \t\r\n \t<\/div>\r\n\t<\/div>\r\n<\/div>'
|
174
207
|
};
|
175
|
-
|
208
|
+
|
176
209
|
win.document.body.innerHTML = html;
|
177
210
|
win.addEventListener = createResponder([
|
178
211
|
{ key: 'body', value: 'Body content' },
|
@@ -180,15 +213,15 @@ describe('nativeAssetManager', () => {
|
|
180
213
|
{ key: 'clickUrl', value: 'http://www.example.com' },
|
181
214
|
{ key: 'image', value: 'http://www.image.com/picture.jpg' },
|
182
215
|
]);
|
183
|
-
|
216
|
+
|
184
217
|
const nativeAssetManager = makeManager();
|
185
218
|
nativeAssetManager.loadAssets(AD_ID);
|
186
|
-
|
219
|
+
|
187
220
|
expect(win.document.body.innerHTML).to.include(`<a href="http://www.example.com" target="_blank" class="pb-click">new value</a>`);
|
188
221
|
expect(win.document.body.innerHTML).to.include(`<img class="pb-icon" src="http://www.image.com/picture.jpg" alt="icon" height="150" width="50">`);
|
189
222
|
expect(win.document.body.innerHTML).to.include(`<p>Body content</p>`);
|
190
223
|
});
|
191
|
-
|
224
|
+
|
192
225
|
it('loads rendererUrl and passes assets to renderAd - writes response to innerHtml', () => {
|
193
226
|
const html = `<script>
|
194
227
|
let nativeTag = {};
|
@@ -203,25 +236,25 @@ describe('nativeAssetManager', () => {
|
|
203
236
|
rendererUrl : 'https://www.renderer.com/render.js',
|
204
237
|
requestAllAssets : true
|
205
238
|
};
|
206
|
-
|
239
|
+
|
207
240
|
win.document.body.innerHTML = html;
|
208
241
|
win.renderAd = generateRenderer;
|
209
|
-
|
242
|
+
|
210
243
|
win.addEventListener = createAllResponder([
|
211
244
|
{ key: 'body', value: 'Body content' },
|
212
245
|
{ key: 'title', value: 'new value' },
|
213
246
|
{ key: 'clickUrl', value: 'http://www.example.com' },
|
214
247
|
{ key: 'image', value: 'http://www.image.com/picture.jpg' },
|
215
248
|
],null,null);
|
216
|
-
|
249
|
+
|
217
250
|
const nativeAssetManager = makeManager();
|
218
251
|
nativeAssetManager.loadAssets(AD_ID);
|
219
|
-
|
252
|
+
|
220
253
|
expect(win.document.body.innerHTML).to.include(`<a href="http://www.example.com" target="_blank" class="pb-click">new value</a>`);
|
221
254
|
expect(win.document.body.innerHTML).to.include(`<img class="pb-icon" src="http://www.image.com/picture.jpg" alt="icon" height="150" width="50">`);
|
222
255
|
expect(win.document.body.innerHTML).to.include(`<p>Body content</p>`);
|
223
256
|
});
|
224
|
-
|
257
|
+
|
225
258
|
it('adId does not match, so assets are not replaced', () => {
|
226
259
|
const html = `<script>
|
227
260
|
let nativeTag = {};
|
@@ -236,20 +269,20 @@ describe('nativeAssetManager', () => {
|
|
236
269
|
rendererUrl : 'https://www.renderer.com/render.js',
|
237
270
|
requestAllAssets : true
|
238
271
|
};
|
239
|
-
|
272
|
+
|
240
273
|
win.document.body.innerHTML = html;
|
241
274
|
win.renderAd = generateRenderer;
|
242
|
-
|
275
|
+
|
243
276
|
win.addEventListener = createAllResponder([
|
244
277
|
{ key: 'body', value: 'Body content' },
|
245
278
|
{ key: 'title', value: 'new value' },
|
246
279
|
{ key: 'clickUrl', value: 'http://www.example.com' },
|
247
280
|
{ key: 'image', value: 'http://www.image.com/picture.jpg' },
|
248
281
|
],null,null);
|
249
|
-
|
282
|
+
|
250
283
|
const nativeAssetManager = makeManager();
|
251
|
-
nativeAssetManager.loadAssets(
|
252
|
-
|
284
|
+
nativeAssetManager.loadAssets(win.pbNativeData.adId);
|
285
|
+
|
253
286
|
expect(win.document.body.innerHTML).to.equal(`<script>
|
254
287
|
let nativeTag = {};
|
255
288
|
nativeTag.pubUrl = "https://www.url.com";
|
@@ -258,7 +291,7 @@ describe('nativeAssetManager', () => {
|
|
258
291
|
window.pbNativeTag.renderNativeAd(nativeTag);
|
259
292
|
</script>`);
|
260
293
|
});
|
261
|
-
|
294
|
+
|
262
295
|
it('adId does not match on first response, so assets are not replaced until match on second response', () => {
|
263
296
|
const html = `<script>
|
264
297
|
let nativeTag = {};
|
@@ -273,20 +306,20 @@ describe('nativeAssetManager', () => {
|
|
273
306
|
rendererUrl : 'https://www.renderer.com/render.js',
|
274
307
|
requestAllAssets : true
|
275
308
|
};
|
276
|
-
|
309
|
+
|
277
310
|
win.document.body.innerHTML = html;
|
278
311
|
win.renderAd = generateRenderer;
|
279
|
-
|
312
|
+
|
280
313
|
win.addEventListener = createAllResponder([
|
281
314
|
{ key: 'body', value: 'Body No Replace' },
|
282
315
|
{ key: 'title', value: 'new value no replace' },
|
283
316
|
{ key: 'clickUrl', value: 'http://www.example.com/noreplace' },
|
284
317
|
{ key: 'image', value: 'http://www.image.com/picture.jpg?noreplace=true' },
|
285
318
|
],null,null);
|
286
|
-
|
319
|
+
|
287
320
|
const nativeAssetManager = makeManager();
|
288
321
|
nativeAssetManager.loadAssets(AD_ID2);
|
289
|
-
|
322
|
+
|
290
323
|
expect(win.document.body.innerHTML).to.equal(`<script>
|
291
324
|
let nativeTag = {};
|
292
325
|
nativeTag.pubUrl = "https://www.url.com";
|
@@ -294,21 +327,21 @@ describe('nativeAssetManager', () => {
|
|
294
327
|
nativeTag.requestAllAssets = true;
|
295
328
|
window.pbNativeTag.renderNativeAd(nativeTag);
|
296
329
|
</script>`);
|
297
|
-
|
330
|
+
|
298
331
|
win.addEventListener = createAltAllResponder([
|
299
332
|
{ key: 'body', value: 'Body content' },
|
300
333
|
{ key: 'title', value: 'new value' },
|
301
334
|
{ key: 'clickUrl', value: 'http://www.example.com' },
|
302
335
|
{ key: 'image', value: 'http://www.image.com/picture.jpg' },
|
303
336
|
],null,null);
|
304
|
-
|
337
|
+
|
305
338
|
nativeAssetManager.loadAssets(AD_ID2);
|
306
|
-
|
339
|
+
|
307
340
|
expect(win.document.body.innerHTML).to.include(`<a href="http://www.example.com" target="_blank" class="pb-click">new value</a>`);
|
308
341
|
expect(win.document.body.innerHTML).to.include(`<img class="pb-icon" src="http://www.image.com/picture.jpg" alt="icon" height="150" width="50">`);
|
309
342
|
expect(win.document.body.innerHTML).to.include(`<p>Body content</p>`);
|
310
343
|
});
|
311
|
-
|
344
|
+
|
312
345
|
it('no placeholders found but requests all assets flag set - rendererUrl', () => {
|
313
346
|
const url = 'https://www.renderer.com/render.js';
|
314
347
|
win.pbNativeData = {
|
@@ -317,25 +350,25 @@ describe('nativeAssetManager', () => {
|
|
317
350
|
rendererUrl : 'https://www.renderer.com/render.js',
|
318
351
|
requestAllAssets : true
|
319
352
|
};
|
320
|
-
|
353
|
+
|
321
354
|
win.document.body.innerHTML = '';
|
322
355
|
win.renderAd = generateRenderer;
|
323
|
-
|
356
|
+
|
324
357
|
win.addEventListener = createAllResponder([
|
325
358
|
{ key: 'body', value: 'Body content' },
|
326
359
|
{ key: 'title', value: 'new value' },
|
327
360
|
{ key: 'clickUrl', value: 'http://www.example.com' },
|
328
361
|
{ key: 'image', value: 'http://www.image.com/picture.jpg' },
|
329
362
|
],url,null);
|
330
|
-
|
363
|
+
|
331
364
|
const nativeAssetManager = makeManager();
|
332
365
|
nativeAssetManager.loadAssets(AD_ID);
|
333
|
-
|
366
|
+
|
334
367
|
expect(win.document.body.innerHTML).to.include(`<a href="http://www.example.com" target="_blank" class="pb-click">new value</a>`);
|
335
368
|
expect(win.document.body.innerHTML).to.include(`<img class="pb-icon" src="http://www.image.com/picture.jpg" alt="icon" height="150" width="50">`);
|
336
369
|
expect(win.document.body.innerHTML).to.include(`<p>Body content</p>`);
|
337
370
|
});
|
338
|
-
|
371
|
+
|
339
372
|
it("no placeholders found but requests all assets flag set - adTemplate - openRTB", () => {
|
340
373
|
const template = `
|
341
374
|
<div class="sponsored-post">
|
@@ -349,6 +382,7 @@ describe('nativeAssetManager', () => {
|
|
349
382
|
<div class="attribution">
|
350
383
|
<img class="pb-icon" src="##hb_native_asset_id_3##" alt="icon" height="150" width="50">
|
351
384
|
</div>
|
385
|
+
<h2>##hb_native_asset_id_1##</h2>
|
352
386
|
<p>##hb_native_asset_id_4##</p>
|
353
387
|
</div>
|
354
388
|
</div>
|
@@ -358,9 +392,9 @@ describe('nativeAssetManager', () => {
|
|
358
392
|
adId: AD_ID,
|
359
393
|
requestAllAssets: true,
|
360
394
|
};
|
361
|
-
|
395
|
+
|
362
396
|
win.document.body.innerHTML = "";
|
363
|
-
|
397
|
+
|
364
398
|
win.addEventListener = createAllResponder(
|
365
399
|
{
|
366
400
|
assets: [
|
@@ -392,10 +426,10 @@ describe('nativeAssetManager', () => {
|
|
392
426
|
template,
|
393
427
|
"ortb"
|
394
428
|
);
|
395
|
-
|
429
|
+
|
396
430
|
const nativeAssetManager = makeManager();
|
397
431
|
nativeAssetManager.loadAssets(AD_ID);
|
398
|
-
|
432
|
+
|
399
433
|
expect(win.document.body.innerHTML).to.include(
|
400
434
|
`<a href="http://www.example.com" target="_blank" class="pb-click">new value</a>`
|
401
435
|
);
|
@@ -404,11 +438,14 @@ describe('nativeAssetManager', () => {
|
|
404
438
|
);
|
405
439
|
expect(win.document.body.innerHTML).to.include(`<p>Body content</p>`);
|
406
440
|
|
407
|
-
// ##hb_native_asset_id_4## was not returned in the response, it should
|
441
|
+
// ##hb_native_asset_id_4## was not returned in the response, it should
|
408
442
|
// be transformed into an empty string
|
409
443
|
expect(win.document.body.innerHTML).to.not.include(`##hb_native_asset_id_4##`);
|
444
|
+
|
445
|
+
// test that we are replacing ALL asset occurrences
|
446
|
+
expect(([...win.document.body.innerHTML.match(/new value/g)] || []).length, "expected 2 occurrences of \"new value\"").to.equal(2);
|
410
447
|
});
|
411
|
-
|
448
|
+
|
412
449
|
it('no placeholders found but requests all assets flag set - adTemplate', () => {
|
413
450
|
const template = '<div class=\"sponsored-post\">\r\n <div class=\"thumbnail\"><\/div>\r\n <div class=\"content\">\r\n <h1>\r\n <a href=\"##hb_native_linkurl##\" target=\"_blank\" class=\"pb-click\">##hb_native_title##<\/a>\r\n <\/h1>\r\n <p>##hb_native_body##<\/p>\r\n \t<div class=\"attribution\">\r\n \t<img class=\"pb-icon\" src=\"##hb_native_image##\" alt=\"icon\" height=\"150\" width=\"50\">\r\n \t\r\n \t<\/div>\r\n\t<\/div>\r\n<\/div>';
|
414
451
|
win.pbNativeData = {
|
@@ -416,24 +453,24 @@ describe('nativeAssetManager', () => {
|
|
416
453
|
adId : AD_ID,
|
417
454
|
requestAllAssets : true
|
418
455
|
};
|
419
|
-
|
456
|
+
|
420
457
|
win.document.body.innerHTML = '';
|
421
|
-
|
458
|
+
|
422
459
|
win.addEventListener = createAllResponder([
|
423
460
|
{ key: 'body', value: 'Body content' },
|
424
461
|
{ key: 'title', value: 'new value' },
|
425
462
|
{ key: 'clickUrl', value: 'http://www.example.com' },
|
426
463
|
{ key: 'image', value: 'http://www.image.com/picture.jpg' },
|
427
464
|
],null,template);
|
428
|
-
|
465
|
+
|
429
466
|
const nativeAssetManager = makeManager();
|
430
467
|
nativeAssetManager.loadAssets(AD_ID);
|
431
|
-
|
468
|
+
|
432
469
|
expect(win.document.body.innerHTML).to.include(`<a href="http://www.example.com" target="_blank" class="pb-click">new value</a>`);
|
433
470
|
expect(win.document.body.innerHTML).to.include(`<img class="pb-icon" src="http://www.image.com/picture.jpg" alt="icon" height="150" width="50">`);
|
434
471
|
expect(win.document.body.innerHTML).to.include(`<p>Body content</p>`);
|
435
472
|
});
|
436
|
-
|
473
|
+
|
437
474
|
it('no placeholders found but assets defined in nativeTag - adTemplate', () => {
|
438
475
|
const template = '<div class=\"sponsored-post\">\r\n <div class=\"thumbnail\"><\/div>\r\n <div class=\"content\">\r\n <h1>\r\n <a href=\"##hb_native_linkurl##\" target=\"_blank\" class=\"pb-click\">##hb_native_title##<\/a>\r\n <\/h1>\r\n <p>##hb_native_body##<\/p>\r\n \t<div class=\"attribution\">\r\n \t<img class=\"pb-icon\" src=\"##hb_native_image##\" alt=\"icon\" height=\"150\" width=\"50\">\r\n \t\r\n \t<\/div>\r\n\t<\/div>\r\n<\/div>';
|
439
476
|
win.pbNativeData = {
|
@@ -441,54 +478,54 @@ describe('nativeAssetManager', () => {
|
|
441
478
|
adId : AD_ID,
|
442
479
|
assetsToReplace: ['image','hb_native_body','clickUrl','hb_native_title']
|
443
480
|
};
|
444
|
-
|
481
|
+
|
445
482
|
win.document.body.innerHTML = '';
|
446
|
-
|
483
|
+
|
447
484
|
win.addEventListener = createAllResponder([
|
448
485
|
{ key: 'body', value: 'Body content' },
|
449
486
|
{ key: 'title', value: 'new value' },
|
450
487
|
{ key: 'clickUrl', value: 'http://www.example.com' },
|
451
488
|
{ key: 'image', value: 'http://www.image.com/picture.jpg' },
|
452
489
|
],null,template);
|
453
|
-
|
490
|
+
|
454
491
|
const nativeAssetManager = makeManager();
|
455
492
|
nativeAssetManager.loadAssets(AD_ID);
|
456
|
-
|
493
|
+
|
457
494
|
expect(win.document.body.innerHTML).to.include(`<a href="http://www.example.com" target="_blank" class="pb-click">new value</a>`);
|
458
495
|
expect(win.document.body.innerHTML).to.include(`<img class="pb-icon" src="http://www.image.com/picture.jpg" alt="icon" height="150" width="50">`);
|
459
496
|
expect(win.document.body.innerHTML).to.include(`<p>Body content</p>`);
|
460
497
|
});
|
461
|
-
|
498
|
+
|
462
499
|
it('does not replace anything if no placeholders found', () => {
|
463
500
|
const html = `
|
464
501
|
<h1>Native Ad</h1>
|
465
502
|
<p>Cool Description</p>
|
466
503
|
<a href="http://www.example.com">Click</a>
|
467
504
|
`;
|
468
|
-
|
505
|
+
|
469
506
|
win.document.body.innerHTML = html;
|
470
507
|
win.addEventListener = createResponder();
|
471
|
-
|
508
|
+
|
472
509
|
const nativeAssetManager = makeManager();
|
473
510
|
nativeAssetManager.loadAssets(AD_ID);
|
474
|
-
|
511
|
+
|
475
512
|
expect(win.document.body.innerHTML).to.equal(html);
|
476
513
|
});
|
477
|
-
|
514
|
+
|
478
515
|
it('replace mobile native placeholder with their values', function() {
|
479
516
|
win.document.body.innerHTML = `
|
480
517
|
<h1>hb_native_cta</h1>
|
481
518
|
<p>hb_native_body</p>
|
482
519
|
<a href="hb_native_linkurl">Click Here</a>
|
483
520
|
`;
|
484
|
-
|
521
|
+
|
485
522
|
let cb = sinon.spy();
|
486
523
|
let targetingData = {
|
487
524
|
uuid: '123'
|
488
525
|
}
|
489
|
-
|
526
|
+
|
490
527
|
sinon.stub(utils, 'sendRequest').callsFake(function(arg1, cb) {
|
491
|
-
let response = JSON.stringify({
|
528
|
+
let response = JSON.stringify({
|
492
529
|
id: '6572251357847878203',
|
493
530
|
impid: 'some-imp-id',
|
494
531
|
price: 10,
|
@@ -499,21 +536,21 @@ describe('nativeAssetManager', () => {
|
|
499
536
|
cid: '9325',
|
500
537
|
crid: '97494204',
|
501
538
|
cat: [ 'IAB3-1' ],
|
502
|
-
ext: {
|
503
|
-
appnexus: {
|
539
|
+
ext: {
|
540
|
+
appnexus: {
|
504
541
|
brand_id: 555545,
|
505
542
|
auction_id: 4550134868038456300,
|
506
543
|
bidder_id: 2,
|
507
|
-
bid_ad_type: 3
|
544
|
+
bid_ad_type: 3
|
508
545
|
}
|
509
546
|
}
|
510
547
|
});
|
511
548
|
cb(response);
|
512
549
|
});
|
513
|
-
|
550
|
+
|
514
551
|
const nativeAssetManager = makeManager();
|
515
552
|
nativeAssetManager.loadMobileAssets(targetingData, cb);
|
516
|
-
|
553
|
+
|
517
554
|
utils.sendRequest.restore();
|
518
555
|
|
519
556
|
expect(win.document.body.innerHTML).to.include('<p>new value</p>');
|
@@ -527,27 +564,28 @@ describe('nativeAssetManager', () => {
|
|
527
564
|
})
|
528
565
|
|
529
566
|
describe('safe frame disabled', () => {
|
530
|
-
|
567
|
+
|
531
568
|
beforeEach(() => {
|
532
569
|
win.parent.frames = [win];
|
533
570
|
win.parent.document = {
|
534
|
-
getElementsByTagName: sinon.stub().returns([{
|
571
|
+
getElementsByTagName: sinon.stub().returns([{
|
535
572
|
contentWindow: win,
|
536
573
|
parentElement: {
|
537
574
|
getBoundingClientRect: () => ({
|
538
575
|
width: 600
|
539
576
|
}),
|
540
577
|
children: [{
|
541
|
-
width: '1',
|
578
|
+
width: '1',
|
542
579
|
height: '1'
|
543
580
|
}]
|
544
581
|
}
|
545
582
|
}])
|
546
|
-
}
|
583
|
+
}
|
547
584
|
})
|
548
585
|
|
549
|
-
|
550
|
-
|
586
|
+
describe('body width resizing', () => {
|
587
|
+
beforeEach(() => {
|
588
|
+
const html = `<script>
|
551
589
|
let nativeTag = {};
|
552
590
|
nativeTag.adTemplate = "<div class=\"sponsored-post\">\r\n <div class=\"thumbnail\"><\/div>\r\n <div class=\"content\">\r\n <h1>\r\n <a href=\"##hb_native_linkurl##\" target=\"_blank\" class=\"pb-click\">##hb_native_title##<\/a>\r\n <\/h1>\r\n <p>##hb_native_body##<\/p>\r\n \t<div class=\"attribution\">\r\n \t<img class=\"pb-icon\" src=\"##hb_native_image##\" alt=\"icon\" height=\"150\" width=\"50\">\r\n \t\r\n \t<\/div>\r\n\t<\/div>\r\n<\/div>";
|
553
591
|
nativeTag.pubUrl = "https://www.url.com";
|
@@ -555,27 +593,186 @@ describe('nativeAssetManager', () => {
|
|
555
593
|
nativeTag.requestAllAssets = true;
|
556
594
|
window.pbNativeTag.renderNativeAd(nativeTag);
|
557
595
|
</script>`;
|
596
|
+
win.pbNativeData = {
|
597
|
+
pubUrl : 'https://www.url.com',
|
598
|
+
adId : AD_ID,
|
599
|
+
adTemplate : '<div class=\"sponsored-post\">\r\n <div class=\"thumbnail\"><\/div>\r\n <div class=\"content\">\r\n <h1>\r\n <a href=\"##hb_native_linkurl##\" target=\"_blank\" class=\"pb-click\">##hb_native_title##<\/a>\r\n <\/h1>\r\n <p>##hb_native_body##<\/p>\r\n \t<div class=\"attribution\">\r\n \t<img class=\"pb-icon\" src=\"##hb_native_image##\" alt=\"icon\" height=\"150\" width=\"50\">\r\n \t\r\n \t<\/div>\r\n\t<\/div>\r\n<\/div>'
|
600
|
+
};
|
601
|
+
|
602
|
+
win.document.body.innerHTML = html;
|
603
|
+
win.addEventListener = createResponder([
|
604
|
+
{ key: 'body', value: 'Body content' },
|
605
|
+
{ key: 'title', value: 'new value' },
|
606
|
+
{ key: 'clickUrl', value: 'http://www.example.com' },
|
607
|
+
{ key: 'image', value: 'http://www.image.com/picture.jpg' },
|
608
|
+
]);
|
609
|
+
});
|
610
|
+
|
611
|
+
it('should not choke when parent window is not available',() => {
|
612
|
+
win.parent.frames = [win];
|
613
|
+
Object.defineProperty(win.parent, 'document', {
|
614
|
+
get() {
|
615
|
+
throw new Error('unvailable');
|
616
|
+
}
|
617
|
+
})
|
618
|
+
const nativeAssetManager = makeManager();
|
619
|
+
nativeAssetManager.loadAssets(AD_ID);
|
620
|
+
expect(win.document.body.innerHTML).to.include(`<a href="http://www.example.com" target="_blank" class="pb-click">new value</a>`);
|
621
|
+
});
|
622
|
+
|
623
|
+
it('should not request width resize if width is 1', () => {
|
624
|
+
sandbox.stub(document.body, 'clientWidth').get(() => 1);
|
625
|
+
const nativeAssetManager = makeManager();
|
626
|
+
nativeAssetManager.loadAssets(AD_ID);
|
627
|
+
const resizeRequest = win.parent.postMessage.args
|
628
|
+
.map(([msg]) => JSON.parse(msg))
|
629
|
+
.find((msg) => msg.action === 'resizeNativeHeight')
|
630
|
+
expect(resizeRequest.width).to.not.exist;
|
631
|
+
})
|
632
|
+
|
633
|
+
it('should set the iframe to the width of the container', () => {
|
634
|
+
const nativeAssetManager = makeManager();
|
635
|
+
nativeAssetManager.loadAssets(AD_ID);
|
636
|
+
expect(win.document.body.innerHTML).to.include(`<a href="http://www.example.com" target="_blank" class="pb-click">new value</a>`);
|
637
|
+
expect(win.document.body.innerHTML).to.include(`<img class="pb-icon" src="http://www.image.com/picture.jpg" alt="icon" height="150" width="50">`);
|
638
|
+
expect(win.document.body.innerHTML).to.include(`<p>Body content</p>`);
|
639
|
+
expect(win.document.body.style.width).to.equal('600px');
|
640
|
+
});
|
641
|
+
});
|
642
|
+
});
|
643
|
+
|
644
|
+
describe('loadAssets calls error callback', () => {
|
645
|
+
let recvMessages, reply;
|
646
|
+
|
647
|
+
function mockMessenger() {
|
648
|
+
return function (msg, cb) {
|
649
|
+
reply = cb;
|
650
|
+
recvMessages.push(msg);
|
651
|
+
};
|
652
|
+
}
|
653
|
+
|
654
|
+
beforeEach(() => {
|
655
|
+
recvMessages = [];
|
656
|
+
reply = null;
|
657
|
+
});
|
658
|
+
|
659
|
+
|
660
|
+
it('when there are no assets to load', () => {
|
661
|
+
win.pbNativeData = {adId: 123};
|
662
|
+
const mgr = makeManager(mockMessenger);
|
663
|
+
const cb = sinon.spy();
|
664
|
+
const errCb = sinon.spy();
|
665
|
+
mgr.loadAssets(123, cb, errCb);
|
666
|
+
expect(cb.called).to.be.false;
|
667
|
+
expect(errCb.called).to.be.true;
|
668
|
+
});
|
669
|
+
|
670
|
+
Object.entries({
|
671
|
+
'all assets': {
|
672
|
+
adId: 123,
|
673
|
+
requestAllAssets: true
|
674
|
+
},
|
675
|
+
'some assets': {
|
676
|
+
adId: 123,
|
677
|
+
}
|
678
|
+
}).forEach(([t, pbData]) => {
|
679
|
+
describe(t, () => {
|
680
|
+
let mgr;
|
681
|
+
beforeEach(() => {
|
682
|
+
win.pbNativeData = pbData;
|
683
|
+
win.document.body.innerHTML = '##hb_native_title##';
|
684
|
+
mgr = makeManager({}, mockMessenger);
|
685
|
+
});
|
686
|
+
|
687
|
+
it('on response "timeout"', () => {
|
688
|
+
const cb = sinon.spy();
|
689
|
+
const err = sinon.spy();
|
690
|
+
mgr.loadAssets(123, cb, err);
|
691
|
+
for (let i = 0; i < 12; i++) {
|
692
|
+
reply({data: 'invalid'});
|
693
|
+
}
|
694
|
+
expect(cb.called).to.be.false;
|
695
|
+
expect(err.called).to.be.true;
|
696
|
+
});
|
697
|
+
|
698
|
+
it('on rendering exceptions', () => {
|
699
|
+
const cb = sinon.spy();
|
700
|
+
const err = sinon.spy();
|
701
|
+
mgr.loadAssets(123, cb, err);
|
702
|
+
win.renderAd = () => {
|
703
|
+
throw new Error();
|
704
|
+
};
|
705
|
+
reply({
|
706
|
+
data: JSON.stringify({
|
707
|
+
message: 'assetResponse',
|
708
|
+
adId: 123,
|
709
|
+
rendererUrl: 'mock-render'
|
710
|
+
})
|
711
|
+
});
|
712
|
+
expect(cb.called).to.be.false;
|
713
|
+
expect(err.called).to.be.true;
|
714
|
+
});
|
715
|
+
});
|
716
|
+
});
|
717
|
+
});
|
718
|
+
|
719
|
+
describe('GAM macro %%CLICK_URL_UNESC%%', () => {
|
720
|
+
it("should remove %%CLICK_URL_UNESC%% if there's no variable set", () => {
|
721
|
+
const html = `<script>
|
722
|
+
let nativeTag = {};
|
723
|
+
nativeTag.adTemplate = "<div class=\"sponsored-post\">\r\n <div class=\"thumbnail\"><\/div>\r\n <div class=\"content\">\r\n <h1>\r\n <a href=\"%%CLICK_URL_UNESC%%##hb_native_linkurl##\" target=\"_blank\" class=\"pb-click\">##hb_native_title##<\/a>\r\n <\/h1>\r\n <p>##hb_native_body##<\/p>\r\n \t<div class=\"attribution\">\r\n \t<img class=\"pb-icon\" src=\"##hb_native_image##\" alt=\"icon\" height=\"150\" width=\"50\">\r\n \t\r\n \t<\/div>\r\n\t<\/div>\r\n<\/div>";
|
724
|
+
nativeTag.pubUrl = "https://www.url.com";
|
725
|
+
nativeTag.adId = "`+AD_ID+`";
|
726
|
+
nativeTag.requestAllAssets = true;
|
727
|
+
window.pbNativeTag.renderNativeAd(nativeTag);
|
728
|
+
</script>`;
|
558
729
|
win.pbNativeData = {
|
559
|
-
|
560
|
-
|
561
|
-
|
730
|
+
pubUrl : 'https://www.url.com',
|
731
|
+
adId : AD_ID,
|
732
|
+
adTemplate : '<div class=\"sponsored-post\">\r\n <div class=\"thumbnail\"><\/div>\r\n <div class=\"content\">\r\n <h1>\r\n <a href=\"%%CLICK_URL_UNESC%%##hb_native_linkurl##\" target=\"_blank\" class=\"pb-click\">##hb_native_title##<\/a>\r\n <\/h1>\r\n <p>##hb_native_body##<\/p>\r\n \t<div class=\"attribution\">\r\n \t<img class=\"pb-icon\" src=\"##hb_native_image##\" alt=\"icon\" height=\"150\" width=\"50\">\r\n \t\r\n \t<\/div>\r\n\t<\/div>\r\n<\/div>'
|
562
733
|
};
|
563
|
-
|
734
|
+
|
564
735
|
win.document.body.innerHTML = html;
|
565
736
|
win.addEventListener = createResponder([
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
737
|
+
{ key: 'body', value: 'Body content' },
|
738
|
+
{ key: 'title', value: 'new value' },
|
739
|
+
{ key: 'clickUrl', value: 'http://www.example.com' },
|
740
|
+
{ key: 'image', value: 'http://www.image.com/picture.jpg' },
|
570
741
|
]);
|
571
|
-
|
742
|
+
|
572
743
|
const nativeAssetManager = makeManager();
|
573
744
|
nativeAssetManager.loadAssets(AD_ID);
|
574
|
-
|
745
|
+
|
575
746
|
expect(win.document.body.innerHTML).to.include(`<a href="http://www.example.com" target="_blank" class="pb-click">new value</a>`);
|
576
|
-
|
577
|
-
|
578
|
-
|
747
|
+
});
|
748
|
+
|
749
|
+
it("should substitute %%CLICK_URL_UNESC%% with clickUrlUnesc value", () => {
|
750
|
+
const html = `<script>
|
751
|
+
let nativeTag = {};
|
752
|
+
nativeTag.adTemplate = "<div class=\"sponsored-post\">\r\n <div class=\"thumbnail\"><\/div>\r\n <div class=\"content\">\r\n <h1>\r\n <a href=\"%%CLICK_URL_UNESC%%##hb_native_linkurl##\" target=\"_blank\" class=\"pb-click\">##hb_native_title##<\/a>\r\n <\/h1>\r\n <p>##hb_native_body##<\/p>\r\n \t<div class=\"attribution\">\r\n \t<img class=\"pb-icon\" src=\"##hb_native_image##\" alt=\"icon\" height=\"150\" width=\"50\">\r\n \t\r\n \t<\/div>\r\n\t<\/div>\r\n<\/div>";
|
753
|
+
nativeTag.pubUrl = "https://www.url.com";
|
754
|
+
nativeTag.adId = "`+AD_ID+`";
|
755
|
+
nativeTag.requestAllAssets = true;
|
756
|
+
window.pbNativeTag.renderNativeAd(nativeTag);
|
757
|
+
</script>`;
|
758
|
+
win.pbNativeData = {
|
759
|
+
pubUrl : 'https://www.url.com',
|
760
|
+
adId : AD_ID,
|
761
|
+
adTemplate : '<div class=\"sponsored-post\">\r\n <div class=\"thumbnail\"><\/div>\r\n <div class=\"content\">\r\n <h1>\r\n <a href=\"%%CLICK_URL_UNESC%%##hb_native_linkurl##\" target=\"_blank\" class=\"pb-click\">##hb_native_title##<\/a>\r\n <\/h1>\r\n <p>##hb_native_body##<\/p>\r\n \t<div class=\"attribution\">\r\n \t<img class=\"pb-icon\" src=\"##hb_native_image##\" alt=\"icon\" height=\"150\" width=\"50\">\r\n \t\r\n \t<\/div>\r\n\t<\/div>\r\n<\/div>',
|
762
|
+
};
|
763
|
+
|
764
|
+
win.document.body.innerHTML = html;
|
765
|
+
win.addEventListener = createResponder([
|
766
|
+
{ key: 'body', value: 'Body content' },
|
767
|
+
{ key: 'title', value: 'new value' },
|
768
|
+
{ key: 'clickUrl', value: 'http://www.example.com' },
|
769
|
+
{ key: 'image', value: 'http://www.image.com/picture.jpg' },
|
770
|
+
], null, null, );
|
771
|
+
|
772
|
+
const nativeAssetManager = makeManager({ clickUrlUnesc: 'https://will.redirect/?to='});
|
773
|
+
nativeAssetManager.loadAssets(AD_ID);
|
774
|
+
|
775
|
+
expect(win.document.body.innerHTML).to.include(`<a href="https://will.redirect/?to=http://www.example.com" target="_blank" class="pb-click">new value</a>`);
|
579
776
|
});
|
580
777
|
});
|
581
778
|
});
|