Skip to content

Commit

Permalink
Initial integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dgirardi committed Sep 30, 2022
1 parent 68d81fc commit 0c446a5
Show file tree
Hide file tree
Showing 16 changed files with 20,666 additions and 179 deletions.
71 changes: 42 additions & 29 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,61 @@
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2
aliases:
- &environment
resource_class: xlarge
working_directory: ~/prebid-universal-creative

jobs:
build:
unit-tests:
<<: *environment
docker:
# specify the version you desire here
- image: circleci/node:14.18.2-browsers

# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/mongo:3.4.4

working_directory: ~/prebid-universal-creative

steps:
- checkout

# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-

- v1-dependencies-unit-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-unit
- run: npm install

- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}

- run: sudo npm install -g gulp
# Download and run BrowserStack local
key: v1-dependencies-unit-{{ checksum "package.json" }}
- run:
name : Download BrowserStack Local binary and start it.
command : |
# Download the browserstack binary file
wget "https://www.browserstack.com/browserstack-local/BrowserStackLocal-linux-x64.zip"
# Unzip it
unzip BrowserStackLocal-linux-x64.zip
# Run the file with user's access key
./BrowserStackLocal ${BROWSERSTACK_ACCESS_KEY} &
# run tests!
name: Install gulp cli
command: sudo npm install -g gulp-cli
- run:
name: BrowserStack testing
command: gulp test --browserstack

integ-tests:
<<: *environment
docker:
- image: mcr.microsoft.com/playwright:v1.26.0-focal
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-integ-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-iteg
- run: npm install
- save_cache:
paths:
- node_modules
key: v1-dependencies-integ-{{ checksum "package.json" }}
- run:
name: Install playwright browsers
command: npx playwright install --with-deps
- run:
name: Integ tests
command: npx playwright test
workflows:
version: 2
test:
jobs:
- unit-tests
- integ-tests
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Built files
/playwright-report/
node_modules/
build
coverage
/build
coverage
dist/
4 changes: 4 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/playwright-report/
node_modules/
/build
coverage
1 change: 0 additions & 1 deletion .nvmrc

This file was deleted.

32 changes: 12 additions & 20 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const KarmaServer = require('karma').Server;
const karmaConfMaker = require('./karma.conf.maker');
const execa = require('execa');
const path = require('path');
const {execSync} = require('child_process');

const dateString = 'Updated : ' + (new Date()).toISOString().substring(0, 10);
const banner = '/* <%= creative.name %> v<%= creative.version %>\n' + dateString + ' */\n';
Expand Down Expand Up @@ -166,20 +167,10 @@ function includeStaticVastXmlFile() {
//
// If --watch is given, the task will open the karma debug window
// If --browserstack is given, it will run the full suite of currently supported browsers.
// If --e2e is given, it will run test defined in ./test/e2e/specs in browserstack

function test(done) {
if (argv.e2e) {
let wdioCmd = path.join(__dirname, 'node_modules/.bin/wdio');
let wdioConf = path.join(__dirname, 'wdio.conf.js');
let wdioOpts = [
wdioConf
];
return execa(wdioCmd, wdioOpts, { stdio: 'inherit' });
} else {
let karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch);
new KarmaServer(karmaConf, newKarmaCallback(done)).start();
}
let karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch);
new KarmaServer(karmaConf, newKarmaCallback(done)).start();
}

function newKarmaCallback(done) {
Expand All @@ -195,18 +186,11 @@ function newKarmaCallback(done) {
process.exit(exitCode);
}
}
}
}

function setupE2E(done) {
argv.e2e = true;
done();
}
}

gulp.task('test', gulp.series(clean, test));

gulp.task('e2e-test', gulp.series(clean, setupE2E, gulp.parallel(buildDev, buildCookieSync, buildCookieSyncWithConsent, buildNativeDev, buildNativeRenderDev, buildUidDev, includeStaticVastXmlFile, watch), test));

