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