blob: 0168f73a196e9969e74249745ff7c9ed30dcca61 [file] [log] [blame]
import * as http from 'http';
import * as net from 'net';
import express from 'express';
import puppeteer from 'puppeteer';
import { expect } from 'chai';
import {
EventName,
addEventListenersToPuppeteerPage,
launchBrowser,
} from './util';
describe('utility functions for Puppeteer tests', async () => {
let browser: puppeteer.Browser;
before(async () => {
browser = await launchBrowser();
});
after(async () => {
await browser.close();
});
let page: puppeteer.Page;
beforeEach(async () => {
page = await browser.newPage();
});
afterEach(async () => {
await page.close();
});
describe('addEventListenersToPuppeteerPage', () => {
let server: http.Server;
let testPageUrl: string;
// Type for the custom event details used in this test.
interface TestEventDetail {
msg: string;
}
beforeEach(async () => {
// Start an HTTP server on a random, unused port.
const app = express();
await new Promise((resolve) => {
server = app.listen(0, () => resolve(undefined));
});
testPageUrl = `http://localhost:${
(server!.address() as net.AddressInfo).port
}/`;
// Serve a test page that triggers various custom events.
app.get('/', (req, res) => res.send(`
<html>
<head>
<script>
async function triggerEvent(name, detail) {
document.dispatchEvent(
new CustomEvent(name, {detail: detail, bubbles: true}));
await new Promise((resolve) => setTimeout(resolve, 10));
}
// This is necessary as await is not allowed outside a function.
async function main() {
await triggerEvent('alpha-event',
{msg: 'Only occurrence of alpha-event'});
await triggerEvent('beta-event',
{msg: '1st occurrence of beta-event'});
await triggerEvent('beta-event',
{msg: '2nd occurrence of beta-event'});
await triggerEvent('beta-event',
{msg: '3rd occurrence of beta-event'});
// No test case should create a promise for this event. The goal
// is to test that no promise accidentally resolves to this guy.
await triggerEvent('ignored-event',
{msg: 'No test case should catch me'});
await triggerEvent('gamma-event',
{msg: '1st occurrence of gamma-event'});
await triggerEvent('gamma-event',
{msg: '2nd occurrence of gamma-event'});
await triggerEvent('gamma-event',
{msg: '3rd occurrence of gamma-event'});
}
main();
</script>
</head>
<body>
<h1>Hello, world!</h1>
<p>I am just a test page.</p>
</body>
</html>
`));
});
afterEach((done) => server.close(done));
it('renders test page correctly', async () => {
await page.goto(testPageUrl);
expect(
await page.$eval('h1', (el) => (el as HTMLElement).innerText),
).to.equal('Hello, world!');
expect(
await page.$eval('p', (el) => (el as HTMLElement).innerText),
).to.equal('I am just a test page.');
});
it('catches events in the right order', async () => {
// Add event listeners.
const eventNames: EventName[] = [
'alpha-event',
'beta-event',
'gamma-event',
// We purposefully add a listener for ignored-event, but we won't try
// to catch any such events. This is to test that uncaught events do
// not interfere with the events we're trying to catch.
'ignored-event',
];
const eventPromise = await addEventListenersToPuppeteerPage(
page,
eventNames,
);
// We will collect the Event object details in the order they are caught.
const eventDetailsInOrder: TestEventDetail[] = [];
const trackCaughtOrder = async (
anEventPromise: Promise<TestEventDetail>,
) => {
const detail = await anEventPromise;
eventDetailsInOrder.push(detail);
return detail;
};
// We create event promises in an arbitrary order to test that this has no
// effect in the order that events are caught.
const allEventDetailsPromise = Promise.all([
trackCaughtOrder(eventPromise<TestEventDetail>('gamma-event')),
trackCaughtOrder(eventPromise<TestEventDetail>('alpha-event')),
trackCaughtOrder(eventPromise<TestEventDetail>('gamma-event')),
trackCaughtOrder(eventPromise<TestEventDetail>('beta-event')),
trackCaughtOrder(eventPromise<TestEventDetail>('gamma-event')),
trackCaughtOrder(eventPromise<TestEventDetail>('beta-event')),
trackCaughtOrder(eventPromise<TestEventDetail>('beta-event')),
]);
await page.goto(testPageUrl);
// Assert that each promise returned the expected event detail.
const allEventDetails = await allEventDetailsPromise;
expect(allEventDetails).to.have.length(7);
expect(allEventDetails[0].msg).to.equal('1st occurrence of gamma-event');
expect(allEventDetails[1].msg).to.equal('Only occurrence of alpha-event');
expect(allEventDetails[2].msg).to.equal('2nd occurrence of gamma-event');
expect(allEventDetails[3].msg).to.equal('1st occurrence of beta-event');
expect(allEventDetails[4].msg).to.equal('3rd occurrence of gamma-event');
expect(allEventDetails[5].msg).to.equal('2nd occurrence of beta-event');
expect(allEventDetails[6].msg).to.equal('3rd occurrence of beta-event');
// Assert that promises were resolved in the expected order.
expect(eventDetailsInOrder).to.have.length(7);
expect(eventDetailsInOrder[0].msg).to.equal(
'Only occurrence of alpha-event',
);
expect(eventDetailsInOrder[1].msg).to.equal(
'1st occurrence of beta-event',
);
expect(eventDetailsInOrder[2].msg).to.equal(
'2nd occurrence of beta-event',
);
expect(eventDetailsInOrder[3].msg).to.equal(
'3rd occurrence of beta-event',
);
expect(eventDetailsInOrder[4].msg).to.equal(
'1st occurrence of gamma-event',
);
expect(eventDetailsInOrder[5].msg).to.equal(
'2nd occurrence of gamma-event',
);
expect(eventDetailsInOrder[6].msg).to.equal(
'3rd occurrence of gamma-event',
);
});
it('fails if event promise function is called with unknown event', async () => {
const eventPromise = await addEventListenersToPuppeteerPage(page, [
'foo-event',
]);
expect(() => eventPromise('invalid-event')).to.throw(
'no event listener for "invalid-event"',
);
});
});
});