import { HTTPResponse, Page, WaitForOptions } from 'puppeteer'; import { EventSpy } from './events.ts'; import { E2EElement } from './element.ts'; export interface PageDiagnostic { type: "error" | "pageerror" | "requestfailed"; message?: string; location?: string; } /** * The E2EPage is a wrapper utility to Puppeteer in order to * to create easier to write and read end-to-end tests. */ export interface E2EPage extends Page { /** * Sets a debugger; */ debugger: () => Promise; /** * Find an element that matches the selector, which is the same as * `document.querySelector(selector)`. Use `>>>` within the * selector to find an element within the host element's shadow root. * For example, to select the first `div` inside of the component * `my-cmp`, the call would be `page.find('my-cmp >>> div')`. * Returns `null` if an element was not found. */ find: (selector: FindSelector) => Promise; /** * Find all elements that match the selector, which is the same as * `document.querySelectorAll(selector)`. Use `>>>` within the * selector to find elements within the host element's shadow root. * For example, to select all of the `li` elements inside of the component * `my-cmp`, the call would be `page.findAll('my-cmp >>> li')`. * Returns an empty array if no elements were found. */ findAll: (selector: string) => Promise; /** * During an end-to-end test, a dev-server is started so `page.goto(url)` can be used * on the app being tested. Urls are always relative since the dev server provides * a localhost address. A shortcut to `page.goto(url)` is to set the `url` option * when creating a new page, such as `const page = await newE2EPage({ url })`. */ goTo: (url: string, options?: WaitForOptions) => Promise; /** * Instead of testing a url directly, html content can be mocked using * `page.setContent(html)`. A shortcut to `page.setContent(html)` is to set * the `html` option when creating a new page, such as * `const page = await newE2EPage({ html })`. */ setContent: (html: string, options?: WaitForOptions) => Promise; /** * Used to test if an event was, or was not dispatched. This method * returns a promise, that resolves with an EventSpy. The EventSpy * can be used along with `expect(spy).toHaveReceivedEvent()`, * `expect(spy).toHaveReceivedEventTimes(x)` and * `expect(spy).toHaveReceivedEventDetail({...})`. */ spyOnEvent: (eventName: string, selector?: "document" | "window") => Promise>; /** * Puppeteer has asynchronous architecture. Since all calls are async, it's * required that `await page.waitForChanges()` is called when changes are * made to components. * An error will be thrown if changes were made to a component but * `waitForChanges()` was not called. * * @param delay - The number of milliseconds to wait after components * finish updating. Default value is determined by the * `puppeteerTesting.waitForChangesDelay` option passed to useLumina(). */ waitForChanges: (delay?: number) => Promise; /** * Waits for the event to be received on `window`. The optional second argument * allows the listener to be set to `document` if needed. */ waitForEvent: (eventName: string) => Promise>; getDiagnostics: () => PageDiagnostic[]; isClosed: () => boolean; /** * Causes your script to wait for the given number of milliseconds. * * @remarks * * It's generally recommended to not wait for a number of seconds, but instead * use {@link Frame.waitForSelector}, {@link Frame.waitForXPath} or * {@link Frame.waitForFunction} to wait for exactly the conditions you want. * * @example * * Wait for 1 second: * * ```ts * await page.waitForTimeout(1000); * ``` * * @param milliseconds - the number of milliseconds to wait. */ waitForTimeout: (milliseconds: number) => Promise; /** @private */ _e2eElements: E2EElement[]; /** @private */ _e2eEvents: Map; /** @private */ _e2eEventIds: number; /** @private */ _originalClose: Page["close"]; /** @private */ _isWaitingForAllReady: boolean; /** @private */ _unhandledError: unknown; } export interface SerializedEvent { bubbles: boolean; cancelable: boolean; composed: boolean; currentTarget: SerializedElement; defaultPrevented: boolean; detail: Detail; eventPhase: number; isTrusted: boolean; target: SerializedElement; timeStamp: number; type: string; isSerializedEvent: boolean; } export type SerializedElement = Record | null; export type FindSelector = FindSelectorOptions | string; export interface FindSelectorOptions { /** * Finds an element with text content matching this * exact value after the whitespace has been trimmed. */ text?: string; /** * Finds an element with text content containing this value. */ contains?: string; } export interface WaitForEventOptions { timeout?: number; } export interface WaitForEvent { eventName: string; callback: (event: SerializedEvent) => void; } export interface BrowserWindow extends Window { puppeteerAwaitAllReady: () => Promise; puppeteerOnEvent: (id: number, event: SerializedEvent) => void; puppeteerSerializeEvent: (event: CustomEvent | Event) => SerializedEvent; puppeteerSerializeEventTarget: (target: Element | EventTarget | null) => SerializedElement; }