| 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"', |
| ); |
| }); |
| }); |
| }); |