prebid-universal-creative 1.16.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/README.md +2 -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 +12 -24
- 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/package.json +7 -13
- 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 +98 -79
- package/src/nativeORTBTrackerManager.js +1 -1
- package/src/nativeRenderManager.js +7 -12
- package/src/nativeTrackerManager.js +2 -2
- package/src/renderingManager.js +13 -19
- 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 +47 -65
- package/test/spec/nativeAssetManager_spec.js +73 -23
- package/test/spec/renderingManager_spec.js +20 -6
- package/webpack.conf.js +0 -1
- package/.nvmrc +0 -1
- package/dist/creative.max.js +0 -3102
- package/src/postscribeRender.js +0 -10
- 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
package/gulpfile.js
CHANGED
@@ -17,6 +17,7 @@ const KarmaServer = require('karma').Server;
|
|
17
17
|
const karmaConfMaker = require('./karma.conf.maker');
|
18
18
|
const execa = require('execa');
|
19
19
|
const path = require('path');
|
20
|
+
const {execSync} = require('child_process');
|
20
21
|
|
21
22
|
const dateString = 'Updated : ' + (new Date()).toISOString().substring(0, 10);
|
22
23
|
const banner = '/* <%= creative.name %> v<%= creative.version %>\n' + dateString + ' */\n';
|
@@ -141,16 +142,12 @@ function includeStaticVastXmlFile() {
|
|
141
142
|
function buildProd({ inputFile, outputFile }) {
|
142
143
|
let cloned = _.cloneDeep(webpackConfig);
|
143
144
|
delete cloned.devtool;
|
144
|
-
|
145
|
+
cloned.output.filename = outputFile;
|
145
146
|
return gulp.src([inputFile])
|
146
147
|
.pipe(webpackStream(cloned))
|
147
148
|
.pipe(gulp.dest('dist'))
|
148
149
|
.pipe(uglify())
|
149
150
|
.pipe(header(banner, { creative: creative }))
|
150
|
-
.pipe(rename({
|
151
|
-
basename: outputFile.split('.')[0],
|
152
|
-
extname: `.${outputFile.split('.')[1]}`
|
153
|
-
}))
|
154
151
|
.pipe(gulp.dest('dist'));
|
155
152
|
}
|
156
153
|
|
@@ -205,20 +202,10 @@ function includeStaticVastXmlFile() {
|
|
205
202
|
//
|
206
203
|
// If --watch is given, the task will open the karma debug window
|
207
204
|
// If --browserstack is given, it will run the full suite of currently supported browsers.
|
208
|
-
// If --e2e is given, it will run test defined in ./test/e2e/specs in browserstack
|
209
205
|
|
210
206
|
function test(done) {
|
211
|
-
|
212
|
-
|
213
|
-
let wdioConf = path.join(__dirname, 'wdio.conf.js');
|
214
|
-
let wdioOpts = [
|
215
|
-
wdioConf
|
216
|
-
];
|
217
|
-
return execa(wdioCmd, wdioOpts, { stdio: 'inherit' });
|
218
|
-
} else {
|
219
|
-
let karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch);
|
220
|
-
new KarmaServer(karmaConf, newKarmaCallback(done)).start();
|
221
|
-
}
|
207
|
+
let karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch);
|
208
|
+
new KarmaServer(karmaConf, newKarmaCallback(done)).start();
|
222
209
|
}
|
223
210
|
|
224
211
|
function newKarmaCallback(done) {
|
@@ -237,17 +224,10 @@ function newKarmaCallback(done) {
|
|
237
224
|
}
|
238
225
|
}
|
239
226
|
|
240
|
-
function setupE2E(done) {
|
241
|
-
argv.e2e = true;
|
242
|
-
done();
|
243
|
-
}
|
244
|
-
|
245
227
|
gulp.task('test', gulp.series(clean, test));
|
246
228
|
|
247
229
|
const buildDevFunctions = [buildLegacyDev, buildBannerDev, buildVideoDev, buildAmpDev, buildMobileDev, buildNativeRenderLegacyDev, buildNativeDev, buildNativeRenderDev, buildCookieSync, buildCookieSyncWithConsent, buildUidDev, includeStaticVastXmlFile];
|
248
230
|
|
249
|
-
gulp.task('e2e-test', gulp.series(clean, setupE2E, gulp.parallel(...buildDevFunctions, watch), test));
|
250
|
-
|
251
231
|
function watch(done) {
|
252
232
|
const mainWatcher = gulp.watch([
|
253
233
|
'src/**/*.js',
|
@@ -275,6 +255,14 @@ gulp.task('test-coverage', (done) => {
|
|
275
255
|
new KarmaServer(karmaConfMaker(true, false, false), newKarmaCallback(done)).start();
|
276
256
|
});
|
277
257
|
|
258
|
+
function integTests(done) {
|
259
|
+
execSync('npx playwright test', {stdio: 'inherit'});
|
260
|
+
done();
|
261
|
+
}
|
262
|
+
|
263
|
+
gulp.task('integ-tests', gulp.series(clean, 'build', integTests));
|
264
|
+
|
265
|
+
|
278
266
|
gulp.task('view-coverage', (done) => {
|
279
267
|
const coveragePort = 1999;
|
280
268
|
const localhost = (argv.host) ? argv.host : 'localhost';
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import {test as baseTest} from '@playwright/test';
|
2
|
+
import path from 'path';
|
3
|
+
import {expect} from '@playwright/test';
|
4
|
+
export {expect} from '@playwright/test';
|
5
|
+
import process from 'process'
|
6
|
+
export const BASE_URL = 'https://www.prebid.org/puc-test/';
|
7
|
+
export const PUC_URL = 'https://cdn.jsdelivr.net/npm/prebid-universal-creative@latest/dist/';
|
8
|
+
export const PBJS_URL = 'https://cdn.jsdelivr.net/npm/prebid.js@latest/dist/not-for-prod/prebid.js'
|
9
|
+
|
10
|
+
const LOCAL_PBJS_URL = 'http://localhost:9999/build/dev/prebid.js';
|
11
|
+
|
12
|
+
const REDIRECTS = {
|
13
|
+
[BASE_URL]: '../pages',
|
14
|
+
[PUC_URL]: '../../dist'
|
15
|
+
};
|
16
|
+
|
17
|
+
export const test = baseTest.extend({
|
18
|
+
/**
|
19
|
+
* Replace requests for "https://www.prebid.org" with the contents of files under "pages",
|
20
|
+
* and requests for the PUC CDN with contents of files under "dist".
|
21
|
+
*/
|
22
|
+
async context({context}, use) {
|
23
|
+
await Promise.all(
|
24
|
+
Object.entries(REDIRECTS).map(([url, localDir]) => {
|
25
|
+
context.route((u) => u.href.startsWith(url), (route, request) => {
|
26
|
+
const fpath = request.url().substring(url.length).split('?')[0];
|
27
|
+
route.fulfill({
|
28
|
+
path: path.resolve(__dirname, localDir, fpath)
|
29
|
+
});
|
30
|
+
});
|
31
|
+
})
|
32
|
+
);
|
33
|
+
if (process.env.LOCAL_PBJS) {
|
34
|
+
const localUrl = process.env.LOCAL_PBJS.startsWith('http') ? process.env.LOCAL_PBJS : LOCAL_PBJS_URL;
|
35
|
+
await context.route((u) => u.href.startsWith(PBJS_URL), (route) => route.fulfill({status: 302, headers: {Location: localUrl}}))
|
36
|
+
}
|
37
|
+
await use(context);
|
38
|
+
},
|
39
|
+
/**
|
40
|
+
* await crossLocator(selector): returns a locator for the first element matching 'selector' that appears on the
|
41
|
+
* page, across all frames.
|
42
|
+
*/
|
43
|
+
async crossLocator({page}, use) {
|
44
|
+
await use(function (selector) {
|
45
|
+
let n = 0;
|
46
|
+
return new Promise((resolve, reject) => {
|
47
|
+
async function frameLocator(frame) {
|
48
|
+
if (!frame.isDetached()) {
|
49
|
+
n++;
|
50
|
+
try {
|
51
|
+
await frame.waitForSelector(selector);
|
52
|
+
resolve(frame.locator(selector));
|
53
|
+
} catch (e) {
|
54
|
+
n--;
|
55
|
+
if (n === 0) {
|
56
|
+
reject(e);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
page.on('frameattached', frameLocator);
|
62
|
+
function walkFrames(frame) {
|
63
|
+
frameLocator(frame);
|
64
|
+
frame.childFrames().forEach(walkFrames)
|
65
|
+
}
|
66
|
+
walkFrames(page.mainFrame());
|
67
|
+
})
|
68
|
+
})
|
69
|
+
},
|
70
|
+
async expectEvent({page}, use) {
|
71
|
+
await use(async function (predicate, numMatches = 1) {
|
72
|
+
await expect.poll(async () =>
|
73
|
+
((await page.evaluate(() => window.pbjs?.getEvents && window.pbjs.getEvents())) || [])
|
74
|
+
.filter(predicate)
|
75
|
+
.length === numMatches
|
76
|
+
).toBeTruthy();
|
77
|
+
});
|
78
|
+
}
|
79
|
+
});
|
@@ -0,0 +1,80 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
|
6
|
+
<link rel="canonical" href="https://www.prebid-org/puc-test/amp.html">
|
7
|
+
<style amp-boilerplate>body {
|
8
|
+
-webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
|
9
|
+
-moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
|
10
|
+
-ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
|
11
|
+
animation: -amp-start 8s steps(1, end) 0s 1 normal both
|
12
|
+
}
|
13
|
+
|
14
|
+
@-webkit-keyframes -amp-start {
|
15
|
+
from {
|
16
|
+
visibility: hidden
|
17
|
+
}
|
18
|
+
to {
|
19
|
+
visibility: visible
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
@-moz-keyframes -amp-start {
|
24
|
+
from {
|
25
|
+
visibility: hidden
|
26
|
+
}
|
27
|
+
to {
|
28
|
+
visibility: visible
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
@-ms-keyframes -amp-start {
|
33
|
+
from {
|
34
|
+
visibility: hidden
|
35
|
+
}
|
36
|
+
to {
|
37
|
+
visibility: visible
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
@-o-keyframes -amp-start {
|
42
|
+
from {
|
43
|
+
visibility: hidden
|
44
|
+
}
|
45
|
+
to {
|
46
|
+
visibility: visible
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
@keyframes -amp-start {
|
51
|
+
from {
|
52
|
+
visibility: hidden
|
53
|
+
}
|
54
|
+
to {
|
55
|
+
visibility: visible
|
56
|
+
}
|
57
|
+
}</style>
|
58
|
+
<noscript>
|
59
|
+
<style amp-boilerplate>body {
|
60
|
+
-webkit-animation: none;
|
61
|
+
-moz-animation: none;
|
62
|
+
-ms-animation: none;
|
63
|
+
animation: none
|
64
|
+
}</style>
|
65
|
+
</noscript>
|
66
|
+
<script async src="https://cdn.ampproject.org/v0.js"></script>
|
67
|
+
<script async custom-element="amp-ad" src="https://cdn.ampproject.org/v0/amp-ad-0.1.js"></script>
|
68
|
+
<title>AMP-RTC RP Test</title>
|
69
|
+
</head>
|
70
|
+
<body>
|
71
|
+
<h2>AMP-RTC RP Test</h2>
|
72
|
+
|
73
|
+
<amp-ad width="300" height="250"
|
74
|
+
type="doubleclick"
|
75
|
+
data-slot="/41758329/integ-test"
|
76
|
+
data-multi-size-validation="false"
|
77
|
+
rtc-config='{"vendors": {"prebidrubicon": {"REQUEST_ID": "14062-amp-300x50"}}}'
|
78
|
+
</amp-ad>
|
79
|
+
</body>
|
80
|
+
</html>
|
@@ -0,0 +1,96 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
<title>Prebid.js Banner Test</title>
|
7
|
+
|
8
|
+
<!-- Prebid.js -->
|
9
|
+
<script async src="https://cdn.jsdelivr.net/npm/prebid.js@latest/dist/not-for-prod/prebid.js"></script>
|
10
|
+
|
11
|
+
<!-- Google Publisher Tag -->
|
12
|
+
<script async src="https://www.googletagservices.com/tag/js/gpt.js"></script>
|
13
|
+
|
14
|
+
<script>
|
15
|
+
var pbjs = pbjs || {};
|
16
|
+
pbjs.que = pbjs.que || [];
|
17
|
+
window.params = new URLSearchParams(window.location.search);
|
18
|
+
</script>
|
19
|
+
|
20
|
+
<script>
|
21
|
+
var googletag = googletag || {};
|
22
|
+
googletag.cmd = googletag.cmd || [];
|
23
|
+
|
24
|
+
googletag.cmd.push(function () {
|
25
|
+
googletag.pubads().disableInitialLoad();
|
26
|
+
});
|
27
|
+
|
28
|
+
pbjs.que.push(function () {
|
29
|
+
pbjs.setConfig({
|
30
|
+
debug: true,
|
31
|
+
debugging: {
|
32
|
+
enabled: true,
|
33
|
+
intercept: [
|
34
|
+
{
|
35
|
+
when: {},
|
36
|
+
then: JSON.parse(params.get('bidResponse'))
|
37
|
+
}
|
38
|
+
]
|
39
|
+
}
|
40
|
+
});
|
41
|
+
|
42
|
+
pbjs.requestBids({
|
43
|
+
bidsBackHandler: sendAdServerRequest,
|
44
|
+
adUnits: [
|
45
|
+
{
|
46
|
+
code: 'slot',
|
47
|
+
mediaTypes: {
|
48
|
+
banner: {
|
49
|
+
sizes: [[300, 250]],
|
50
|
+
}
|
51
|
+
},
|
52
|
+
bids: [{
|
53
|
+
bidder: 'appnexus',
|
54
|
+
params: {
|
55
|
+
placementId: 123
|
56
|
+
}
|
57
|
+
}]
|
58
|
+
}
|
59
|
+
]
|
60
|
+
});
|
61
|
+
});
|
62
|
+
|
63
|
+
function sendAdServerRequest() {
|
64
|
+
googletag.cmd.push(function () {
|
65
|
+
pbjs.que.push(function () {
|
66
|
+
pbjs.setTargetingForGPTAsync('slot');
|
67
|
+
googletag.pubads().refresh();
|
68
|
+
});
|
69
|
+
});
|
70
|
+
}
|
71
|
+
</script>
|
72
|
+
|
73
|
+
<script>
|
74
|
+
googletag.cmd.push(function () {
|
75
|
+
googletag
|
76
|
+
.defineSlot('/41758329/integ-test', [[300, 250]], 'slot')
|
77
|
+
.setTargeting('creative', params.get('creative'))
|
78
|
+
.addService(googletag.pubads());
|
79
|
+
|
80
|
+
googletag.pubads().enableSingleRequest();
|
81
|
+
googletag.enableServices();
|
82
|
+
});
|
83
|
+
</script>
|
84
|
+
</head>
|
85
|
+
|
86
|
+
<body>
|
87
|
+
<h2>Prebid.js Banner Ad Unit Test</h2>
|
88
|
+
<div id='slot'>
|
89
|
+
<script>
|
90
|
+
googletag.cmd.push(function () {
|
91
|
+
googletag.display('slot');
|
92
|
+
});
|
93
|
+
</script>
|
94
|
+
</div>
|
95
|
+
</body>
|
96
|
+
</html>
|
@@ -0,0 +1,107 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
<title>Prebid.js Legacy Native Test</title>
|
7
|
+
|
8
|
+
<!-- Prebid.js -->
|
9
|
+
<script async src="https://cdn.jsdelivr.net/npm/prebid.js@latest/dist/not-for-prod/prebid.js"></script>
|
10
|
+
|
11
|
+
<!-- Google Publisher Tag -->
|
12
|
+
<script async src="https://www.googletagservices.com/tag/js/gpt.js"></script>
|
13
|
+
|
14
|
+
<script>
|
15
|
+
var pbjs = pbjs || {};
|
16
|
+
pbjs.que = pbjs.que || [];
|
17
|
+
window.params = new URLSearchParams(window.location.search);
|
18
|
+
</script>
|
19
|
+
|
20
|
+
<script>
|
21
|
+
var googletag = googletag || {};
|
22
|
+
googletag.cmd = googletag.cmd || [];
|
23
|
+
|
24
|
+
googletag.cmd.push(function () {
|
25
|
+
googletag.pubads().disableInitialLoad();
|
26
|
+
});
|
27
|
+
|
28
|
+
pbjs.que.push(function () {
|
29
|
+
pbjs.setConfig({
|
30
|
+
debug: true,
|
31
|
+
debugging: {
|
32
|
+
enabled: true,
|
33
|
+
intercept: [
|
34
|
+
{
|
35
|
+
when: {},
|
36
|
+
then: JSON.parse(params.get('bidResponse'))
|
37
|
+
}
|
38
|
+
]
|
39
|
+
}
|
40
|
+
});
|
41
|
+
|
42
|
+
pbjs.requestBids({
|
43
|
+
bidsBackHandler: sendAdServerRequest,
|
44
|
+
adUnits: [
|
45
|
+
{
|
46
|
+
code: 'slot',
|
47
|
+
mediaTypes: {
|
48
|
+
native: {
|
49
|
+
image: {
|
50
|
+
required: false,
|
51
|
+
},
|
52
|
+
title: {
|
53
|
+
required: true
|
54
|
+
},
|
55
|
+
body: {
|
56
|
+
required: true
|
57
|
+
},
|
58
|
+
clickUrl: {
|
59
|
+
required: true
|
60
|
+
}
|
61
|
+
}
|
62
|
+
},
|
63
|
+
bids: [{
|
64
|
+
bidder: 'appnexus',
|
65
|
+
params: {
|
66
|
+
placementId: 123
|
67
|
+
}
|
68
|
+
}]
|
69
|
+
}
|
70
|
+
]
|
71
|
+
});
|
72
|
+
});
|
73
|
+
|
74
|
+
function sendAdServerRequest() {
|
75
|
+
googletag.cmd.push(function () {
|
76
|
+
pbjs.que.push(function () {
|
77
|
+
pbjs.setTargetingForGPTAsync('slot');
|
78
|
+
googletag.pubads().refresh();
|
79
|
+
});
|
80
|
+
});
|
81
|
+
}
|
82
|
+
</script>
|
83
|
+
|
84
|
+
<script>
|
85
|
+
googletag.cmd.push(function () {
|
86
|
+
googletag
|
87
|
+
.defineSlot('/41758329/integ-test', params.get('banner') === 'true' ? [[640, 480]] : 'fluid', 'slot')
|
88
|
+
.setTargeting('creative', params.get('creative'))
|
89
|
+
.addService(googletag.pubads());
|
90
|
+
|
91
|
+
googletag.pubads().enableSingleRequest();
|
92
|
+
googletag.enableServices();
|
93
|
+
});
|
94
|
+
</script>
|
95
|
+
</head>
|
96
|
+
|
97
|
+
<body>
|
98
|
+
<h2>Prebid.js Legacy Native Ad Unit Test</h2>
|
99
|
+
<div id='slot'>
|
100
|
+
<script>
|
101
|
+
googletag.cmd.push(function () {
|
102
|
+
googletag.display('slot');
|
103
|
+
});
|
104
|
+
</script>
|
105
|
+
</div>
|
106
|
+
</body>
|
107
|
+
</html>
|
@@ -0,0 +1,111 @@
|
|
1
|
+
import {test, expect} from '../fixtures/test.js';
|
2
|
+
|
3
|
+
test.describe('AMP', () => {
|
4
|
+
const PBS_AMP_URL = 'https://prebid-server.rubiconproject.com/openrtb2/amp';
|
5
|
+
const CACHE_HOST = 'cache-host.prebid-server.com';
|
6
|
+
const CACHE_PATH = '/cache';
|
7
|
+
const CACHE_ID = 'test-cache-id'
|
8
|
+
const TRIGGERED_URL_BASE = 'https://url-triggers.com/';
|
9
|
+
const URLS = Object.fromEntries(['burl', 'nurl', 'wurl'].map((t) => [t, `${TRIGGERED_URL_BASE}${t}`]))
|
10
|
+
|
11
|
+
let creative, imp, nurlResponse, triggers;
|
12
|
+
|
13
|
+
test.beforeEach(async ({page}) => {
|
14
|
+
creative = null;
|
15
|
+
imp = {};
|
16
|
+
nurlResponse = null;
|
17
|
+
triggers = {};
|
18
|
+
await page.route((u) => u.href.startsWith(PBS_AMP_URL), (route) => {
|
19
|
+
route.fulfill({
|
20
|
+
contentType: 'application/json',
|
21
|
+
body: JSON.stringify({
|
22
|
+
targeting: {
|
23
|
+
hb_cache_id: CACHE_ID,
|
24
|
+
hb_pb: "1.00",
|
25
|
+
hb_pb_rubicon: "1.00",
|
26
|
+
hb_cache_path: CACHE_PATH,
|
27
|
+
hb_size: "300x50",
|
28
|
+
hb_bidder: "rubicon",
|
29
|
+
hb_cache_host: CACHE_HOST,
|
30
|
+
creative
|
31
|
+
}
|
32
|
+
})
|
33
|
+
})
|
34
|
+
});
|
35
|
+
await page.route((u) => u.host.startsWith(CACHE_HOST) && u.pathname === CACHE_PATH, (route) => {
|
36
|
+
route.fulfill({
|
37
|
+
contentType: 'application/json',
|
38
|
+
body: JSON.stringify(imp)
|
39
|
+
})
|
40
|
+
})
|
41
|
+
await page.route((u) => u.href.startsWith(TRIGGERED_URL_BASE), (route, req)=> {
|
42
|
+
const trigger = req.url().substring(TRIGGERED_URL_BASE.length);
|
43
|
+
triggers[trigger] = true;
|
44
|
+
route.fulfill({
|
45
|
+
contentType: 'text/html',
|
46
|
+
body: trigger === 'nurl' && nurlResponse || ''
|
47
|
+
})
|
48
|
+
})
|
49
|
+
});
|
50
|
+
|
51
|
+
test.describe('Banner', () => {
|
52
|
+
Object.entries({
|
53
|
+
'safeframe': 'banner-safeframe',
|
54
|
+
'non safeframe': 'banner-noframe',
|
55
|
+
}).forEach(([t, cr]) => {
|
56
|
+
test.describe(t, () => {
|
57
|
+
const AD = `
|
58
|
+
<p id="the-ad">
|
59
|
+
This is the ad
|
60
|
+
<span id="ad-price">\${AUCTION_PRICE}</span>
|
61
|
+
</p>
|
62
|
+
`
|
63
|
+
|
64
|
+
test.beforeEach(() => {
|
65
|
+
creative = cr;
|
66
|
+
});
|
67
|
+
|
68
|
+
Object.entries({
|
69
|
+
'imp.adm': {
|
70
|
+
adm: AD,
|
71
|
+
setup() {}
|
72
|
+
},
|
73
|
+
'imp.nurl': {
|
74
|
+
setup() {
|
75
|
+
nurlResponse = AD;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}).forEach(([t, {adm, setup}]) => {
|
79
|
+
test.describe(t, () => {
|
80
|
+
test.beforeEach(async ({page}) => {
|
81
|
+
imp = {
|
82
|
+
price: 1.23,
|
83
|
+
adm,
|
84
|
+
...URLS
|
85
|
+
};
|
86
|
+
setup();
|
87
|
+
await page.goto('amp.html');
|
88
|
+
});
|
89
|
+
|
90
|
+
|
91
|
+
test('should display ad', async ({crossLocator}) => {
|
92
|
+
await expect(await crossLocator('#the-ad')).toBeVisible();
|
93
|
+
})
|
94
|
+
|
95
|
+
if (adm != null) { // TODO: should AUCTION_PRICE work in the nurl case? see https://github.com/prebid/prebid-universal-creative/issues/183
|
96
|
+
test('should replace auction price', async ({crossLocator}) => {
|
97
|
+
await expect(await crossLocator('#the-ad #ad-price')).toHaveText('1.23');
|
98
|
+
})
|
99
|
+
}
|
100
|
+
|
101
|
+
Object.keys(URLS).forEach((trigger) => {
|
102
|
+
test(`should trigger ${trigger}`, () => {
|
103
|
+
expect.poll(() => triggers[trigger]).toBeTruthy();
|
104
|
+
});
|
105
|
+
});
|
106
|
+
});
|
107
|
+
});
|
108
|
+
});
|
109
|
+
});
|
110
|
+
});
|
111
|
+
});
|
@@ -0,0 +1,85 @@
|
|
1
|
+
import {test, expect} from '../fixtures/test.js';
|
2
|
+
|
3
|
+
test.describe('Banner', () => {
|
4
|
+
Object.entries({
|
5
|
+
'safeframe': 'banner-safeframe',
|
6
|
+
'non safeframe': 'banner-noframe'
|
7
|
+
}).forEach(([t, creative]) => {
|
8
|
+
test.describe(t, () => {
|
9
|
+
[
|
10
|
+
{
|
11
|
+
t: 'bidResponse.ad',
|
12
|
+
bidResponse: {
|
13
|
+
adId: 'mock-ad',
|
14
|
+
cpm: 1.23,
|
15
|
+
ad: `
|
16
|
+
<p id="the-ad">
|
17
|
+
This is the ad
|
18
|
+
<span id="ad-price">\${AUCTION_PRICE}</span>
|
19
|
+
</p>'
|
20
|
+
`
|
21
|
+
},
|
22
|
+
setup: async () => null
|
23
|
+
},
|
24
|
+
(() => {
|
25
|
+
const mockAdUrl = 'https://mock-ad.com/'
|
26
|
+
return {
|
27
|
+
t: 'bidResponse.adUrl',
|
28
|
+
bidResponse: {
|
29
|
+
adId: 'mock-ad',
|
30
|
+
cpm: 1.23,
|
31
|
+
adUrl: mockAdUrl + '${AUCTION_PRICE}',
|
32
|
+
mediaType: 'banner',
|
33
|
+
},
|
34
|
+
setup: async (page) => {
|
35
|
+
await page.route((u) => u.href.startsWith(mockAdUrl), (route, request) => {
|
36
|
+
const price = request.url().substring(mockAdUrl.length);
|
37
|
+
route.fulfill({
|
38
|
+
contentType: 'text/html',
|
39
|
+
body: `
|
40
|
+
<p id="the-ad">
|
41
|
+
This is the ad
|
42
|
+
<span id="ad-price">${price}</span>
|
43
|
+
</p>'
|
44
|
+
`
|
45
|
+
})
|
46
|
+
});
|
47
|
+
}
|
48
|
+
};
|
49
|
+
|
50
|
+
})()
|
51
|
+
].forEach(({t, bidResponse, setup}) => {
|
52
|
+
test.describe(t, () => {
|
53
|
+
test.beforeEach(async ({page}) => {
|
54
|
+
await setup(page);
|
55
|
+
await page.goto(`banner.html?creative=${creative}&bidResponse=${encodeURIComponent(JSON.stringify(bidResponse))}`)
|
56
|
+
});
|
57
|
+
test('should display ad', async ({crossLocator}) => {
|
58
|
+
await expect(await crossLocator('#the-ad')).toBeVisible();
|
59
|
+
});
|
60
|
+
['adRenderSucceeded', 'bidWon'].forEach(ev => {
|
61
|
+
test(`should emit '${ev}'`, async ({expectEvent}) => {
|
62
|
+
await expectEvent((event) => event.eventType === ev && event.args.adId === 'mock-ad')
|
63
|
+
})
|
64
|
+
});
|
65
|
+
test('should replace AUCTION_PRICE macro', async ({crossLocator}) => {
|
66
|
+
await expect(await crossLocator('#the-ad #ad-price')).toHaveText('1.23');
|
67
|
+
});
|
68
|
+
|
69
|
+
})
|
70
|
+
});
|
71
|
+
test.describe('Missing ad', () => {
|
72
|
+
const bidResponse = {
|
73
|
+
adId: 'mock-ad',
|
74
|
+
ad: null,
|
75
|
+
}
|
76
|
+
test.beforeEach(async ({page}) => {
|
77
|
+
await page.goto(`banner.html?creative=${creative}&bidResponse=${encodeURIComponent(JSON.stringify(bidResponse))}`);
|
78
|
+
});
|
79
|
+
test('should emit \'adRenderFailed\'', async ({expectEvent}) => {
|
80
|
+
await expectEvent((ev) => ev.eventType === 'adRenderFailed')
|
81
|
+
})
|
82
|
+
});
|
83
|
+
});
|
84
|
+
})
|
85
|
+
});
|