function watch(done) {
const mainWatcher = gulp.watch([
'src/**/*.js',
Expand Down Expand Up @@ -236,6 +220,14 @@ gulp.task('test-coverage', (done) => {
new KarmaServer(karmaConfMaker(true, false, false), newKarmaCallback(done)).start();
});

function integTests(done) {
execSync('npx playwright test', {stdio: 'inherit'});
done();
}

gulp.task('integ-tests', gulp.series(clean, 'build', integTests));


gulp.task('view-coverage', (done) => {
const coveragePort = 1999;
const localhost = (argv.host) ? argv.host : 'localhost';
Expand Down
62 changes: 62 additions & 0 deletions integ-test/fixtures/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {test as baseTest} from '@playwright/test';
import path from 'path';

export {expect} from '@playwright/test';
export const BASE_URL = 'https://www.prebid.org/puc-test/';
export const PUC_URL = 'https://cdn.jsdelivr.net/npm/prebid-universal-creative@latest/dist/';

const REDIRECTS = {
[BASE_URL]: '../pages',
[PUC_URL]: '../../dist'
};

export const test = baseTest.extend({
/**
* Replace requests for "https://www.prebid.org" with the contents of files under "pages",
* and requests for the PUC CDN with contents of files under "dist".
*/
async context({context}, use) {
await Promise.all(
Object.entries(REDIRECTS).map(([url, localDir]) => {
context.route((u) => u.href.startsWith(url), (route, request) => {
const fpath = request.url().substring(url.length).split('?')[0];
route.fulfill({
path: path.resolve(__dirname, localDir, fpath)
});
});
})
);
await use(context);
},
/**
* await crossLocator(selector): returns a locator for the first element matching 'selector' that appears on the
* page, across all frames.
*/
async crossLocator({page}, use) {
use(function (selector) {
let n = 0;
return new Promise((resolve, reject) => {
async function frameLocator(frame) {
if (!frame.isDetached()) {
n++;
try {
await frame.waitForSelector(selector);
resolve(frame.locator(selector));
} catch (e) {
n--;
if (n === 0) {
reject(e);
}
}
}
}
page.on('frameattached', frameLocator);
function walkFrames(frame) {
frameLocator(frame);
frame.childFrames().forEach(walkFrames)
}
walkFrames(page.mainFrame());
})
})
},
});
99 changes: 99 additions & 0 deletions integ-test/pages/banner.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>Prebid.js Banner Test</title>

<!-- Prebid.js -->
<script async src="https://cdn.jsdelivr.net/npm/prebid.js@latest/dist/not-for-prod/prebid.js"></script>

<!-- Google Publisher Tag -->
<script async src="https://www.googletagservices.com/tag/js/gpt.js"></script>

<script>
var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];
window.params = new URLSearchParams(window.location.search);
</script>

<script>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];

googletag.cmd.push(function () {
googletag.pubads().disableInitialLoad();
});

pbjs.que.push(function () {
pbjs.setConfig({
debug: true,
debugging: {
enabled: true,
intercept: [
{
when: {},
then: {
ad: '<p id="the-ad">This is the ad</p>',
mediaType: params.get('mediaType') || 'banner'
}
}
]
}
});

pbjs.requestBids({
bidsBackHandler: sendAdServerRequest,
adUnits: [
{
code: 'slot',
mediaTypes: {
banner: {
sizes: [[300, 250]],
}
},
bids: [{
bidder: 'appnexus',
params: {
placementId: 123
}
}]
}
]
});
});

function sendAdServerRequest() {
googletag.cmd.push(function () {
pbjs.que.push(function () {
pbjs.setTargetingForGPTAsync('slot');
googletag.pubads().refresh();
});
});
}
</script>

<script>
googletag.cmd.push(function () {
googletag
.defineSlot('/41758329/integ-test', [[300, 250]], 'slot')
.setTargeting('creative', params.get('creative'))
.addService(googletag.pubads());

googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
</script>
</head>

<body>
<h2>Prebid.js Banner Ad Unit Test</h2>
<div id='slot'>
<script>
googletag.cmd.push(function () {
googletag.display('slot');
});
</script>
</div>
</body>
</html>
25 changes: 25 additions & 0 deletions integ-test/spec/banner_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {test, expect} from '../fixtures/test.js';

test.describe('Banner', () => {
Object.entries({
'safeframe': 'banner-safeframe',
'non safeframe': 'banner-noframe'
}).forEach(([t, creative]) => {
test.describe(t, () => {
test.beforeEach(async ({page}) => {
await page.goto(`banner.html?creative=${creative}`)
});
test('should display ad', async ({crossLocator}) => {
await expect(await crossLocator('#the-ad')).toBeVisible();
});
test('should emit AD_RENDER_SUCCEEDED', async ({page}) => {
await expect.poll(async () =>
await page.evaluate(() =>
window.pbjs?.getEvents &&
window.pbjs.getEvents().filter((ev) => ev.eventType === 'adRenderSucceeded').length > 0
)
).toBeTruthy();
});
})
})
});
24 changes: 24 additions & 0 deletions integ-test/spec/render_failed_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {test, expect} from'../fixtures/test.js';

test.describe('video render', () => {
Object.entries({
// safeframe should not render video ads, and emit AD_RENDER_FAILED
// this does not work currently; mediaType is not in the message payload
// 'safeframe': 'banner-safeframe',
'non safeframe': 'banner-noframe'
}).forEach(([t, creative]) => {
test.describe(t, () => {
test.beforeEach(async ({page}) => {
await page.goto(`banner.html?creative=${creative}&mediaType=video`);
});
test('should emit AD_RENDER_FAILED', async ({page}) => {
await expect.poll(async () =>
await page.evaluate(() =>
window.pbjs?.getEvents &&
window.pbjs.getEvents().filter(ev => ev.eventType === 'adRenderFailed').length > 0
)
).toBeTruthy();
})
})
})
})
Loading

0 comments on commit 0c446a5

Please sign in to comment.