@molecule/app-e2e-fixtures-default

Feature · e2e-fixtures-default · App (browser) · v1.2.2 · Apache-2.0

The @playwright/test drop-in for molecule apps: Playwright's test, expect and page with the browser supplied by the bonded e2e provider (live preview or real browsers), a console-error guard on every test, and the Playwright-shaped page adapter for evaluate-only bonds.

npm install @molecule/app-e2e-fixtures-default

npm · Source on GitHub

How it works

@molecule/app-e2e-fixtures-default is a ready-made e2e-fixtures-default feature for the app (browser) side. It composes the core interfaces it needs, so it works with whichever providers your app has bonded.

// e2e/bonds.ts — scaffolded; wires the provider for THIS environment
import { resolveE2EProviderName, setProvider } from '@molecule/app-e2e'
import { provider as playwright } from '@molecule/app-e2e-playwright'
import { provider as preview } from '@molecule/app-e2e-preview'

setProvider(resolveE2EProviderName() === 'preview' ? preview : playwright)

// e2e/post.spec.ts — an ordinary Playwright spec
import { expect, test } from '@molecule/app-e2e-fixtures-default'

import './bonds.js'

test('the phone layout keeps the prose large', async ({ page }) => {
  await page.setViewportSize({ width: 390, height: 844 })
  await page.goto('/blog/hello/')
  const prose = page.locator('article p').first()
  const size = await prose.evaluate((el) => parseFloat(getComputedStyle(el).fontSize))
  expect(size).toBeGreaterThanOrEqual(18)
  await expect(page.getByRole('switch', { name: /summar/i })).toBeVisible()
})

Works with: @molecule/app-bond, @molecule/app-e2e

Reference

The @playwright/test drop-in for molecule apps: Playwright's test, expect and page, with the browser supplied by the bonded e2e provider and a console-error guard on every test.

Import test and expect from here instead of @playwright/test and write ordinary Playwright specs. Which browser runs them is the e2e bond (@molecule/app-e2e):

  • @molecule/app-e2e-playwright launches a real Playwright browser. Every molecule sandbox image bakes Chromium, so this is what a sandbox uses as well as your own machine and CI — the specs run against the app's dev server on localhost, no IDE tab involved.
  • @molecule/app-e2e-preview drives the LIVE PREVIEW the molecule.dev IDE is showing — the page the person is looking at, in their own browser — over a WebSocket through the dev server. Pick it with MOL_E2E_PROVIDER=preview when the point is that tab.

The same spec file runs unchanged in both. The provider is picked by resolveE2EProviderName(): MOL_E2E_PROVIDER when set; otherwise, inside a molecule sandbox (the /etc/mol/app-root marker exists), playwright when a Playwright browser is installed and preview when none is; and playwright everywhere else. The scaffolded e2e/bonds.ts bonds the matching provider (and test bonds it by name as a fallback); test reads the same answer to decide whether to launch a browser.

Every test also carries the console-error guard: the page's pageerror and console.error events fail the test at teardown, so a spec that only asserts on page.request cannot stay green while the rendered page is blank. Allow a known error with test.info().annotations.push({ type: 'allow-console-error', description: '<regex>' }).

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Quick Start

// e2e/bonds.ts — scaffolded; wires the provider for THIS environment
import { resolveE2EProviderName, setProvider } from '@molecule/app-e2e'
import { provider as playwright } from '@molecule/app-e2e-playwright'
import { provider as preview } from '@molecule/app-e2e-preview'

setProvider(resolveE2EProviderName() === 'preview' ? preview : playwright)

// e2e/post.spec.ts — an ordinary Playwright spec
import { expect, test } from '@molecule/app-e2e-fixtures-default'

import './bonds.js'

test('the phone layout keeps the prose large', async ({ page }) => {
  await page.setViewportSize({ width: 390, height: 844 })
  await page.goto('/blog/hello/')
  const prose = page.locator('article p').first()
  const size = await prose.evaluate((el) => parseFloat(getComputedStyle(el).fontSize))
  expect(size).toBeGreaterThanOrEqual(18)
  await expect(page.getByRole('switch', { name: /summar/i })).toBeVisible()
})

Type

feature

Installation

npm install @molecule/app-e2e-fixtures-default @molecule/app-bond @molecule/app-e2e @playwright/test

API

Interfaces

Page

Page provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. One Browser instance might have multiple Page instances.

This example creates a page, navigates it to a URL, and then saves a screenshot:

const { webkit } = require('playwright') // Or 'chromium' or 'firefox'.

;(async () => {
  const browser = await webkit.launch()
  const context = await browser.newContext()
  const page = await context.newPage()
  await page.goto('https://example.com')
  await page.screenshot({ path: 'screenshot.png' })
  await browser.close()
})()

The Page class emits various events (described below) which can be handled using any of Node's native EventEmitter methods, such as on, once or removeListener.

This example logs a message for a single page load event:

page.once('load', () => console.log('Page loaded!'))

To unsubscribe from events use the removeListener method:

function logRequest(interceptedRequest) {
  console.log('A request was made:', interceptedRequest.url())
}
page.on('request', logRequest)
// Sometime later...
page.removeListener('request', logRequest)
interface Page {
  /**
   * Returns the value of the
   * [`pageFunction`](https://playwright.dev/docs/api/class-page#page-evaluate-option-expression) invocation.
   *
   * If the function passed to the
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate) returns a
   * [Promise], then
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate) would wait
   * for the promise to resolve and return its value.
   *
   * If the function passed to the
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate) returns a
   * non-[Serializable] value, then
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate) resolves to
   * `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`:
   * `-0`, `NaN`, `Infinity`, `-Infinity`.
   *
   * **Usage**
   *
   * Passing argument to [`pageFunction`](https://playwright.dev/docs/api/class-page#page-evaluate-option-expression):
   *
   * ```js
   * const result = await page.evaluate(([x, y]) => {
   *   return Promise.resolve(x * y);
   * }, [7, 8]);
   * console.log(result); // prints "56"
   * ```
   *
   * A string can also be passed in instead of a function:
   *
   * ```js
   * console.log(await page.evaluate('1 + 2')); // prints "3"
   * const x = 10;
   * console.log(await page.evaluate(`1 + ${x}`)); // prints "11"
   * ```
   *
   * [ElementHandle](https://playwright.dev/docs/api/class-elementhandle) instances can be passed as an argument to the
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate):
   *
   * ```js
   * const bodyHandle = await page.evaluateHandle('document.body');
   * const html = await page.evaluate<string, HTMLElement>(([body, suffix]) =>
   *   body.innerHTML + suffix, [bodyHandle, 'hello']
   * );
   * await bodyHandle.dispose();
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-page#page-evaluate-option-expression).
   * @param options
   */
  evaluate<R, Arg>(pageFunction: PageFunction<Arg, R>, arg: Arg, options?: { exposeFunctions?: boolean }): Promise<R>;
  /**
   * Returns the value of the
   * [`pageFunction`](https://playwright.dev/docs/api/class-page#page-evaluate-option-expression) invocation.
   *
   * If the function passed to the
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate) returns a
   * [Promise], then
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate) would wait
   * for the promise to resolve and return its value.
   *
   * If the function passed to the
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate) returns a
   * non-[Serializable] value, then
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate) resolves to
   * `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`:
   * `-0`, `NaN`, `Infinity`, `-Infinity`.
   *
   * **Usage**
   *
   * Passing argument to [`pageFunction`](https://playwright.dev/docs/api/class-page#page-evaluate-option-expression):
   *
   * ```js
   * const result = await page.evaluate(([x, y]) => {
   *   return Promise.resolve(x * y);
   * }, [7, 8]);
   * console.log(result); // prints "56"
   * ```
   *
   * A string can also be passed in instead of a function:
   *
   * ```js
   * console.log(await page.evaluate('1 + 2')); // prints "3"
   * const x = 10;
   * console.log(await page.evaluate(`1 + ${x}`)); // prints "11"
   * ```
   *
   * [ElementHandle](https://playwright.dev/docs/api/class-elementhandle) instances can be passed as an argument to the
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate):
   *
   * ```js
   * const bodyHandle = await page.evaluateHandle('document.body');
   * const html = await page.evaluate<string, HTMLElement>(([body, suffix]) =>
   *   body.innerHTML + suffix, [bodyHandle, 'hello']
   * );
   * await bodyHandle.dispose();
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-page#page-evaluate-option-expression).
   * @param options
   */
  evaluate<R>(pageFunction: PageFunction<void, R>, arg?: any, options?: { exposeFunctions?: boolean }): Promise<R>;

  /**
   * Returns the value of the
   * [`pageFunction`](https://playwright.dev/docs/api/class-page#page-evaluate-handle-option-expression) invocation as a
   * [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * The only difference between
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate) and
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle)
   * is that
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle)
   * returns [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * If the function passed to the
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle)
   * returns a [Promise], then
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle)
   * would wait for the promise to resolve and return its value.
   *
   * **Usage**
   *
   * ```js
   * // Handle for the window object.
   * const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
   * ```
   *
   * A string can also be passed in instead of a function:
   *
   * ```js
   * const aHandle = await page.evaluateHandle('document'); // Handle for the 'document'
   * ```
   *
   * [JSHandle](https://playwright.dev/docs/api/class-jshandle) instances can be passed as an argument to the
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle):
   *
   * ```js
   * const aHandle = await page.evaluateHandle(() => document.body);
   * const resultHandle = await page.evaluateHandle(body => body.innerHTML, aHandle);
   * console.log(await resultHandle.jsonValue());
   * await resultHandle.dispose();
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-page#page-evaluate-handle-option-expression).
   * @param options
   */
  evaluateHandle<R, Arg>(pageFunction: PageFunction<Arg, R>, arg: Arg, options?: { exposeFunctions?: boolean }): Promise<SmartHandle<R>>;
  /**
   * Returns the value of the
   * [`pageFunction`](https://playwright.dev/docs/api/class-page#page-evaluate-handle-option-expression) invocation as a
   * [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * The only difference between
   * [page.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate) and
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle)
   * is that
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle)
   * returns [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * If the function passed to the
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle)
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

Frame

At every point of time, page exposes its current frame tree via the page.mainFrame() and frame.childFrames() methods.

Frame object's lifecycle is controlled by three events, dispatched on the page object:

An example of dumping frame tree:

const { firefox } = require('playwright') // Or 'chromium' or 'webkit'.

;(async () => {
  const browser = await firefox.launch()
  const page = await browser.newPage()
  await page.goto('https://www.google.com/chrome/browser/canary.html')
  dumpFrameTree(page.mainFrame(), '')
  await browser.close()

  function dumpFrameTree(frame, indent) {
    console.log(indent + frame.url())
    for (const child of frame.childFrames()) dumpFrameTree(child, indent + '  ')
  }
})()
interface Frame {
  /**
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-frame#frame-evaluate-option-expression).
   *
   * If the function passed to the
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate) returns
   * a [Promise], then
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate) would
   * wait for the promise to resolve and return its value.
   *
   * If the function passed to the
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate) returns
   * a non-[Serializable] value, then
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate) returns
   * `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`:
   * `-0`, `NaN`, `Infinity`, `-Infinity`.
   *
   * **Usage**
   *
   * ```js
   * const result = await frame.evaluate(([x, y]) => {
   *   return Promise.resolve(x * y);
   * }, [7, 8]);
   * console.log(result); // prints "56"
   * ```
   *
   * A string can also be passed in instead of a function.
   *
   * ```js
   * console.log(await frame.evaluate('1 + 2')); // prints "3"
   * ```
   *
   * [ElementHandle](https://playwright.dev/docs/api/class-elementhandle) instances can be passed as an argument to the
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate):
   *
   * ```js
   * const bodyHandle = await frame.evaluateHandle('document.body');
   * const html = await frame.evaluate(([body, suffix]) =>
   *   body.innerHTML + suffix, [bodyHandle, 'hello'],
   * );
   * await bodyHandle.dispose();
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-frame#frame-evaluate-option-expression).
   * @param options
   */
  evaluate<R, Arg>(pageFunction: PageFunction<Arg, R>, arg: Arg, options?: { exposeFunctions?: boolean }): Promise<R>;
  /**
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-frame#frame-evaluate-option-expression).
   *
   * If the function passed to the
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate) returns
   * a [Promise], then
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate) would
   * wait for the promise to resolve and return its value.
   *
   * If the function passed to the
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate) returns
   * a non-[Serializable] value, then
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate) returns
   * `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`:
   * `-0`, `NaN`, `Infinity`, `-Infinity`.
   *
   * **Usage**
   *
   * ```js
   * const result = await frame.evaluate(([x, y]) => {
   *   return Promise.resolve(x * y);
   * }, [7, 8]);
   * console.log(result); // prints "56"
   * ```
   *
   * A string can also be passed in instead of a function.
   *
   * ```js
   * console.log(await frame.evaluate('1 + 2')); // prints "3"
   * ```
   *
   * [ElementHandle](https://playwright.dev/docs/api/class-elementhandle) instances can be passed as an argument to the
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate):
   *
   * ```js
   * const bodyHandle = await frame.evaluateHandle('document.body');
   * const html = await frame.evaluate(([body, suffix]) =>
   *   body.innerHTML + suffix, [bodyHandle, 'hello'],
   * );
   * await bodyHandle.dispose();
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-frame#frame-evaluate-option-expression).
   * @param options
   */
  evaluate<R>(pageFunction: PageFunction<void, R>, arg?: any, options?: { exposeFunctions?: boolean }): Promise<R>;

  /**
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle-option-expression) as a
   * [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * The only difference between
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate) and
   * [frame.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle)
   * is that
   * [frame.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle)
   * returns [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * If the function, passed to the
   * [frame.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle),
   * returns a [Promise], then
   * [frame.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle)
   * would wait for the promise to resolve and return its value.
   *
   * **Usage**
   *
   * ```js
   * // Handle for the window object
   * const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window));
   * ```
   *
   * A string can also be passed in instead of a function.
   *
   * ```js
   * const aHandle = await frame.evaluateHandle('document'); // Handle for the 'document'.
   * ```
   *
   * [JSHandle](https://playwright.dev/docs/api/class-jshandle) instances can be passed as an argument to the
   * [frame.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle):
   *
   * ```js
   * const aHandle = await frame.evaluateHandle(() => document.body);
   * const resultHandle = await frame.evaluateHandle(([body, suffix]) =>
   *   body.innerHTML + suffix, [aHandle, 'hello'],
   * );
   * console.log(await resultHandle.jsonValue());
   * await resultHandle.dispose();
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle-option-expression).
   * @param options
   */
  evaluateHandle<R, Arg>(pageFunction: PageFunction<Arg, R>, arg: Arg, options?: { exposeFunctions?: boolean }): Promise<SmartHandle<R>>;
  /**
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle-option-expression) as a
   * [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * The only difference between
   * [frame.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate) and
   * [frame.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle)
   * is that
   * [frame.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle)
   * returns [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * If the function, passed to the
   * [frame.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle),
   * returns a [Promise], then
   * [frame.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-frame#frame-evaluate-handle)
   * would wait for the promise to resolve and return its value.
   *
   * **Usage**
   *
   * ```js
   * // Handle for the window object
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

BrowserContext

BrowserContexts provide a way to operate multiple independent browser sessions.

If a page opens another page, e.g. with a window.open call, the popup will belong to the parent page's browser context.

Playwright allows creating isolated non-persistent browser contexts with browser.newContext([options]) method. Non-persistent browser contexts don't write any browsing data to disk.

// Create a new incognito browser context
const context = await browser.newContext()
// Create a new page inside context.
const page = await context.newPage()
await page.goto('https://example.com')
// Dispose context once it's no longer needed.
await context.close()
interface BrowserContext {
  /**
   * The method adds a function called
   * [`name`](https://playwright.dev/docs/api/class-browsercontext#browser-context-expose-binding-option-name) on the
   * `window` object of every frame in every page in the context. When called, the function executes
   * [`callback`](https://playwright.dev/docs/api/class-browsercontext#browser-context-expose-binding-option-callback)
   * and returns a [Promise] which resolves to the return value of
   * [`callback`](https://playwright.dev/docs/api/class-browsercontext#browser-context-expose-binding-option-callback).
   * If the
   * [`callback`](https://playwright.dev/docs/api/class-browsercontext#browser-context-expose-binding-option-callback)
   * returns a [Promise], it will be awaited.
   *
   * The first argument of the
   * [`callback`](https://playwright.dev/docs/api/class-browsercontext#browser-context-expose-binding-option-callback)
   * function contains information about the caller: `{ browserContext: BrowserContext, page: Page, frame: Frame }`.
   *
   * See [page.exposeBinding(name, callback)](https://playwright.dev/docs/api/class-page#page-expose-binding) for
   * page-only version.
   *
   * **Usage**
   *
   * An example of exposing page URL to all frames in all pages in the context:
   *
   * ```js
   * const { webkit } = require('playwright');  // Or 'chromium' or 'firefox'.
   *
   * (async () => {
   *   const browser = await webkit.launch({ headless: false });
   *   const context = await browser.newContext();
   *   await context.exposeBinding('pageURL', ({ page }) => page.url());
   *   const page = await context.newPage();
   *   await page.setContent(`
   *     <script>
   *       async function onClick() {
   *         document.querySelector('div').textContent = await window.pageURL();
   *       }
   *     </script>
   *     <button onclick="onClick()">Click me</button>
   *     <div></div>
   *   `);
   *   await page.getByRole('button').click();
   * })();
   * ```
   *
   * @param name Name of the function on the window object.
   * @param callback Callback function that will be called in the Playwright's context.
   */
  exposeBinding(name: string, playwrightBinding: (source: BindingSource, ...args: any[]) => any): Promise<Disposable>;

  /**
   * Adds a script which would be evaluated in one of the following scenarios:
   * - Whenever a page is created in the browser context or is navigated.
   * - Whenever a child frame is attached or navigated in any page in the browser context. In this case, the script is
   *   evaluated in the context of the newly attached frame.
   *
   * The script is evaluated after the document was created but before any of its scripts were run. This is useful to
   * amend the JavaScript environment, e.g. to seed `Math.random`.
   *
   * **Usage**
   *
   * An example of overriding `Math.random` before the page loads:
   *
   * ```js
   * // preload.js
   * Math.random = () => 42;
   * ```
   *
   * ```js
   * // In your playwright script, assuming the preload.js file is in same directory.
   * await browserContext.addInitScript({
   *   path: 'preload.js'
   * });
   * ```
   *
   * **NOTE** The order of evaluation of multiple scripts installed via
   * [browserContext.addInitScript(script[, arg, options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-add-init-script)
   * and [page.addInitScript(script[, arg, options])](https://playwright.dev/docs/api/class-page#page-add-init-script)
   * is not defined.
   *
   * @param script Script to be evaluated in all pages in the browser context.
   * @param arg Optional argument to pass to
   * [`script`](https://playwright.dev/docs/api/class-browsercontext#browser-context-add-init-script-option-script)
   * (only supported when passing a function).
   * @param options
   */
  addInitScript<Arg>(script: PageFunction<Arg, any> | { path?: string, content?: string }, arg?: Arg, options?: { exposeFunctions?: boolean }): Promise<Disposable>;

  /**
   * Removes all the listeners of the given type (or all registered listeners if no type given). Allows to wait for
   * async listeners to complete or to ignore subsequent errors from these listeners.
   * @param type
   * @param options
   */
  removeAllListeners(type?: string): this;
  /**
   * Removes all the listeners of the given type (or all registered listeners if no type given). Allows to wait for
   * async listeners to complete or to ignore subsequent errors from these listeners.
   * @param type
   * @param options
   */
  removeAllListeners(type: string | undefined, options: {
    /**
     * Specifies whether to wait for already running listeners and what to do if they throw errors:
     * - `'default'` - do not wait for current listener calls (if any) to finish, if the listener throws, it may result in unhandled error
     * - `'wait'` - wait for current listener calls (if any) to finish
     * - `'ignoreErrors'` - do not wait for current listener calls (if any) to finish, all errors thrown by the listeners after removal are silently caught
     */
    behavior?: 'wait'|'ignoreErrors'|'default'
  }): Promise<void>;

  /**
   * This event is not emitted.
   */
  on(event: 'backgroundpage', listener: (page: Page) => any): this;

  /**
   * Emitted when Browser context gets closed. This might happen because of one of the following:
   * - Browser context is closed.
   * - Browser application is closed or crashed.
   * - The [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close) method was called.
   */
  on(event: 'close', listener: (browserContext: BrowserContext) => any): this;

  /**
   * Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`.
   *
   * The arguments passed into `console.log` and the page are available on the
   * [ConsoleMessage](https://playwright.dev/docs/api/class-consolemessage) event handler argument.
   *
   * **Usage**
   *
   * ```js
   * context.on('console', async msg => {
   *   const values = [];
   *   for (const arg of msg.args())
   *     values.push(await arg.jsonValue());
   *   console.log(...values);
   * });
   * await page.evaluate(() => console.log('hello', 5, { foo: 'bar' }));
   * ```
   *
   */
  on(event: 'console', listener: (consoleMessage: ConsoleMessage) => any): this;

  /**
   * Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Listener **must**
   * either [dialog.accept([promptText])](https://playwright.dev/docs/api/class-dialog#dialog-accept) or
   * [dialog.dismiss()](https://playwright.dev/docs/api/class-dialog#dialog-dismiss) the dialog - otherwise the page
   * will [freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking) waiting for the
   * dialog, and actions like click will never finish.
   *
   * **Usage**
   *
   * ```js
   * context.on('dialog', dialog => {
   *   dialog.accept();
   * });
   * ```
   *
   * **NOTE** When no [page.on('dialog')](https://playwright.dev/docs/api/class-page#page-event-dialog) or
   * [browserContext.on('dialog')](https://playwright.dev/docs/api/class-browsercontext#browser-context-event-dialog)
   * listeners are present, all dialogs are automatically dismissed.
   *
   */
  on(event: 'dialog', listener: (dialog: Dialog) => any): this;

  /**
   * Emitted when a JavaScript dialog in any page belonging to this context has been closed, either by
   * [dialog.accept([promptText])](https://playwright.dev/docs/api/class-dialog#dialog-accept), by
   * [dialog.dismiss()](https://playwright.dev/docs/api/class-dialog#dialog-dismiss), or manually by the user in the
   * headed browser.
   */
  on(event: 'dialogclosed', listener: (dialog: Dialog) => any): this;

  /**
   * Emitted when attachment download started in any page belonging to this context. User can access basic file
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

Browser

A Browser is created via browserType.launch([options]). An example of using a Browser to create a Page:

const { firefox } = require('playwright') // Or 'chromium' or 'webkit'.

;(async () => {
  const browser = await firefox.launch()
  const page = await browser.newPage()
  await page.goto('https://example.com')
  await browser.close()
})()
interface Browser {
  /**
   * Removes all the listeners of the given type (or all registered listeners if no type given). Allows to wait for
   * async listeners to complete or to ignore subsequent errors from these listeners.
   * @param type
   * @param options
   */
  removeAllListeners(type?: string): this;
  /**
   * Removes all the listeners of the given type (or all registered listeners if no type given). Allows to wait for
   * async listeners to complete or to ignore subsequent errors from these listeners.
   * @param type
   * @param options
   */
  removeAllListeners(type: string | undefined, options: {
    /**
     * Specifies whether to wait for already running listeners and what to do if they throw errors:
     * - `'default'` - do not wait for current listener calls (if any) to finish, if the listener throws, it may result in unhandled error
     * - `'wait'` - wait for current listener calls (if any) to finish
     * - `'ignoreErrors'` - do not wait for current listener calls (if any) to finish, all errors thrown by the listeners after removal are silently caught
     */
    behavior?: 'wait'|'ignoreErrors'|'default'
  }): Promise<void>;
  /**
   * Emitted when a new browser context is created.
   */
  on(event: 'context', listener: (browserContext: BrowserContext) => any): this;

  /**
   * Emitted when Browser gets disconnected from the browser application. This might happen because of one of the
   * following:
   * - Browser application is closed or crashed.
   * - The [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close) method was called.
   */
  on(event: 'disconnected', listener: (browser: Browser) => any): this;

  /**
   * Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
   */
  once(event: 'context', listener: (browserContext: BrowserContext) => any): this;

  /**
   * Adds an event listener that will be automatically removed after it is triggered once. See `addListener` for more information about this event.
   */
  once(event: 'disconnected', listener: (browser: Browser) => any): this;

  /**
   * Emitted when a new browser context is created.
   */
  addListener(event: 'context', listener: (browserContext: BrowserContext) => any): this;

  /**
   * Emitted when Browser gets disconnected from the browser application. This might happen because of one of the
   * following:
   * - Browser application is closed or crashed.
   * - The [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close) method was called.
   */
  addListener(event: 'disconnected', listener: (browser: Browser) => any): this;

  /**
   * Removes an event listener added by `on` or `addListener`.
   */
  removeListener(event: 'context', listener: (browserContext: BrowserContext) => any): this;

  /**
   * Removes an event listener added by `on` or `addListener`.
   */
  removeListener(event: 'disconnected', listener: (browser: Browser) => any): this;

  /**
   * Removes an event listener added by `on` or `addListener`.
   */
  off(event: 'context', listener: (browserContext: BrowserContext) => any): this;

  /**
   * Removes an event listener added by `on` or `addListener`.
   */
  off(event: 'disconnected', listener: (browser: Browser) => any): this;

  /**
   * Emitted when a new browser context is created.
   */
  prependListener(event: 'context', listener: (browserContext: BrowserContext) => any): this;

  /**
   * Emitted when Browser gets disconnected from the browser application. This might happen because of one of the
   * following:
   * - Browser application is closed or crashed.
   * - The [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close) method was called.
   */
  prependListener(event: 'disconnected', listener: (browser: Browser) => any): this;

  /**
   * Binds the browser to a named pipe or web socket, making it available for other clients to connect to.
   * @param title Title of the browser server, used for identification.
   * @param options
   */
  bind(title: string, options?: {
    /**
     * Host to bind the web socket server to. When specified, a web socket server is created instead of a named pipe.
     */
    host?: string;

    /**
     * Additional metadata to associate with the browser server.
     */
    metadata?: { [key: string]: any; };

    /**
     * Port to bind the web socket server to. When specified, a web socket server is created instead of a named pipe. Use
     * `0` to let the OS pick an available port.
     */
    port?: number;

    /**
     * Working directory associated with this browser server.
     */
    workspaceDir?: string;
  }): Promise<{
    endpoint: string;
  }>;

  /**
   * Get the browser type (chromium, firefox or webkit) that the browser belongs to.
   */
  browserType(): BrowserType;

  /**
   * In case this browser is obtained using
   * [browserType.launch([options])](https://playwright.dev/docs/api/class-browsertype#browser-type-launch), closes the
   * browser and all of its pages (if any were opened).
   *
   * In case this browser is connected to, clears all created contexts belonging to this browser and disconnects from
   * the browser server.
   *
   * **NOTE** This is similar to force-quitting the browser. To close pages gracefully and ensure you receive page close
   * events, call
   * [browserContext.close([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-close) on
   * any [BrowserContext](https://playwright.dev/docs/api/class-browsercontext) instances you explicitly created earlier
   * using [browser.newContext([options])](https://playwright.dev/docs/api/class-browser#browser-new-context) **before**
   * calling [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close).
   *
   * The [Browser](https://playwright.dev/docs/api/class-browser) object itself is considered to be disposed and cannot
   * be used anymore.
   * @param options
   */
  close(options?: {
    /**
     * The reason to be reported to the operations interrupted by the browser closure.
     */
    reason?: string;
  }): Promise<void>;

  /**
   * Returns an array of all open browser contexts. In a newly created browser, this will return zero browser contexts.
   *
   * **Usage**
   *
   * ```js
   * const browser = await pw.webkit.launch();
   * console.log(browser.contexts().length); // prints `0`
   *
   * const context = await browser.newContext();
   * console.log(browser.contexts().length); // prints `1`
   * ```
   *
   */
  contexts(): Array<BrowserContext>;

  /**
   * Indicates that the browser is connected.
   */
  isConnected(): boolean;

  /**
   * **NOTE** CDP Sessions are only supported on Chromium-based browsers.
   *
   * Returns the newly created browser session.
   */
  newBrowserCDPSession(): Promise<CDPSession>;

  /**
   * Creates a new browser context. It won't share cookies/cache with other browser contexts.
   *
   * **NOTE** If directly using this method to create
   * [BrowserContext](https://playwright.dev/docs/api/class-browsercontext)s, it is best practice to explicitly close
   * the returned context via
   * [browserContext.close([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-close) when
   * your code is done with the [BrowserContext](https://playwright.dev/docs/api/class-browsercontext), and before
   * calling [browser.close([options])](https://playwright.dev/docs/api/class-browser#browser-close). This will ensure
   * the `context` is closed gracefully and any artifacts—like HARs and videos—are fully flushed and saved.
   *
   * **Usage**
   *
   * ```js
   * (async () => {
   *   const browser = await playwright.firefox.launch();  // Or 'chromium' or 'webkit'.
   *   // Create a new incognito browser context.
   *   const context = await browser.newContext();
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

JSHandle

JSHandle represents an in-page JavaScript object. JSHandles can be created with the page.evaluateHandle(pageFunction[, arg, options]) method.

const windowHandle = await page.evaluateHandle(() => window)
// ...

JSHandle prevents the referenced JavaScript object being garbage collected unless the handle is exposed with jsHandle.dispose(). JSHandles are auto-disposed when their origin frame gets navigated or the parent context gets destroyed.

JSHandle instances can be used as an argument in page.$eval(selector, pageFunction[, arg, options]), page.evaluate(pageFunction[, arg, options]) and page.evaluateHandle(pageFunction[, arg, options]) methods.

interface JSHandle<T = any> {
  /**
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-option-expression).
   *
   * This method passes this handle as the first argument to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-option-expression).
   *
   * If [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-option-expression)
   * returns a [Promise], then `handle.evaluate` would wait for the promise to resolve and return its value.
   *
   * **Usage**
   *
   * ```js
   * const tweetHandle = await page.$('.tweet .retweets');
   * expect(await tweetHandle.evaluate(node => node.innerText)).toBe('10 retweets');
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-option-expression).
   * @param options
   */
  evaluate<R, Arg, O extends T = T>(
    pageFunction: PageFunctionOn<O, Arg, R>,
    arg: Arg,
    options?: { exposeFunctions?: boolean },
  ): Promise<R>
  /**
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-option-expression).
   *
   * This method passes this handle as the first argument to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-option-expression).
   *
   * If [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-option-expression)
   * returns a [Promise], then `handle.evaluate` would wait for the promise to resolve and return its value.
   *
   * **Usage**
   *
   * ```js
   * const tweetHandle = await page.$('.tweet .retweets');
   * expect(await tweetHandle.evaluate(node => node.innerText)).toBe('10 retweets');
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-option-expression).
   * @param options
   */
  evaluate<R, O extends T = T>(
    pageFunction: PageFunctionOn<O, void, R>,
    arg?: any,
    options?: { exposeFunctions?: boolean },
  ): Promise<R>

  /**
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-handle-option-expression)
   * as a [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * This method passes this handle as the first argument to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-handle-option-expression).
   *
   * The only difference between `jsHandle.evaluate` and `jsHandle.evaluateHandle` is that `jsHandle.evaluateHandle`
   * returns [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * If the function passed to the `jsHandle.evaluateHandle` returns a [Promise], then `jsHandle.evaluateHandle` would
   * wait for the promise to resolve and return its value.
   *
   * See
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle)
   * for more details.
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-handle-option-expression).
   * @param options
   */
  evaluateHandle<R, Arg, O extends T = T>(
    pageFunction: PageFunctionOn<O, Arg, R>,
    arg: Arg,
    options?: { exposeFunctions?: boolean },
  ): Promise<SmartHandle<R>>
  /**
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-handle-option-expression)
   * as a [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * This method passes this handle as the first argument to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-handle-option-expression).
   *
   * The only difference between `jsHandle.evaluate` and `jsHandle.evaluateHandle` is that `jsHandle.evaluateHandle`
   * returns [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * If the function passed to the `jsHandle.evaluateHandle` returns a [Promise], then `jsHandle.evaluateHandle` would
   * wait for the promise to resolve and return its value.
   *
   * See
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle)
   * for more details.
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-evaluate-handle-option-expression).
   * @param options
   */
  evaluateHandle<R, O extends T = T>(
    pageFunction: PageFunctionOn<O, void, R>,
    arg?: any,
    options?: { exposeFunctions?: boolean },
  ): Promise<SmartHandle<R>>

  /**
   * Returns a JSON representation of the object. If the object has a `toJSON` function, it **will not be called**.
   *
   * **NOTE** The method will return an empty JSON object if the referenced object is not stringifiable. It will throw
   * an error if the object has circular references.
   *
   */
  jsonValue(): Promise<T>
  /**
   * Returns either `null` or the object handle itself, if the object handle is an instance of
   * [ElementHandle](https://playwright.dev/docs/api/class-elementhandle).
   */
  asElement(): T extends Node ? ElementHandle<T> : null
  /**
   * The `jsHandle.dispose` method stops referencing the element handle.
   */
  dispose(): Promise<void>

  /**
   * The method returns a map with **own property names** as keys and JSHandle instances for the property values.
   *
   * **Usage**
   *
   * ```js
   * const handle = await page.evaluateHandle(() => ({ window, document }));
   * const properties = await handle.getProperties();
   * const windowHandle = properties.get('window');
   * const documentHandle = properties.get('document');
   * await handle.dispose();
   * ```
   *
   */
  getProperties(): Promise<Map<string, JSHandle>>

  /**
   * Fetches a single property from the referenced object.
   * @param propertyName property to get
   */
  getProperty(propertyName: string): Promise<JSHandle>

  [Symbol.asyncDispose](): Promise<void>
}

APIResponse

APIResponse class represents responses returned by apiRequestContext.get(url[, options]) and similar methods.

interface APIResponse<T = any> {
  /**
   * Returns the JSON representation of response body.
   *
   * This method will throw if the response body is not parsable via `JSON.parse`.
   */
  json(): Promise<T>
  /**
   * Returns the buffer with response body.
   */
  body(): Promise<Buffer>

  /**
   * Disposes the body of this response. If not called then the body will stay in memory until the context closes.
   */
  dispose(): Promise<void>

  /**
   * An object with all the response HTTP headers associated with this response.
   */
  headers(): { [key: string]: string }

  /**
   * An array with all the response HTTP headers associated with this response. Header names are not lower-cased.
   * Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
   */
  headersArray(): Array<{
    /**
     * Name of the header.
     */
    name: string

    /**
     * Value of the header.
     */
    value: string
  }>

  /**
   * Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
   */
  ok(): boolean

  /**
   * Returns SSL and other security information. Resolves to `null` for non-HTTPS responses. For redirected requests,
   * returns the information for the last request in the redirect chain.
   */
  securityDetails(): Promise<null | {
    /**
     * Common Name component of the Issuer field. from the certificate. This should only be used for informational
     * purposes. Optional.
     */
    issuer?: string

    /**
     * The specific TLS protocol used. (e.g. `TLS 1.3`). Optional.
     */
    protocol?: string

    /**
     * Common Name component of the Subject field from the certificate. This should only be used for informational
     * purposes. Optional.
     */
    subjectName?: string

    /**
     * Unix timestamp (in seconds) specifying when this cert becomes valid. Optional.
     */
    validFrom?: number

    /**
     * Unix timestamp (in seconds) specifying when this cert becomes invalid. Optional.
     */
    validTo?: number
  }>

  /**
   * Returns the IP address and port of the server. Resolves to `null` if the server address is not available. For
   * redirected requests, returns the information for the last request in the redirect chain.
   */
  serverAddr(): Promise<null | {
    /**
     * IPv4 or IPV6 address of the server.
     */
    ipAddress: string

    port: number
  }>

  /**
   * Contains the status code of the response (e.g., 200 for a success).
   */
  status(): number

  /**
   * Contains the status text of the response (e.g. usually an "OK" for a success).
   */
  statusText(): string

  /**
   * Returns the text representation of response body.
   */
  text(): Promise<string>

  /**
   * Returns resource timing information for given response. For redirected requests, returns the information for the
   * last request in the redirect chain. When the response is served [from the HAR file](https://playwright.dev/docs/mock#replaying-from-har),
   * timing information is not available and all the values are -1. Find more information at
   * [Resource Timing API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming).
   */
  timing(): {
    /**
     * Request start time in milliseconds elapsed since January 1, 1970 00:00:00 UTC
     */
    startTime: number

    /**
     * Time immediately before the client starts the domain name lookup for the resource. The value is given in
     * milliseconds relative to `startTime`, -1 if not available.
     */
    domainLookupStart: number

    /**
     * Time immediately after the client ends the domain name lookup for the resource. The value is given in milliseconds
     * relative to `startTime`, -1 if not available.
     */
    domainLookupEnd: number

    /**
     * Time immediately before the client starts establishing the connection to the server to retrieve the resource. The
     * value is given in milliseconds relative to `startTime`, -1 if not available.
     */
    connectStart: number

    /**
     * Time immediately before the client starts the handshake process to secure the current connection. The value is
     * given in milliseconds relative to `startTime`, -1 if not available.
     */
    secureConnectionStart: number

    /**
     * Time immediately after the client establishes the connection to the server to retrieve the resource. The value is
     * given in milliseconds relative to `startTime`, -1 if not available.
     */
    connectEnd: number

    /**
     * Time immediately before the client starts requesting the resource from the server, cache, or local resource. The
     * value is given in milliseconds relative to `startTime`, -1 if not available.
     */
    requestStart: number

    /**
     * Time immediately after the client receives the first byte of the response from the server, cache, or local
     * resource. The value is given in milliseconds relative to `startTime`, -1 if not available.
     */
    responseStart: number

    /**
     * Time immediately after the client receives the last byte of the resource or immediately before the transport
     * connection is closed, whichever comes first. The value is given in milliseconds relative to `startTime`, -1 if not
     * available.
     */
    responseEnd: number
  }

  /**
   * Contains the URL of the response.
   */
  url(): string

  [Symbol.asyncDispose](): Promise<void>
}

ElementHandle

ElementHandle represents an in-page DOM element. ElementHandles can be created with the page.$(selector[, options]) method.

NOTE The use of ElementHandle is discouraged, use Locator objects and web-first assertions instead.

const hrefElement = await page.$('a')
await hrefElement.click()

ElementHandle prevents DOM element from garbage collection unless the handle is disposed with jsHandle.dispose(). ElementHandles are auto-disposed when their origin frame gets navigated.

ElementHandle instances can be used as an argument in page.$eval(selector, pageFunction[, arg, options]) and page.evaluate(pageFunction[, arg, options]) methods.

The difference between the Locator and ElementHandle is that the ElementHandle points to a particular element, while Locator captures the logic of how to retrieve an element.

In the example below, handle points to a particular DOM element on page. If that element changes text or is used by

(description truncated — read the full text in node_modules/playwright-core/types/types.d.ts.)

interface ElementHandle<T=Node> extends JSHandle<T> {
  /**
   * **NOTE** Use locator-based [page.locator(selector[, options])](https://playwright.dev/docs/api/class-page#page-locator)
   * instead. Read more about [locators](https://playwright.dev/docs/locators).
   *
   * The method finds an element matching the specified selector in the `ElementHandle`'s subtree. If no elements match
   * the selector, returns `null`.
   * @param selector A selector to query for.
   */
  $<K extends keyof HTMLElementTagNameMap>(selector: K, options?: { strict: boolean }): Promise<ElementHandleForTag<K> | null>;
  /**
   * **NOTE** Use locator-based [page.locator(selector[, options])](https://playwright.dev/docs/api/class-page#page-locator)
   * instead. Read more about [locators](https://playwright.dev/docs/locators).
   *
   * The method finds an element matching the specified selector in the `ElementHandle`'s subtree. If no elements match
   * the selector, returns `null`.
   * @param selector A selector to query for.
   */
  $(selector: string, options?: { strict: boolean }): Promise<ElementHandle<SVGElement | HTMLElement> | null>;

  /**
   * **NOTE** Use locator-based [page.locator(selector[, options])](https://playwright.dev/docs/api/class-page#page-locator)
   * instead. Read more about [locators](https://playwright.dev/docs/locators).
   *
   * The method finds all elements matching the specified selector in the `ElementHandle`s subtree. If no elements match
   * the selector, returns empty array.
   * @param selector A selector to query for.
   */
  $$<K extends keyof HTMLElementTagNameMap>(selector: K): Promise<ElementHandleForTag<K>[]>;
  /**
   * **NOTE** Use locator-based [page.locator(selector[, options])](https://playwright.dev/docs/api/class-page#page-locator)
   * instead. Read more about [locators](https://playwright.dev/docs/locators).
   *
   * The method finds all elements matching the specified selector in the `ElementHandle`s subtree. If no elements match
   * the selector, returns empty array.
   * @param selector A selector to query for.
   */
  $$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement>[]>;

  /**
   * **NOTE** This method does not wait for the element to pass actionability checks and therefore can lead to the flaky tests.
   * Use
   * [locator.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate),
   * other [Locator](https://playwright.dev/docs/api/class-locator) helper methods or web-first assertions instead.
   *
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression).
   *
   * The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a
   * first argument to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression).
   * If no elements match the selector, the method throws an error.
   *
   * If
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression)
   * returns a [Promise], then
   * [elementHandle.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector)
   * would wait for the promise to resolve and return its value.
   *
   * **Usage**
   *
   * ```js
   * const tweetHandle = await page.$('.tweet');
   * expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100');
   * expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10');
   * ```
   *
   * @param selector A selector to query for.
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression).
   */
  $eval<K extends keyof HTMLElementTagNameMap, R, Arg>(selector: K, pageFunction: PageFunctionOn<HTMLElementTagNameMap[K], Arg, R>, arg: Arg): Promise<R>;
  /**
   * **NOTE** This method does not wait for the element to pass actionability checks and therefore can lead to the flaky tests.
   * Use
   * [locator.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate),
   * other [Locator](https://playwright.dev/docs/api/class-locator) helper methods or web-first assertions instead.
   *
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression).
   *
   * The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a
   * first argument to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression).
   * If no elements match the selector, the method throws an error.
   *
   * If
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression)
   * returns a [Promise], then
   * [elementHandle.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector)
   * would wait for the promise to resolve and return its value.
   *
   * **Usage**
   *
   * ```js
   * const tweetHandle = await page.$('.tweet');
   * expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100');
   * expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10');
   * ```
   *
   * @param selector A selector to query for.
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression).
   */
  $eval<R, Arg, E extends SVGElement | HTMLElement = SVGElement | HTMLElement>(selector: string, pageFunction: PageFunctionOn<E, Arg, R>, arg: Arg): Promise<R>;
  /**
   * **NOTE** This method does not wait for the element to pass actionability checks and therefore can lead to the flaky tests.
   * Use
   * [locator.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate),
   * other [Locator](https://playwright.dev/docs/api/class-locator) helper methods or web-first assertions instead.
   *
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression).
   *
   * The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a
   * first argument to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression).
   * If no elements match the selector, the method throws an error.
   *
   * If
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression)
   * returns a [Promise], then
   * [elementHandle.$eval(selector, pageFunction[, arg])](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector)
   * would wait for the promise to resolve and return its value.
   *
   * **Usage**
   *
   * ```js
   * const tweetHandle = await page.$('.tweet');
   * expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100');
   * expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10');
   * ```
   *
   * @param selector A selector to query for.
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-elementhandle#element-handle-eval-on-selector-option-expression).
   */
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

Locator

Locators are the central piece of Playwright's auto-waiting and retry-ability. In a nutshell, locators represent a way to find element(s) on the page at any moment. A locator can be created with the page.locator(selector[, options]) method.

Learn more about locators.

interface Locator {
  /**
   * Execute JavaScript code in the page, taking the matching element as an argument.
   *
   * **Details**
   *
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-option-expression), called with the
   * matching element as a first argument, and
   * [`arg`](https://playwright.dev/docs/api/class-locator#locator-evaluate-option-arg) as a second argument.
   *
   * If [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-option-expression) returns a
   * [Promise], this method will wait for the promise to resolve and return its value.
   *
   * If [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-option-expression) throws or
   * rejects, this method throws.
   *
   * **Usage**
   *
   * Passing argument to
   * [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-option-expression):
   *
   * ```js
   * const result = await page.getByTestId('myId').evaluate((element, [x, y]) => {
   *   return element.textContent + ' ' + x * y;
   * }, [7, 8]);
   * console.log(result); // prints "myId text 56"
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-option-expression).
   * @param options
   */
  evaluate<R, Arg, E extends SVGElement | HTMLElement = SVGElement | HTMLElement>(pageFunction: PageFunctionOn<E, Arg, R>, arg?: Arg, options?: { timeout?: number, signal?: AbortSignal, exposeFunctions?: boolean }): Promise<R>;
  /**
   * Execute JavaScript code in the page, taking the matching element as an argument, and return a
   * [JSHandle](https://playwright.dev/docs/api/class-jshandle) with the result.
   *
   * **Details**
   *
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle-option-expression) as
   * a[JSHandle](https://playwright.dev/docs/api/class-jshandle), called with the matching element as a first argument,
   * and [`arg`](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle-option-arg) as a second argument.
   *
   * The only difference between
   * [locator.evaluate(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate)
   * and
   * [locator.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle)
   * is that
   * [locator.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle)
   * returns [JSHandle](https://playwright.dev/docs/api/class-jshandle).
   *
   * If [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle-option-expression)
   * returns a [Promise], this method will wait for the promise to resolve and return its value.
   *
   * If [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle-option-expression) throws
   * or rejects, this method throws.
   *
   * See
   * [page.evaluateHandle(pageFunction[, arg, options])](https://playwright.dev/docs/api/class-page#page-evaluate-handle)
   * for more details.
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-handle-option-expression).
   * @param options
   */
  evaluateHandle<R, Arg, E extends SVGElement | HTMLElement = SVGElement | HTMLElement>(pageFunction: PageFunctionOn<E, Arg, R>, arg?: Arg, options?: { timeout?: number, signal?: AbortSignal, exposeFunctions?: boolean }): Promise<SmartHandle<R>>;
  /**
   * Execute JavaScript code in the page, taking all matching elements as an argument.
   *
   * **Details**
   *
   * Returns the return value of
   * [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-all-option-expression), called with
   * an array of all matching elements as a first argument, and
   * [`arg`](https://playwright.dev/docs/api/class-locator#locator-evaluate-all-option-arg) as a second argument.
   *
   * If [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-all-option-expression) returns a
   * [Promise], this method will wait for the promise to resolve and return its value.
   *
   * If [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-all-option-expression) throws or
   * rejects, this method throws.
   *
   * **Usage**
   *
   * ```js
   * const locator = page.locator('div');
   * const moreThanTen = await locator.evaluateAll((divs, min) => divs.length > min, 10);
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-evaluate-all-option-expression).
   */
  evaluateAll<R, Arg, E extends SVGElement | HTMLElement = SVGElement | HTMLElement>(pageFunction: PageFunctionOn<E[], Arg, R>, arg?: Arg): Promise<R>;
  /**
   * Returns when
   * [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-wait-for-function-option-expression) returns
   * a truthy value, called with the matching element as a first argument, and
   * [`arg`](https://playwright.dev/docs/api/class-locator#locator-wait-for-function-option-arg) as a second argument.
   *
   * This is a generic way to wait for an element to reach a custom condition without asserting it. The locator is
   * re-resolved on each retry, so it tolerates the element being re-rendered while waiting.
   *
   * If [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-wait-for-function-option-expression)
   * returns a [Promise], this method will wait for the promise to resolve before checking its value.
   *
   * If [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-wait-for-function-option-expression)
   * throws or rejects, this method throws.
   *
   * **Usage**
   *
   * Wait for an attribute to appear:
   *
   * ```js
   * const toggle = page.getByRole('button', { name: 'Menu' });
   * await toggle.click();
   * await toggle.waitForFunction(element => element.hasAttribute('aria-expanded'));
   * ```
   *
   * Passing argument to
   * [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-wait-for-function-option-expression):
   *
   * ```js
   * await page.getByTestId('status').waitForFunction((element, value) => {
   *   return element.textContent === value;
   * }, 'Ready');
   * ```
   *
   * @param pageFunction Function to be evaluated in the page context.
   * @param arg Optional argument to pass to
   * [`pageFunction`](https://playwright.dev/docs/api/class-locator#locator-wait-for-function-option-expression).
   * @param options
   */
  waitForFunction<Arg, E extends SVGElement | HTMLElement = SVGElement | HTMLElement>(pageFunction: PageFunctionOn<E, Arg, any>, arg?: Arg, options?: { timeout?: number, signal?: AbortSignal }): Promise<void>;
  /**
   * **NOTE** Always prefer using [Locator](https://playwright.dev/docs/api/class-locator)s and web assertions over
   * [ElementHandle](https://playwright.dev/docs/api/class-elementhandle)s because latter are inherently racy.
   *
   * Resolves given locator to the first matching DOM element. If there are no matching elements, waits for one. If
   * multiple elements match the locator, throws.
   * @param options
   */
  elementHandle(options?: { timeout?: number }): Promise<ElementHandle<SVGElement | HTMLElement>>;
  /**
   * Highlight the corresponding element(s) on the screen. Useful for debugging, don't commit the code that uses
   * [locator.highlight([options])](https://playwright.dev/docs/api/class-locator#locator-highlight).
   * @param options
   */
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

BrowserType

BrowserType provides methods to launch a specific browser instance or connect to an existing one. The following is a typical example of using Playwright to drive automation:

const { chromium } = require('playwright') // Or 'firefox' or 'webkit'.

;(async () => {
  const browser = await chromium.launch()
  const page = await browser.newPage()
  await page.goto('https://example.com')
  // other actions...
  await browser.close()
})()
interface BrowserType<Unused = {}> {
  /**
   * This method attaches Playwright to an existing browser instance using the Chrome DevTools Protocol.
   *
   * The default browser context is accessible via
   * [browser.contexts()](https://playwright.dev/docs/api/class-browser#browser-contexts).
   *
   * **NOTE** Connecting over the Chrome DevTools Protocol is only supported for Chromium-based browsers.
   *
   * **NOTE** This connection is significantly lower fidelity than the Playwright protocol connection via
   * [browserType.connect(endpoint[, options])](https://playwright.dev/docs/api/class-browsertype#browser-type-connect).
   * If you are experiencing issues or attempting to use advanced functionality, you probably want to use
   * [browserType.connect(endpoint[, options])](https://playwright.dev/docs/api/class-browsertype#browser-type-connect).
   *
   * **NOTE** Playwright maintains a curated list of arguments for launching the browser. If you launch the browser
   * without Playwright and do not pass the exact same arguments, some of Playwright functionality may be broken upon
   * connecting to the browser.
   *
   * **Usage**
   *
   * ```js
   * const browser = await playwright.chromium.connectOverCDP('http://localhost:9222');
   * const defaultContext = browser.contexts()[0];
   * const page = defaultContext.pages()[0];
   * ```
   *
   * @param endpointURL A CDP websocket endpoint or http url to connect to. For example `http://localhost:9222/` or
   * `ws://127.0.0.1:9222/devtools/browser/387adf4c-243f-4051-a181-46798f4a46f4`.
   * @param options
   */
  connectOverCDP(endpointURL: string, options?: ConnectOverCDPOptions): Promise<Browser>;
  /**
   * This method attaches Playwright to an existing browser instance using the Chrome DevTools Protocol.
   *
   * The default browser context is accessible via
   * [browser.contexts()](https://playwright.dev/docs/api/class-browser#browser-contexts).
   *
   * **NOTE** Connecting over the Chrome DevTools Protocol is only supported for Chromium-based browsers.
   *
   * **NOTE** This connection is significantly lower fidelity than the Playwright protocol connection via
   * [browserType.connect(endpoint[, options])](https://playwright.dev/docs/api/class-browsertype#browser-type-connect).
   * If you are experiencing issues or attempting to use advanced functionality, you probably want to use
   * [browserType.connect(endpoint[, options])](https://playwright.dev/docs/api/class-browsertype#browser-type-connect).
   *
   * **NOTE** Playwright maintains a curated list of arguments for launching the browser. If you launch the browser
   * without Playwright and do not pass the exact same arguments, some of Playwright functionality may be broken upon
   * connecting to the browser.
   *
   * **Usage**
   *
   * ```js
   * const browser = await playwright.chromium.connectOverCDP('http://localhost:9222');
   * const defaultContext = browser.contexts()[0];
   * const page = defaultContext.pages()[0];
   * ```
   *
   * @param endpointURL A CDP websocket endpoint or http url to connect to. For example `http://localhost:9222/` or
   * `ws://127.0.0.1:9222/devtools/browser/387adf4c-243f-4051-a181-46798f4a46f4`.
   * @param options
   */
  connectOverCDP(transport: ConnectOverCDPTransport, options?: ConnectOverCDPOptions): Promise<Browser>;
  /**
   * Option `wsEndpoint` is deprecated. Instead use `endpointURL`.
   * @deprecated
   */
  /**
   * This method attaches Playwright to an existing browser instance using the Chrome DevTools Protocol.
   *
   * The default browser context is accessible via
   * [browser.contexts()](https://playwright.dev/docs/api/class-browser#browser-contexts).
   *
   * **NOTE** Connecting over the Chrome DevTools Protocol is only supported for Chromium-based browsers.
   *
   * **NOTE** This connection is significantly lower fidelity than the Playwright protocol connection via
   * [browserType.connect(endpoint[, options])](https://playwright.dev/docs/api/class-browsertype#browser-type-connect).
   * If you are experiencing issues or attempting to use advanced functionality, you probably want to use
   * [browserType.connect(endpoint[, options])](https://playwright.dev/docs/api/class-browsertype#browser-type-connect).
   *
   * **NOTE** Playwright maintains a curated list of arguments for launching the browser. If you launch the browser
   * without Playwright and do not pass the exact same arguments, some of Playwright functionality may be broken upon
   * connecting to the browser.
   *
   * **Usage**
   *
   * ```js
   * const browser = await playwright.chromium.connectOverCDP('http://localhost:9222');
   * const defaultContext = browser.contexts()[0];
   * const page = defaultContext.pages()[0];
   * ```
   *
   * @param endpointURL A CDP websocket endpoint or http url to connect to. For example `http://localhost:9222/` or
   * `ws://127.0.0.1:9222/devtools/browser/387adf4c-243f-4051-a181-46798f4a46f4`.
   * @param options
   */
  connectOverCDP(options: ConnectOverCDPOptions & { wsEndpoint?: string }): Promise<Browser>;

  /**
   * This method attaches Playwright to an existing browser instance created via `BrowserType.launchServer` in Node.js.
   *
   * **NOTE** The major and minor version of the Playwright instance that connects needs to match the version of
   * Playwright that launches the browser (1.2.3 → is compatible with 1.2.x).
   *
   * @param endpoint A Playwright browser websocket endpoint to connect to. You obtain this endpoint via `BrowserServer.wsEndpoint`.
   * @param options
   */
  connect(wsEndpoint: string, options?: ConnectOptions): Promise<Browser>;
  /**
   * wsEndpoint in options is deprecated. Instead use `wsEndpoint`.
   * @param wsEndpoint A browser websocket endpoint to connect to.
   * @param options
   * @deprecated
   */
  /**
   * This method attaches Playwright to an existing browser instance created via `BrowserType.launchServer` in Node.js.
   *
   * **NOTE** The major and minor version of the Playwright instance that connects needs to match the version of
   * Playwright that launches the browser (1.2.3 → is compatible with 1.2.x).
   *
   * @param endpoint A Playwright browser websocket endpoint to connect to. You obtain this endpoint via `BrowserServer.wsEndpoint`.
   * @param options
   */
  connect(options: ConnectOptions & { wsEndpoint?: string }): Promise<Browser>;
  /**
   * A path where Playwright expects to find a bundled browser executable.
   */
  executablePath(): string;

  /**
   * Returns the browser instance.
   *
   * **Usage**
   *
   * You can use
   * [`ignoreDefaultArgs`](https://playwright.dev/docs/api/class-browsertype#browser-type-launch-option-ignore-default-args)
   * to filter out `--mute-audio` from default arguments:
   *
   * ```js
   * const browser = await chromium.launch({  // Or 'firefox' or 'webkit'.
   *   ignoreDefaultArgs: ['--mute-audio']
   * });
   * ```
   *
   * > **Chromium-only** Playwright can also be used to control the Google Chrome or Microsoft Edge browsers, but it
   * works best with the version of Chromium it is bundled with. There is no guarantee it will work with any other
   * version. Use
   * [`executablePath`](https://playwright.dev/docs/api/class-browsertype#browser-type-launch-option-executable-path)
   * option with extreme caution.
   * >
   * > If Google Chrome (rather than Chromium) is preferred, a
   * [Chrome Canary](https://www.google.com/chrome/browser/canary.html) or
   * [Dev Channel](https://www.chromium.org/getting-involved/dev-channel) build is suggested.
   * >
   * > Stock browsers like Google Chrome and Microsoft Edge are suitable for tests that require proprietary media codecs
   * for video playback. See
   * [this article](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for
   * other differences between Chromium and Chrome.
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

APIRequestContext

This API is used for the Web API testing. You can use it to trigger API endpoints, configure micro-services, prepare environment or the service to your e2e test.

Each Playwright browser context has an associated APIRequestContext, accessible via browserContext.request or page.request (these return the

same instance — page.request is a shortcut for page.context().request). You can also create a standalone, isolated instance with apiRequest.newContext([options]).

Cookie management

The APIRequestContext returned by browserContext.request and

page.request uses the same cookie jar as its BrowserContext:

If you want API requests that do not share cookies with the browser, create an isolated context via apiRequest.newContext([options]). Such APIRequestContext object will have its own isolated cookie storage.

interface APIRequestContext {
  /**
   * Sends HTTP(S) [DELETE](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) request and returns its
   * response. The method will populate request cookies from the context and update context cookies from the response.
   * The method will automatically follow redirects.
   * @param url Target URL.
   * @param options
   */
  delete<T = any>(url: string, options?: {
    /**
     * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
     * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
     * header will be set to `application/octet-stream` if not explicitly set.
     */
    data?: string|Buffer|Serializable;

    /**
     * Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
     * codes.
     */
    failOnStatusCode?: boolean;

    /**
     * Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
     * as this request body. If this parameter is specified `content-type` header will be set to
     * `application/x-www-form-urlencoded` unless explicitly provided.
     */
    form?: { [key: string]: string|number|boolean; }|FormData;

    /**
     * Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
     * it.
     */
    headers?: { [key: string]: string; };

    /**
     * Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
     */
    ignoreHTTPSErrors?: boolean;

    /**
     * Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
     * exceeded. Defaults to `20`. Pass `0` to not follow redirects.
     */
    maxRedirects?: number;

    /**
     * Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
     * retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
     */
    maxRetries?: number;

    /**
     * Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as this
     * request body. If this parameter is specified `content-type` header will be set to `multipart/form-data` unless
     * explicitly provided. File values can be passed either as
     * [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream) or as file-like object containing file
     * name, mime-type and its content.
     */
    multipart?: FormData|{ [key: string]: string|number|boolean|ReadStream|{
      /**
       * File name
       */
      name: string;

      /**
       * File type
       */
      mimeType: string;

      /**
       * File content
       */
      buffer: Buffer;
    }; };

    /**
     * Query parameters to be sent with the URL.
     */
    params?: { [key: string]: string|number|boolean; }|URLSearchParams|string;

    /**
     * Allows to cancel the operation using an
     * [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal). If the signal is aborted, the
     * operation will be aborted and throw an error. Note that providing a signal does not disable the default timeout,
     * which can be changed using
     * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout)
     * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout); pass
     * `timeout: 0` to disable the timeout entirely.
     */
    signal?: AbortSignal;

    /**
     * Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout.
     */
    timeout?: number;
  }): Promise<APIResponse<T>>;

  /**
   * All responses returned by
   * [apiRequestContext.get(url[, options])](https://playwright.dev/docs/api/class-apirequestcontext#api-request-context-get)
   * and similar methods are stored in the memory, so that you can later call
   * [apiResponse.body()](https://playwright.dev/docs/api/class-apiresponse#api-response-body).This method discards all
   * its resources, calling any method on disposed
   * [APIRequestContext](https://playwright.dev/docs/api/class-apirequestcontext) will throw an exception.
   * @param options
   */
  dispose(options?: {
    /**
     * The reason to be reported to the operations interrupted by the context disposal.
     */
    reason?: string;
  }): Promise<void>;

  /**
   * Sends HTTP(S) request and returns its response. The method will populate request cookies from the context and
   * update context cookies from the response. The method will automatically follow redirects.
   *
   * **Usage**
   *
   * JSON objects can be passed directly to the request:
   *
   * ```js
   * await request.fetch('https://example.com/api/createBook', {
   *   method: 'post',
   *   data: {
   *     title: 'Book Title',
   *     author: 'John Doe',
   *   }
   * });
   * ```
   *
   * The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data`
   * encoding, by specifiying the `multipart` parameter:
   *
   * ```js
   * const form = new FormData();
   * form.set('name', 'John');
   * form.append('name', 'Doe');
   * // Send two file fields with the same name.
   * form.append('file', new File(['console.log(2024);'], 'f1.js', { type: 'text/javascript' }));
   * form.append('file', new File(['hello'], 'f2.txt', { type: 'text/plain' }));
   * await request.fetch('https://example.com/api/uploadForm', {
   *   multipart: form
   * });
   * ```
   *
   * @param urlOrRequest Target URL or Request to get all parameters from.
   * @param options
   */
  fetch<T = any>(urlOrRequest: string|Request, options?: {
    /**
     * Allows to set post data of the request. If the data parameter is an object, it will be serialized to json string
     * and `content-type` header will be set to `application/json` if not explicitly set. Otherwise the `content-type`
     * header will be set to `application/octet-stream` if not explicitly set.
     */
    data?: string|Buffer|Serializable;

    /**
     * Whether to throw on response codes other than 2xx and 3xx. By default response object is returned for all status
     * codes.
     */
    failOnStatusCode?: boolean;

    /**
     * Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent
     * as this request body. If this parameter is specified `content-type` header will be set to
     * `application/x-www-form-urlencoded` unless explicitly provided.
     */
    form?: { [key: string]: string|number|boolean; }|FormData;

    /**
     * Allows to set HTTP headers. These headers will apply to the fetched request as well as any redirects initiated by
     * it.
     */
    headers?: { [key: string]: string; };

    /**
     * Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
     */
    ignoreHTTPSErrors?: boolean;

    /**
     * Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is
     * exceeded. Defaults to `20`. Pass `0` to not follow redirects.
     */
    maxRedirects?: number;

    /**
     * Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not
     * retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
     */
    maxRetries?: number;

    /**
     * If set changes the fetch method (e.g. [PUT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) or
     * [POST](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)). If not specified, GET method is used.
     */
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

ConsoleMessage

ConsoleMessage objects are dispatched by page via the page.on('console') event. For each console message logged in the page there will be corresponding event in the Playwright context.

// Listen for all console logs
page.on('console', (msg) => console.log(msg.text()))

// Listen for all console events and handle errors
page.on('console', (msg) => {
  if (msg.type() === 'error') console.log(`Error text: "${msg.text()}"`)
})

// Get the next console log
const msgPromise = page.waitForEvent('console')
await page.evaluate(() => {
  console.log('hello', 42, { foo: 'bar' }) // Issue console.log inside the page
})
const msg = await msgPromise

// Deconstruct console log arguments
await msg.args()[0].jsonValue() // hello
await msg.args()[1].jsonValue() // 42
interface ConsoleMessage {
  /**
   * List of arguments passed to a `console` function call. See also
   * [page.on('console')](https://playwright.dev/docs/api/class-page#page-event-console).
   */
  args(): Array<JSHandle>

  location(): {
    /**
     * URL of the resource.
     */
    url: string

    /**
     * 0-based line number in the resource.
     */
    line: number

    /**
     * 0-based column number in the resource.
     */
    column: number

    /**
     * 0-based line number in the resource. Deprecated, use `line` instead.
     */
    lineNumber: number

    /**
     * 0-based column number in the resource. Deprecated, use `column` instead.
     */
    columnNumber: number
  }

  /**
   * The page that produced this console message, if any.
   */
  page(): null | Page

  /**
   * The text of the console message.
   */
  text(): string

  /**
   * The timestamp of the console message in milliseconds since the Unix epoch.
   */
  timestamp(): number

  type():
    | 'log'
    | 'debug'
    | 'info'
    | 'error'
    | 'warning'
    | 'dir'
    | 'dirxml'
    | 'table'
    | 'trace'
    | 'clear'
    | 'startGroup'
    | 'startGroupCollapsed'
    | 'endGroup'
    | 'assert'
    | 'profile'
    | 'profileEnd'
    | 'count'
    | 'time'
    | 'timeEnd'

  /**
   * The web worker or service worker that produced this console message, if any. Note that console messages from web
   * workers also have non-null
   * [consoleMessage.page()](https://playwright.dev/docs/api/class-consolemessage#console-message-page).
   */
  worker(): null | Worker
}

Dialog

Dialog objects are dispatched by page via the page.on('dialog') event.

An example of using Dialog class:

const { chromium } = require('playwright') // Or 'firefox' or 'webkit'.

;(async () => {
  const browser = await chromium.launch()
  const page = await browser.newPage()
  page.on('dialog', async (dialog) => {
    console.log(dialog.message())
    await dialog.dismiss()
  })
  await page.evaluate(() => alert('1'))
  await browser.close()
})()

NOTE Dialogs are dismissed automatically, unless there is a page.on('dialog') listener. When listener is present, it must either dialog.accept([promptText]) or dialog.dismiss() the dialog - otherwise the page will freeze waiting for the dialog, and actions like click will never finish.

interface Dialog {
  /**
   * Returns when the dialog has been accepted.
   * @param promptText A text to enter in prompt. Does not cause any effects if the dialog's `type` is not prompt. Optional.
   */
  accept(promptText?: string): Promise<void>

  /**
   * If dialog is prompt, returns default prompt value. Otherwise, returns empty string.
   */
  defaultValue(): string

  /**
   * Returns when the dialog has been dismissed.
   */
  dismiss(): Promise<void>

  /**
   * A message displayed in the dialog.
   */
  message(): string

  /**
   * The page that initiated this dialog, if available.
   */
  page(): null | Page

  /**
   * Returns dialog's type, can be one of `alert`, `beforeunload`, `confirm` or `prompt`.
   */
  type(): string
}

Download

Download objects are dispatched by page via the page.on('download') event.

All the downloaded files belonging to the browser context are deleted when the browser context is closed.

Download event is emitted once the download starts. Download path becomes available once download completes.

// Start waiting for download before clicking. Note no await.
const downloadPromise = page.waitForEvent('download')
await page.getByText('Download file').click()
const download = await downloadPromise

// Wait for the download process to complete and save the downloaded file somewhere.
await download.saveAs('/path/to/save/at/' + download.suggestedFilename())
interface Download {
  /**
   * Cancels a download. Will not fail if the download is already finished or canceled. Upon successful cancellations,
   * `download.failure()` would resolve to `'canceled'`.
   */
  cancel(): Promise<void>

  /**
   * Returns a readable stream for a successful download, or throws for a failed/canceled download.
   *
   * **NOTE** If you don't need a readable stream, it's usually simpler to read the file from disk after the download
   * completed. See [download.path()](https://playwright.dev/docs/api/class-download#download-path).
   *
   */
  createReadStream(): Promise<Readable>

  /**
   * Deletes the downloaded file. Will wait for the download to finish if necessary.
   */
  delete(): Promise<void>

  /**
   * Returns download error if any. Will wait for the download to finish if necessary.
   */
  failure(): Promise<null | string>

  /**
   * Get the page that the download belongs to.
   */
  page(): Page

  /**
   * Returns path to the downloaded file for a successful download, or throws for a failed/canceled download. The method
   * will wait for the download to finish if necessary. The method throws when connected remotely.
   *
   * Note that the download's file name is a random GUID, use
   * [download.suggestedFilename()](https://playwright.dev/docs/api/class-download#download-suggested-filename) to get
   * suggested file name.
   */
  path(): Promise<string>

  /**
   * Copy the download to a user-specified path. It is safe to call this method while the download is still in progress.
   * Will wait for the download to finish if necessary.
   *
   * **Usage**
   *
   * ```js
   * await download.saveAs('/path/to/save/at/' + download.suggestedFilename());
   * ```
   *
   * @param path Path where the download should be copied.
   */
  saveAs(path: string): Promise<void>

  /**
   * Returns suggested filename for this download. It is typically computed by the browser from the
   * [`Content-Disposition`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition) response
   * header or the `download` attribute. See the spec on [whatwg](https://html.spec.whatwg.org/#downloading-resources).
   * Different browsers can use different logic for computing it.
   */
  suggestedFilename(): string

  /**
   * Returns downloaded url.
   */
  url(): string
}

FileChooser

FileChooser objects are dispatched by the page in the page.on('filechooser') event.

// Start waiting for file chooser before clicking. Note no await.
const fileChooserPromise = page.waitForEvent('filechooser')
await page.getByText('Upload file').click()
const fileChooser = await fileChooserPromise
await fileChooser.setFiles(path.join(__dirname, 'myfile.pdf'))
interface FileChooser {
  /**
   * Returns input element associated with this file chooser.
   */
  element(): ElementHandle

  /**
   * Returns whether this file chooser accepts multiple files.
   */
  isMultiple(): boolean

  /**
   * Returns page this file chooser belongs to.
   */
  page(): Page

  /**
   * Sets the value of the file input this chooser is associated with. If some of the `filePaths` are relative paths,
   * then they are resolved relative to the current working directory. For empty array, clears the selected files.
   * @param files
   * @param options
   */
  setFiles(
    files:
      | string
      | ReadonlyArray<string>
      | {
          /**
           * File name
           */
          name: string

          /**
           * File type
           */
          mimeType: string

          /**
           * File content
           */
          buffer: Buffer
        }
      | ReadonlyArray<{
          /**
           * File name
           */
          name: string

          /**
           * File type
           */
          mimeType: string

          /**
           * File content
           */
          buffer: Buffer
        }>,
    options?: {
      /**
       * This option has no effect.
       * @deprecated This option has no effect.
       */
      noWaitAfter?: boolean

      /**
       * Allows to cancel the operation using an
       * [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal). If the signal is aborted, the
       * operation will be aborted and throw an error. Note that providing a signal does not disable the default timeout,
       * which can be changed using
       * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout)
       * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout); pass
       * `timeout: 0` to disable the timeout entirely.
       */
      signal?: AbortSignal

      /**
       * Maximum time in milliseconds. Defaults to `0` - no timeout. The default value can be changed via `actionTimeout`
       * option in the config, or by using the
       * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout)
       * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods.
       */
      timeout?: number
    },
  ): Promise<void>
}

FrameLocator

FrameLocator represents a view to the iframe on the page. It captures the logic sufficient to retrieve the iframe and locate elements in that iframe. FrameLocator can be created with either locator.contentFrame(), page.frameLocator([selector]) or locator.frameLocator(selector) method.

const locator = page.locator('#my-frame').contentFrame().getByText('Submit')
await locator.click()

Strictness

Frame locators are strict. This means that all operations on frame locators will throw if more than one element matches a given selector.

// Throws if there are several frames in DOM:
await page.locator('.result-frame').contentFrame().getByRole('button').click()

// Works because we explicitly tell locator to pick the first frame:
await page.locator('.result-frame').contentFrame().first().getByRole('button').click()

Any frame

Calling page.frameLocator([selector]) or frame.frameLocator([selector]) without a selector creates a frame locator that starts the search in any frame of the subtree - so that you don't need to locate the iframe first.

// Finds the button in any frame on the page:

*(description truncated — read the full text in `node_modules/playwright-core/types/types.d.ts`.)*

```typescript
interface FrameLocator {
  /**
   * Returns locator to the first matching frame.
   * @deprecated Use [locator.first()](https://playwright.dev/docs/api/class-locator#locator-first) followed by
   * [locator.contentFrame()](https://playwright.dev/docs/api/class-locator#locator-content-frame) instead.
   */
  first(): FrameLocator;

  /**
   * When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
   * in that iframe.
   * @param selector A selector to use when resolving DOM element.
   */
  frameLocator(selector: string): FrameLocator;

  /**
   * Allows locating elements by their alt text.
   *
   * **Usage**
   *
   * For example, this method will find the image by alt text "Playwright logo":
   *
   * ```html
   * <img alt='Playwright logo'>
   * ```
   *
   * ```js
   * await page.getByAltText('Playwright logo').click();
   * ```
   *
   * @param text Text to locate the element for.
   * @param options
   */
  getByAltText(text: string|RegExp, options?: {
    /**
     * Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
     * regular expression. Note that exact match still trims whitespace.
     */
    exact?: boolean;
  }): Locator;

  /**
   * Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the
   * `aria-label` attribute.
   *
   * **Usage**
   *
   * For example, this method will find inputs by label "Username" and "Password" in the following DOM:
   *
   * ```html
   * <input aria-label="Username">
   * <label for="password-input">Password:</label>
   * <input id="password-input">
   * ```
   *
   * ```js
   * await page.getByLabel('Username').fill('john');
   * await page.getByLabel('Password').fill('secret');
   * ```
   *
   * @param text Text to locate the element for.
   * @param options
   */
  getByLabel(text: string|RegExp, options?: {
    /**
     * Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
     * regular expression. Note that exact match still trims whitespace.
     */
    exact?: boolean;
  }): Locator;

  /**
   * Allows locating input elements by the placeholder text.
   *
   * **Usage**
   *
   * For example, consider the following DOM structure.
   *
   * ```html
   * <input type="email" placeholder="name@example.com" />
   * ```
   *
   * You can fill the input after locating it by the placeholder text:
   *
   * ```js
   * await page
   *     .getByPlaceholder('name@example.com')
   *     .fill('playwright@microsoft.com');
   * ```
   *
   * @param text Text to locate the element for.
   * @param options
   */
  getByPlaceholder(text: string|RegExp, options?: {
    /**
     * Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a
     * regular expression. Note that exact match still trims whitespace.
     */
    exact?: boolean;
  }): Locator;

  /**
   * Allows locating elements by their [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles),
   * [ARIA attributes](https://www.w3.org/TR/wai-aria-1.2/#aria-attributes) and
   * [accessible name](https://w3c.github.io/accname/#dfn-accessible-name).
   *
   * **Usage**
   *
   * Consider the following DOM structure.
   *
   * ```html
   * <h3>Sign up</h3>
   * <label>
   *   <input type="checkbox" /> Subscribe
   * </label>
   * <br/>
   * <button>Submit</button>
   * ```
   *
   * You can locate each element by its implicit role:
   *
   * ```js
   * await expect(page.getByRole('heading', { name: 'Sign up' })).toBeVisible();
   *
   * await page.getByRole('checkbox', { name: 'Subscribe' }).check();
   *
   * await page.getByRole('button', { name: /submit/i }).click();
   * ```
   *
   * **Details**
   *
   * Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback
   * about the ARIA guidelines.
   *
   * Many html elements have an implicitly [defined role](https://w3c.github.io/html-aam/#html-element-role-mappings)
   * that is recognized by the role selector. You can find all the
   * [supported roles here](https://www.w3.org/TR/wai-aria-1.2/#role_definitions). ARIA guidelines **do not recommend**
   * duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
   * @param role Required aria role.
   * @param options
   */
  getByRole(role: "alert"|"alertdialog"|"application"|"article"|"banner"|"blockquote"|"button"|"caption"|"cell"|"checkbox"|"code"|"columnheader"|"combobox"|"complementary"|"contentinfo"|"definition"|"deletion"|"dialog"|"directory"|"document"|"emphasis"|"feed"|"figure"|"form"|"generic"|"grid"|"gridcell"|"group"|"heading"|"img"|"insertion"|"link"|"list"|"listbox"|"listitem"|"log"|"main"|"marquee"|"math"|"meter"|"menu"|"menubar"|"menuitem"|"menuitemcheckbox"|"menuitemradio"|"navigation"|"none"|"note"|"option"|"paragraph"|"presentation"|"progressbar"|"radio"|"radiogroup"|"region"|"row"|"rowgroup"|"rowheader"|"scrollbar"|"search"|"searchbox"|"separator"|"slider"|"spinbutton"|"status"|"strong"|"subscript"|"superscript"|"switch"|"tab"|"table"|"tablist"|"tabpanel"|"term"|"textbox"|"time"|"timer"|"toolbar"|"tooltip"|"tree"|"treegrid"|"treeitem", options?: {
    /**
     * An attribute that is usually set by `aria-checked` or native `<input type=checkbox>` controls.
     *
     * Learn more about [`aria-checked`](https://www.w3.org/TR/wai-aria-1.2/#aria-checked).
     */
    checked?: boolean;

    /**
     * Option to match the [accessible description](https://w3c.github.io/accname/#dfn-accessible-description). By
     * default, matching is case-insensitive and searches for a substring, use
     * [`exact`](https://playwright.dev/docs/api/class-framelocator#frame-locator-get-by-role-option-exact) to control
     * this behavior.
     *
     * Learn more about [accessible description](https://w3c.github.io/accname/#dfn-accessible-description).
     */
    description?: string|RegExp;

    /**
     * An attribute that is usually set by `aria-disabled` or `disabled`.
     *
     * **NOTE** Unlike most other attributes, `disabled` is inherited through the DOM hierarchy. Learn more about
     * [`aria-disabled`](https://www.w3.org/TR/wai-aria-1.2/#aria-disabled).
     *
     */
    disabled?: boolean;

    /**
     * Whether [`name`](https://playwright.dev/docs/api/class-framelocator#frame-locator-get-by-role-option-name) and
     * [`description`](https://playwright.dev/docs/api/class-framelocator#frame-locator-get-by-role-option-description)
     * are matched exactly: case-sensitive and whole-string. Defaults to false. Ignored when the value is a regular
     * expression. Note that exact match still trims whitespace.
     */
    exact?: boolean;

    /**
     * An attribute that is usually set by `aria-expanded`.
     *
     * Learn more about [`aria-expanded`](https://www.w3.org/TR/wai-aria-1.2/#aria-expanded).
     */
    expanded?: boolean;

    /**
     * Option that controls whether hidden elements are matched. By default, only non-hidden elements, as
     * [defined by ARIA](https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion), are matched by role selector.
     *
     * Learn more about [`aria-hidden`](https://www.w3.org/TR/wai-aria-1.2/#aria-hidden).
     */
    includeHidden?: boolean;

    /**
     * A number attribute that is usually present for roles `heading`, `listitem`, `row`, `treeitem`, with default values
     * for `<h1>-<h6>` elements.
     *
     * Learn more about [`aria-level`](https://www.w3.org/TR/wai-aria-1.2/#aria-level).
     */
    level?: number;

    /**
     * Option to match the [accessible name](https://w3c.github.io/accname/#dfn-accessible-name). By default, matching is
     * case-insensitive and searches for a substring, use
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

Keyboard

Keyboard provides an api for managing a virtual keyboard. The high level api is keyboard.type(text[, options]), which takes raw characters and generates proper keydown, keypress/input, and keyup events on your page.

For finer control, you can use keyboard.down(key), keyboard.up(key), and keyboard.insertText(text) to manually fire events as if they were generated from a real keyboard.

An example of holding down Shift in order to select and delete some text:

await page.keyboard.type('Hello World!')
await page.keyboard.press('ArrowLeft')

await page.keyboard.down('Shift')
for (let i = 0; i < ' World'.length; i++) await page.keyboard.press('ArrowLeft')
await page.keyboard.up('Shift')

await page.keyboard.press('Backspace')
// Result text will end up saying 'Hello!'

An example of pressing uppercase A

await page.keyboard.press('Shift+KeyA')
// or
await page.keyboard.press('Shift+A')

An example to trigger select-all with the keyboard

await page.keyboard.press('ControlOrMeta+A')
interface Keyboard {
  /**
   * Dispatches a `keydown` event.
   *
   * [`key`](https://playwright.dev/docs/api/class-keyboard#keyboard-down-option-key) can specify the intended
   * [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character
   * to generate the text for. A superset of the
   * [`key`](https://playwright.dev/docs/api/class-keyboard#keyboard-down-option-key) values can be found
   * [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
   *
   * `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
   * `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
   * etc.
   *
   * Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
   * `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
   *
   * Holding down `Shift` will type the text that corresponds to the
   * [`key`](https://playwright.dev/docs/api/class-keyboard#keyboard-down-option-key) in the upper case.
   *
   * If [`key`](https://playwright.dev/docs/api/class-keyboard#keyboard-down-option-key) is a single character, it is
   * case-sensitive, so the values `a` and `A` will generate different respective texts.
   *
   * If [`key`](https://playwright.dev/docs/api/class-keyboard#keyboard-down-option-key) is a modifier key, `Shift`,
   * `Meta`, `Control`, or `Alt`, subsequent key presses will be sent with that modifier active. To release the modifier
   * key, use [keyboard.up(key)](https://playwright.dev/docs/api/class-keyboard#keyboard-up).
   *
   * After the key is pressed once, subsequent calls to
   * [keyboard.down(key)](https://playwright.dev/docs/api/class-keyboard#keyboard-down) will have
   * [repeat](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat) set to true. To release the key,
   * use [keyboard.up(key)](https://playwright.dev/docs/api/class-keyboard#keyboard-up).
   *
   * **NOTE** Modifier keys DO influence `keyboard.down`. Holding down `Shift` will type the text in upper case.
   *
   * @param key Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
   */
  down(key: string): Promise<void>

  /**
   * Dispatches only `input` event, does not emit the `keydown`, `keyup` or `keypress` events.
   *
   * **Usage**
   *
   * ```js
   * page.keyboard.insertText('嗨');
   * ```
   *
   * **NOTE** Modifier keys DO NOT effect `keyboard.insertText`. Holding down `Shift` will not type the text in upper
   * case.
   *
   * @param text Sets input to the specified text value.
   */
  insertText(text: string): Promise<void>

  /**
   * **NOTE** In most cases, you should use
   * [locator.press(key[, options])](https://playwright.dev/docs/api/class-locator#locator-press) instead.
   *
   * [`key`](https://playwright.dev/docs/api/class-keyboard#keyboard-press-option-key) can specify the intended
   * [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character
   * to generate the text for. A superset of the
   * [`key`](https://playwright.dev/docs/api/class-keyboard#keyboard-press-option-key) values can be found
   * [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
   *
   * `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
   * `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`,
   * etc.
   *
   * Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`,
   * `ControlOrMeta`. `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
   *
   * Holding down `Shift` will type the text that corresponds to the
   * [`key`](https://playwright.dev/docs/api/class-keyboard#keyboard-press-option-key) in the upper case.
   *
   * If [`key`](https://playwright.dev/docs/api/class-keyboard#keyboard-press-option-key) is a single character, it is
   * case-sensitive, so the values `a` and `A` will generate different respective texts.
   *
   * Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When
   * specified with the modifier, modifier is pressed and being held while the subsequent key is being pressed.
   *
   * **Usage**
   *
   * ```js
   * const page = await browser.newPage();
   * await page.goto('https://keycode.info');
   * await page.keyboard.press('A');
   * await page.screenshot({ path: 'A.png' });
   * await page.keyboard.press('ArrowLeft');
   * await page.screenshot({ path: 'ArrowLeft.png' });
   * await page.keyboard.press('Shift+O');
   * await page.screenshot({ path: 'O.png' });
   * await browser.close();
   * ```
   *
   * Shortcut for [keyboard.down(key)](https://playwright.dev/docs/api/class-keyboard#keyboard-down) and
   * [keyboard.up(key)](https://playwright.dev/docs/api/class-keyboard#keyboard-up).
   * @param key Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
   * @param options
   */
  press(
    key: string,
    options?: {
      /**
       * Time to wait between `keydown` and `keyup` in milliseconds. Defaults to 0.
       */
      delay?: number
    },
  ): Promise<void>

  /**
   * **NOTE** In most cases, you should use
   * [locator.fill(value[, options])](https://playwright.dev/docs/api/class-locator#locator-fill) instead. You only need
   * to press keys one by one if there is special keyboard handling on the page - in this case use
   * [locator.pressSequentially(text[, options])](https://playwright.dev/docs/api/class-locator#locator-press-sequentially).
   *
   * Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.
   *
   * To press a special key, like `Control` or `ArrowDown`, use
   * [keyboard.press(key[, options])](https://playwright.dev/docs/api/class-keyboard#keyboard-press).
   *
   * **Usage**
   *
   * ```js
   * await page.keyboard.type('Hello'); // Types instantly
   * await page.keyboard.type('World', { delay: 100 }); // Types slower, like a user
   * ```
   *
   * **NOTE** Modifier keys DO NOT effect `keyboard.type`. Holding down `Shift` will not type the text in upper case.
   *
   * **NOTE** For characters that are not on a US keyboard, only an `input` event will be sent.
   *
   * @param text A text to type into a focused element.
   * @param options
   */
  type(
    text: string,
    options?: {
      /**
       * Time to wait between key presses in milliseconds. Defaults to 0.
       */
      delay?: number
    },
  ): Promise<void>

  /**
   * Dispatches a `keyup` event.
   * @param key Name of the key to press or a character to generate, such as `ArrowLeft` or `a`.
   */
  up(key: string): Promise<void>
}

Mouse

The Mouse class operates in main-frame CSS pixels relative to the top-left corner of the viewport.

NOTE If you want to debug where the mouse moved, you can use the Trace viewer or Playwright Inspector. A red dot showing the location of the mouse will be shown for every mouse action.

Every page object has its own Mouse, accessible with page.mouse.

// Using ‘page.mouse’ to trace a 100x100 square.
await page.mouse.move(0, 0)
await page.mouse.down()
await page.mouse.move(0, 100)
await page.mouse.move(100, 100)
await page.mouse.move(100, 0)
await page.mouse.move(0, 0)
await page.mouse.up()
interface Mouse {
  /**
   * Shortcut for [mouse.move(x, y[, options])](https://playwright.dev/docs/api/class-mouse#mouse-move),
   * [mouse.down([options])](https://playwright.dev/docs/api/class-mouse#mouse-down),
   * [mouse.up([options])](https://playwright.dev/docs/api/class-mouse#mouse-up).
   * @param x X coordinate relative to the main frame's viewport in CSS pixels.
   * @param y Y coordinate relative to the main frame's viewport in CSS pixels.
   * @param options
   */
  click(
    x: number,
    y: number,
    options?: {
      /**
       * Defaults to `left`.
       */
      button?: 'left' | 'right' | 'middle'

      /**
       * defaults to 1. See [UIEvent.detail].
       */
      clickCount?: number

      /**
       * Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
       */
      delay?: number
    },
  ): Promise<void>

  /**
   * Shortcut for [mouse.move(x, y[, options])](https://playwright.dev/docs/api/class-mouse#mouse-move),
   * [mouse.down([options])](https://playwright.dev/docs/api/class-mouse#mouse-down),
   * [mouse.up([options])](https://playwright.dev/docs/api/class-mouse#mouse-up),
   * [mouse.down([options])](https://playwright.dev/docs/api/class-mouse#mouse-down) and
   * [mouse.up([options])](https://playwright.dev/docs/api/class-mouse#mouse-up).
   * @param x X coordinate relative to the main frame's viewport in CSS pixels.
   * @param y Y coordinate relative to the main frame's viewport in CSS pixels.
   * @param options
   */
  dblclick(
    x: number,
    y: number,
    options?: {
      /**
       * Defaults to `left`.
       */
      button?: 'left' | 'right' | 'middle'

      /**
       * Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0.
       */
      delay?: number
    },
  ): Promise<void>

  /**
   * Dispatches a `mousedown` event.
   * @param options
   */
  down(options?: {
    /**
     * Defaults to `left`.
     */
    button?: 'left' | 'right' | 'middle'

    /**
     * defaults to 1. See [UIEvent.detail].
     */
    clickCount?: number
  }): Promise<void>

  /**
   * Dispatches a `mousemove` event.
   * @param x X coordinate relative to the main frame's viewport in CSS pixels.
   * @param y Y coordinate relative to the main frame's viewport in CSS pixels.
   * @param options
   */
  move(
    x: number,
    y: number,
    options?: {
      /**
       * Defaults to 1. Sends `n` interpolated `mousemove` events to represent travel between Playwright's current cursor
       * position and the provided destination. When set to 1, emits a single `mousemove` event at the destination location.
       */
      steps?: number
    },
  ): Promise<void>

  /**
   * Dispatches a `mouseup` event.
   * @param options
   */
  up(options?: {
    /**
     * Defaults to `left`.
     */
    button?: 'left' | 'right' | 'middle'

    /**
     * defaults to 1. See [UIEvent.detail].
     */
    clickCount?: number
  }): Promise<void>

  /**
   * Dispatches a `wheel` event. This method is usually used to manually scroll the page. See
   * [scrolling](https://playwright.dev/docs/input#scrolling) for alternative ways to scroll.
   *
   * **NOTE** Wheel events may cause scrolling if they are not handled, and this method does not wait for the scrolling
   * to finish before returning.
   *
   * @param deltaX Pixels to scroll horizontally.
   * @param deltaY Pixels to scroll vertically.
   */
  wheel(deltaX: number, deltaY: number): Promise<void>
}

Request

Whenever the page sends a request for a network resource the following sequence of events are emitted by Page:

If request fails at some point, then instead of 'requestfinished' event (and possibly instead of 'response' event), the page.on('requestfailed') event is emitted.

NOTE HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will complete with 'requestfinished' event.

If request gets a 'redirect' response, the request is successfully finished with the requestfinished event, and a new request is issued to a redirected url.

interface Request {
  /**
   * An object with all the request HTTP headers associated with this request. The header names are lower-cased.
   */
  allHeaders(): Promise<{ [key: string]: string; }>;

  /**
   * Returns the [Response](https://playwright.dev/docs/api/class-response) object if the response has already been
   * received, `null` otherwise.
   *
   * Unlike [request.response()](https://playwright.dev/docs/api/class-request#request-response), this method does not
   * wait for the response to arrive. It returns immediately with the response object if the response has been received,
   * or `null` if the response has not been received yet.
   */
  existingResponse(): null|Response;

  /**
   * The method returns `null` unless this request has failed, as reported by `requestfailed` event.
   *
   * **Usage**
   *
   * Example of logging of all the failed requests:
   *
   * ```js
   * page.on('requestfailed', request => {
   *   console.log(request.url() + ' ' + request.failure().errorText);
   * });
   * ```
   *
   */
  failure(): null|{
    /**
     * Human-readable error message, e.g. `'net::ERR_FAILED'`.
     */
    errorText: string;
  };

  /**
   * Returns the [Frame](https://playwright.dev/docs/api/class-frame) that initiated this request.
   *
   * **Usage**
   *
   * ```js
   * const frameUrl = request.frame().url();
   * ```
   *
   * **Details**
   *
   * Note that in some cases the frame is not available, and this method will throw.
   * - When request originates in the Service Worker. You can use `request.serviceWorker()` to check that.
   * - When navigation request is issued before the corresponding frame is created. You can use
   *   [request.isNavigationRequest()](https://playwright.dev/docs/api/class-request#request-is-navigation-request) to
   *   check that.
   *
   * Here is an example that handles all the cases:
   *
   * ```js
   * if (request.serviceWorker())
   *   console.log(`request ${request.url()} from a service worker`);
   * else if (request.isNavigationRequest())
   *   console.log(`request ${request.url()} is a navigation request`);
   * else
   *   console.log(`request ${request.url()} from a frame ${request.frame().url()}`);
   * ```
   *
   */
  frame(): Frame;

  /**
   * An object with the request HTTP headers. The header names are lower-cased. Note that this method does not return
   * security-related headers, including cookie-related ones. You can use
   * [request.allHeaders()](https://playwright.dev/docs/api/class-request#request-all-headers) for complete list of
   * headers that include `cookie` information.
   */
  headers(): { [key: string]: string; };

  /**
   * An array with all the request HTTP headers associated with this request. Unlike
   * [request.allHeaders()](https://playwright.dev/docs/api/class-request#request-all-headers), header names are NOT
   * lower-cased. Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
   */
  headersArray(): Promise<Array<{
    /**
     * Name of the header.
     */
    name: string;

    /**
     * Value of the header.
     */
    value: string;
  }>>;

  /**
   * Returns the value of the header matching the name. The name is case-insensitive.
   * @param name Name of the header.
   */
  headerValue(name: string): Promise<null|string>;

  /**
   * Whether this request is driving frame's navigation.
   *
   * Some navigation requests are issued before the corresponding frame is created, and therefore do not have
   * [request.frame()](https://playwright.dev/docs/api/class-request#request-frame) available.
   */
  isNavigationRequest(): boolean;

  /**
   * Request's method (GET, POST, etc.)
   */
  method(): string;

  /**
   * Request's post body, if any.
   */
  postData(): null|string;

  /**
   * Request's post body in a binary form, if any.
   */
  postDataBuffer(): null|Buffer;

  /**
   * Returns parsed request's body for `form-urlencoded` and JSON as a fallback if any.
   *
   * When the response is `application/x-www-form-urlencoded` then a key/value object of the values will be returned.
   * Otherwise it will be parsed as JSON.
   */
  postDataJSON(): null|Serializable;

  /**
   * Request that was redirected by the server to this one, if any.
   *
   * When the server responds with a redirect, Playwright creates a new
   * [Request](https://playwright.dev/docs/api/class-request) object. The two requests are connected by
   * `redirectedFrom()` and `redirectedTo()` methods. When multiple server redirects has happened, it is possible to
   * construct the whole redirect chain by repeatedly calling `redirectedFrom()`.
   *
   * **Usage**
   *
   * For example, if the website `http://example.com` redirects to `https://example.com`:
   *
   * ```js
   * const response = await page.goto('http://example.com');
   * console.log(response.request().redirectedFrom().url()); // 'http://example.com'
   * ```
   *
   * If the website `https://google.com` has no redirects:
   *
   * ```js
   * const response = await page.goto('https://google.com');
   * console.log(response.request().redirectedFrom()); // null
   * ```
   *
   */
  redirectedFrom(): null|Request;

  /**
   * New request issued by the browser if the server responded with redirect.
   *
   * **Usage**
   *
   * This method is the opposite of
   * [request.redirectedFrom()](https://playwright.dev/docs/api/class-request#request-redirected-from):
   *
   * ```js
   * console.log(request.redirectedFrom().redirectedTo() === request); // true
   * ```
   *
   */
  redirectedTo(): null|Request;

  /**
   * Contains the request's resource type as it was perceived by the rendering engine. ResourceType will be one of the
   * following: `document`, `stylesheet`, `image`, `media`, `font`, `script`, `texttrack`, `xhr`, `fetch`,
   * `eventsource`, `websocket`, `manifest`, `other`.
   */
  resourceType(): string;

  /**
   * Returns the matching [Response](https://playwright.dev/docs/api/class-response) object, or `null` if the response
   * was not received due to error.
   */
  response(): Promise<null|Response>;

  /**
   * The Service [Worker](https://playwright.dev/docs/api/class-worker) that is performing the request.
   *
   * **Details**
   *
   * This method is Chromium only. It's safe to call when using other browsers, but it will always be `null`.
   *
   * Requests originated in a Service Worker do not have a
   * [request.frame()](https://playwright.dev/docs/api/class-request#request-frame) available.
   */
  serviceWorker(): null|Worker;

  /**
   * Returns resource size information for given request.
   */
  sizes(): Promise<{
    /**
     * Size of the request body (POST data payload) in bytes. Set to 0 if there was no body.
     */
    requestBodySize: number;

    /**
     * Total number of bytes from the start of the HTTP request message until (and including) the double CRLF before the
     * body.
     */
    requestHeadersSize: number;

    /**
     * Size of the received response body (encoded) in bytes.
     */
    responseBodySize: number;

    /**
     * Total number of bytes from the start of the HTTP response message until (and including) the double CRLF before the
     * body.
     */
    responseHeadersSize: number;
  }>;

  /**
   * Returns resource timing information for given request. Most of the timing values become available upon the
   * response, `responseEnd` becomes available when request finishes. Find more information at
   * [Resource Timing API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming).
   *
   * **Usage**
   *
   * ```js
   * const requestFinishedPromise = page.waitForEvent('requestfinished');
   * await page.goto('http://example.com');
   * const request = await requestFinishedPromise;
   * console.log(request.timing());
   * ```
   *
   */
  timing(): {
    /**
     * Request start time in milliseconds elapsed since January 1, 1970 00:00:00 UTC
     */
    startTime: number;

    /**
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

Response

Response class represents responses which are received by page.

interface Response {
  /**
   * An object with all the response HTTP headers associated with this response.
   */
  allHeaders(): Promise<{ [key: string]: string }>

  /**
   * Returns the buffer with response body.
   */
  body(): Promise<Buffer>

  /**
   * Waits for this response to finish, returns always `null`.
   */
  finished(): Promise<null | Error>

  /**
   * Returns the [Frame](https://playwright.dev/docs/api/class-frame) that initiated this response.
   */
  frame(): Frame

  /**
   * Indicates whether this Response was fulfilled by a Service Worker's Fetch Handler (i.e. via
   * [FetchEvent.respondWith](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith)).
   */
  fromServiceWorker(): boolean

  /**
   * An object with the response HTTP headers. The header names are lower-cased. Note that this method does not return
   * security-related headers, including cookie-related ones. You can use
   * [response.allHeaders()](https://playwright.dev/docs/api/class-response#response-all-headers) for complete list of
   * headers that include `cookie` information.
   */
  headers(): { [key: string]: string }

  /**
   * An array with all the request HTTP headers associated with this response. Unlike
   * [response.allHeaders()](https://playwright.dev/docs/api/class-response#response-all-headers), header names are NOT
   * lower-cased. Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
   */
  headersArray(): Promise<
    Array<{
      /**
       * Name of the header.
       */
      name: string

      /**
       * Value of the header.
       */
      value: string
    }>
  >

  /**
   * Returns the value of the header matching the name. The name is case-insensitive. If multiple headers have the same
   * name (except `set-cookie`), they are returned as a list separated by `, `. For `set-cookie`, the `\n` separator is
   * used. If no headers are found, `null` is returned.
   * @param name Name of the header.
   */
  headerValue(name: string): Promise<null | string>

  /**
   * Returns all values of the headers matching the name, for example `set-cookie`. The name is case-insensitive.
   * @param name Name of the header.
   */
  headerValues(name: string): Promise<Array<string>>

  /**
   * Returns the http version used by the response.
   */
  httpVersion(): Promise<string>

  /**
   * Returns the JSON representation of response body.
   *
   * This method will throw if the response body is not parsable via `JSON.parse`.
   */
  json(): Promise<Serializable>

  /**
   * Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
   */
  ok(): boolean

  /**
   * Returns the matching [Request](https://playwright.dev/docs/api/class-request) object.
   */
  request(): Request

  /**
   * Returns SSL and other security information.
   */
  securityDetails(): Promise<null | {
    /**
     * Common Name component of the Issuer field. from the certificate. This should only be used for informational
     * purposes. Optional.
     */
    issuer?: string

    /**
     * The specific TLS protocol used. (e.g. `TLS 1.3`). Optional.
     */
    protocol?: string

    /**
     * Common Name component of the Subject field from the certificate. This should only be used for informational
     * purposes. Optional.
     */
    subjectName?: string

    /**
     * Unix timestamp (in seconds) specifying when this cert becomes valid. Optional.
     */
    validFrom?: number

    /**
     * Unix timestamp (in seconds) specifying when this cert becomes invalid. Optional.
     */
    validTo?: number
  }>

  /**
   * Returns the IP address and port of the server.
   */
  serverAddr(): Promise<null | {
    /**
     * IPv4 or IPV6 address of the server.
     */
    ipAddress: string

    port: number
  }>

  /**
   * Contains the status code of the response (e.g., 200 for a success).
   */
  status(): number

  /**
   * Contains the status text of the response (e.g. usually an "OK" for a success).
   */
  statusText(): string

  /**
   * Returns the text representation of response body.
   */
  text(): Promise<string>

  /**
   * Contains the URL of the response.
   */
  url(): string
}

Route

Whenever a network route is set up with page.route(url, handler[, options]) or browserContext.route(url, handler[, options]), the Route object allows to handle the route.

Learn more about networking.

interface Route {
  /**
   * Aborts the route's request.
   * @param errorCode Optional error code. Defaults to `failed`, could be one of the following:
   * - `'aborted'` - An operation was aborted (due to user action)
   * - `'accessdenied'` - Permission to access a resource, other than the network, was denied
   * - `'addressunreachable'` - The IP address is unreachable. This usually means that there is no route to the
   * specified host or network.
   * - `'blockedbyclient'` - The client chose to block the request.
   * - `'blockedbyresponse'` - The request failed because the response was delivered along with requirements which are
   * not met ('X-Frame-Options' and 'Content-Security-Policy' ancestor checks, for instance).
   * - `'connectionaborted'` - A connection timed out as a result of not receiving an ACK for data sent.
   * - `'connectionclosed'` - A connection was closed (corresponding to a TCP FIN).
   * - `'connectionfailed'` - A connection attempt failed.
   * - `'connectionrefused'` - A connection attempt was refused.
   * - `'connectionreset'` - A connection was reset (corresponding to a TCP RST).
   * - `'internetdisconnected'` - The Internet connection has been lost.
   * - `'namenotresolved'` - The host name could not be resolved.
   * - `'timedout'` - An operation timed out.
   * - `'failed'` - A generic failure occurred.
   */
  abort(errorCode?: string): Promise<void>;

  /**
   * Sends route's request to the network with optional overrides.
   *
   * **Usage**
   *
   * ```js
   * await page.route('**\/*', async (route, request) => {
   *   // Override headers
   *   const headers = {
   *     ...request.headers(),
   *     foo: 'foo-value', // set "foo" header
   *     bar: undefined, // remove "bar" header
   *   };
   *   await route.continue({ headers });
   * });
   * ```
   *
   * **Details**
   *
   * The [`headers`](https://playwright.dev/docs/api/class-route#route-continue-option-headers) option applies to both
   * the routed request and any redirects it initiates. However,
   * [`url`](https://playwright.dev/docs/api/class-route#route-continue-option-url),
   * [`method`](https://playwright.dev/docs/api/class-route#route-continue-option-method), and
   * [`postData`](https://playwright.dev/docs/api/class-route#route-continue-option-post-data) only apply to the
   * original request and are not carried over to redirected requests.
   *
   * [route.continue([options])](https://playwright.dev/docs/api/class-route#route-continue) will immediately send the
   * request to the network, other matching handlers won't be invoked. Use
   * [route.fallback([options])](https://playwright.dev/docs/api/class-route#route-fallback) If you want next matching
   * handler in the chain to be invoked.
   *
   * **NOTE** Some request headers are **forbidden** and cannot be overridden (for example, `Cookie`, `Host`,
   * `Content-Length` and others, see
   * [this MDN page](https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header) for full list). If an
   * override is provided for a forbidden header, it will be ignored and the original request header will be used.
   *
   * To set custom cookies, use
   * [browserContext.addCookies(cookies)](https://playwright.dev/docs/api/class-browsercontext#browser-context-add-cookies).
   *
   * @param options
   */
  continue(options?: {
    /**
     * If set changes the request HTTP headers. Header values will be converted to a string.
     */
    headers?: { [key: string]: string; };

    /**
     * If set changes the request method (e.g. GET or POST).
     */
    method?: string;

    /**
     * If set changes the post data of request.
     */
    postData?: string|Buffer|Serializable;

    /**
     * If set changes the request URL. New URL must have same protocol as original one.
     */
    url?: string;
  }): Promise<void>;

  /**
   * Continues route's request with optional overrides. The method is similar to
   * [route.continue([options])](https://playwright.dev/docs/api/class-route#route-continue) with the difference that
   * other matching handlers will be invoked before sending the request.
   *
   * **Usage**
   *
   * When several routes match the given pattern, they run in the order opposite to their registration. That way the
   * last registered route can always override all the previous ones. In the example below, request will be handled by
   * the bottom-most handler first, then it'll fall back to the previous one and in the end will be aborted by the first
   * registered route.
   *
   * ```js
   * await page.route('**\/*', async route => {
   *   // Runs last.
   *   await route.abort();
   * });
   * await page.route('**\/*', async route => {
   *   // Runs second.
   *   await route.fallback();
   * });
   * await page.route('**\/*', async route => {
   *   // Runs first.
   *   await route.fallback();
   * });
   * ```
   *
   * Registering multiple routes is useful when you want separate handlers to handle different kinds of requests, for
   * example API calls vs page resources or GET requests vs POST requests as in the example below.
   *
   * ```js
   * // Handle GET requests.
   * await page.route('**\/*', async route => {
   *   if (route.request().method() !== 'GET') {
   *     await route.fallback();
   *     return;
   *   }
   *   // Handling GET only.
   *   // ...
   * });
   *
   * // Handle POST requests.
   * await page.route('**\/*', async route => {
   *   if (route.request().method() !== 'POST') {
   *     await route.fallback();
   *     return;
   *   }
   *   // Handling POST only.
   *   // ...
   * });
   * ```
   *
   * One can also modify request while falling back to the subsequent handler, that way intermediate route handler can
   * modify url, method, headers and postData of the request.
   *
   * ```js
   * await page.route('**\/*', async (route, request) => {
   *   // Override headers
   *   const headers = {
   *     ...request.headers(),
   *     foo: 'foo-value', // set "foo" header
   *     bar: undefined, // remove "bar" header
   *   };
   *   await route.fallback({ headers });
   * });
   * ```
   *
   * Use [route.continue([options])](https://playwright.dev/docs/api/class-route#route-continue) to immediately send the
   * request to the network, other matching handlers won't be invoked in that case.
   * @param options
   */
  fallback(options?: {
    /**
     * If set changes the request HTTP headers. Header values will be converted to a string.
     */
    headers?: { [key: string]: string; };

    /**
     * If set changes the request method (e.g. GET or POST).
     */
    method?: string;

    /**
     * If set changes the post data of request.
     */
    postData?: string|Buffer|Serializable;

    /**
     * If set changes the request URL. New URL must have same protocol as original one. Changing the URL won't affect the
     * route matching, all the routes are matched using the original request URL.
     */
    url?: string;
  }): Promise<void>;

  /**
   * Performs the request and fetches result without fulfilling it, so that the response could be modified and then
   * fulfilled.
   *
   * **Usage**
   *
   * ```js
   * await page.route('https://dog.ceo/api/breeds/list/all', async route => {
   *   const response = await route.fetch();
   *   const json = await response.json();
   *   json.message['big_red_dog'] = [];
   *   await route.fulfill({ response, json });
   * });
   * ```
   *
   * **Details**
   *
   * Note that [`headers`](https://playwright.dev/docs/api/class-route#route-fetch-option-headers) option will apply to
   * the fetched request as well as any redirects initiated by it. If you want to only apply
   * [`headers`](https://playwright.dev/docs/api/class-route#route-fetch-option-headers) to the original request, but
   * not to redirects, look into [route.continue([options])](https://playwright.dev/docs/api/class-route#route-continue)
   * instead.
   * @param options
   */
// … truncated — the full declaration is in node_modules/playwright-core/types/types.d.ts

Touchscreen

The Touchscreen class operates in main-frame CSS pixels relative to the top-left corner of the viewport. Methods on the touchscreen can only be used in browser contexts that have been initialized with hasTouch set to true.

This class is limited to emulating tap gestures. For examples of other gestures simulated by manually dispatching touch events, see the emulating legacy touch events page.

interface Touchscreen {
  /**
   * Dispatches a `touchstart` and `touchend` event with a single touch at the position
   * ([`x`](https://playwright.dev/docs/api/class-touchscreen#touchscreen-tap-option-x),[`y`](https://playwright.dev/docs/api/class-touchscreen#touchscreen-tap-option-y)).
   *
   * **NOTE** [touchscreen.tap(x, y)](https://playwright.dev/docs/api/class-touchscreen#touchscreen-tap) will throw if
   * the [`hasTouch`](https://playwright.dev/docs/api/class-browser#browser-new-context-option-has-touch) option of the
   * browser context is false.
   *
   * @param x X coordinate relative to the main frame's viewport in CSS pixels.
   * @param y Y coordinate relative to the main frame's viewport in CSS pixels.
   */
  tap(x: number, y: number): Promise<void>
}

FullProject

Runtime representation of the test project configuration. It is accessible in the tests via testInfo.project and workerInfo.project and is passed to the test reporters. To see the format of the project in the Playwright configuration file please see TestProject instead.

interface FullProject<TestArgs = {}, WorkerArgs = {}> {
  /**
   * See [testProject.use](https://playwright.dev/docs/api/class-testproject#test-project-use).
   */
  use: UseOptions<PlaywrightTestOptions & TestArgs, PlaywrightWorkerOptions & WorkerArgs>
  /**
   * See [testProject.dependencies](https://playwright.dev/docs/api/class-testproject#test-project-dependencies).
   */
  dependencies: Array<string>

  /**
   * See [testProject.grep](https://playwright.dev/docs/api/class-testproject#test-project-grep).
   */
  grep: RegExp | Array<RegExp>

  /**
   * See [testProject.grepInvert](https://playwright.dev/docs/api/class-testproject#test-project-grep-invert).
   */
  grepInvert: null | RegExp | Array<RegExp>

  /**
   * See [testProject.ignoreSnapshots](https://playwright.dev/docs/api/class-testproject#test-project-ignore-snapshots).
   */
  ignoreSnapshots: boolean

  /**
   * See [testProject.metadata](https://playwright.dev/docs/api/class-testproject#test-project-metadata).
   */
  metadata: Metadata

  /**
   * See [testProject.name](https://playwright.dev/docs/api/class-testproject#test-project-name).
   */
  name: string

  /**
   * See [testProject.outputDir](https://playwright.dev/docs/api/class-testproject#test-project-output-dir).
   */
  outputDir: string

  /**
   * See [testProject.repeatEach](https://playwright.dev/docs/api/class-testproject#test-project-repeat-each).
   */
  repeatEach: number

  /**
   * See [testProject.retries](https://playwright.dev/docs/api/class-testproject#test-project-retries).
   */
  retries: number

  /**
   * See [testProject.snapshotDir](https://playwright.dev/docs/api/class-testproject#test-project-snapshot-dir).
   */
  snapshotDir: string

  /**
   * See [testProject.teardown](https://playwright.dev/docs/api/class-testproject#test-project-teardown).
   */
  teardown?: string

  /**
   * See [testProject.testDir](https://playwright.dev/docs/api/class-testproject#test-project-test-dir).
   */
  testDir: string

  /**
   * See [testProject.testIgnore](https://playwright.dev/docs/api/class-testproject#test-project-test-ignore).
   */
  testIgnore: string | RegExp | Array<string | RegExp>

  /**
   * See [testProject.testMatch](https://playwright.dev/docs/api/class-testproject#test-project-test-match).
   */
  testMatch: string | RegExp | Array<string | RegExp>

  /**
   * See [testProject.timeout](https://playwright.dev/docs/api/class-testproject#test-project-timeout).
   */
  timeout: number
}

FullConfig

Resolved configuration which is accessible via testInfo.config and is passed to the test reporters. To see the format of Playwright configuration file, please see TestConfig instead.

interface FullConfig<TestArgs = {}, WorkerArgs = {}> {
  /**
   * List of resolved projects.
   */
  projects: FullProject<TestArgs, WorkerArgs>[]
  /**
   * See [testConfig.reporter](https://playwright.dev/docs/api/class-testconfig#test-config-reporter).
   */
  reporter: ReporterDescription[]
  /**
   * See [testConfig.webServer](https://playwright.dev/docs/api/class-testconfig#test-config-web-server).
   */
  webServer: TestConfigWebServer | null
  /**
   * Snapshot of [`process.argv`](https://nodejs.org/api/process.html#processargv) captured in the runner process.
   * Useful for reading custom command-line arguments — for example, args supplied after the `--` separator (`npx
   * playwright test -- --build-path=./out`). Playwright does not parse these; consumers are responsible for slicing and
   * interpreting them with any argument-parsing library.
   */
  argv: Array<string>

  /**
   * Path to the configuration file used to run the tests. The value is an empty string if no config file was used.
   */
  configFile?: string

  /**
   * See
   * [testConfig.failOnFlakyTests](https://playwright.dev/docs/api/class-testconfig#test-config-fail-on-flaky-tests).
   */
  failOnFlakyTests: boolean

  /**
   * See [testConfig.forbidOnly](https://playwright.dev/docs/api/class-testconfig#test-config-forbid-only).
   */
  forbidOnly: boolean

  /**
   * See [testConfig.fullyParallel](https://playwright.dev/docs/api/class-testconfig#test-config-fully-parallel).
   */
  fullyParallel: boolean

  /**
   * See [testConfig.globalSetup](https://playwright.dev/docs/api/class-testconfig#test-config-global-setup).
   */
  globalSetup: null | string

  /**
   * See [testConfig.globalTeardown](https://playwright.dev/docs/api/class-testconfig#test-config-global-teardown).
   */
  globalTeardown: null | string

  /**
   * See [testConfig.globalTimeout](https://playwright.dev/docs/api/class-testconfig#test-config-global-timeout).
   */
  globalTimeout: number

  /**
   * See [testConfig.grep](https://playwright.dev/docs/api/class-testconfig#test-config-grep).
   */
  grep: RegExp | Array<RegExp>

  /**
   * See [testConfig.grepInvert](https://playwright.dev/docs/api/class-testconfig#test-config-grep-invert).
   */
  grepInvert: null | RegExp | Array<RegExp>

  /**
   * See [testConfig.maxFailures](https://playwright.dev/docs/api/class-testconfig#test-config-max-failures).
   */
  maxFailures: number

  /**
   * See [testConfig.metadata](https://playwright.dev/docs/api/class-testconfig#test-config-metadata).
   */
  metadata: Metadata

  /**
   * See [testConfig.preserveOutput](https://playwright.dev/docs/api/class-testconfig#test-config-preserve-output).
   */
  preserveOutput: 'always' | 'never' | 'failures-only'

  /**
   * See [testConfig.quiet](https://playwright.dev/docs/api/class-testconfig#test-config-quiet).
   */
  quiet: boolean

  /**
   * See [testConfig.reportSlowTests](https://playwright.dev/docs/api/class-testconfig#test-config-report-slow-tests).
   */
  reportSlowTests: null | {
    /**
     * The maximum number of slow test files to report.
     */
    max: number

    /**
     * Test file duration in milliseconds that is considered slow.
     */
    threshold: number
  }

  /**
   * Base directory for all relative paths used in the reporters.
   */
  rootDir: string

  /**
   * See [testConfig.shard](https://playwright.dev/docs/api/class-testconfig#test-config-shard).
   */
  shard: null | {
    /**
     * The total number of shards.
     */
    total: number

    /**
     * The index of the shard to execute, one-based.
     */
    current: number
  }

  /**
   * Resolved global tags. See [testConfig.tag](https://playwright.dev/docs/api/class-testconfig#test-config-tag).
   */
  tags: Array<string>

  /**
   * See [testConfig.updateSnapshots](https://playwright.dev/docs/api/class-testconfig#test-config-update-snapshots).
   */
  updateSnapshots: 'all' | 'changed' | 'missing' | 'none'

  /**
   * See
   * [testConfig.updateSourceMethod](https://playwright.dev/docs/api/class-testconfig#test-config-update-source-method).
   */
  updateSourceMethod: 'overwrite' | '3way' | 'patch'

  /**
   * Playwright version.
   */
  version: string

  /**
   * See [testConfig.workers](https://playwright.dev/docs/api/class-testconfig#test-config-workers).
   */
  workers: number
}

TestInfo

TestInfo contains information about currently running test. It is available to test functions, test.beforeEach([title, hookFunction]), test.afterEach([title, hookFunction]), test.beforeAll([title, hookFunction]) and test.afterAll([title, hookFunction]) hooks, and test-scoped fixtures. TestInfo provides utilities to control test execution: attach files, update test timeout, determine which test is currently running and whether it was retried, etc.

import { test, expect } from '@playwright/test'

test('basic test', async ({ page }, testInfo) => {
  expect(testInfo.title).toBe('basic test')
  await page.screenshot(testInfo.outputPath('screenshot.png'))
})
interface TestInfo {
  /**
   * Returns a path to a snapshot file with the given `name`. Pass
   * [`kind`](https://playwright.dev/docs/api/class-testinfo#test-info-snapshot-path-option-kind) to obtain a specific
   * path:
   * - `kind: 'screenshot'` for
   *   [expect(page).toHaveScreenshot(name[, options])](https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot-1);
   * - `kind: 'aria'` for
   *   [expect(locator).toMatchAriaSnapshot(expected[, options])](https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-match-aria-snapshot);
   * - `kind: 'snapshot'` for
   *   [expect(value).toMatchSnapshot(name[, options])](https://playwright.dev/docs/api/class-snapshotassertions#snapshot-assertions-to-match-snapshot-1).
   *
   * **Usage**
   *
   * ```js
   * await expect(page).toHaveScreenshot('header.png');
   * // Screenshot assertion above expects screenshot at this path:
   * const screenshotPath = test.info().snapshotPath('header.png', { kind: 'screenshot' });
   *
   * await expect(page.getByRole('main')).toMatchAriaSnapshot({ name: 'main.aria.yml' });
   * // Aria snapshot assertion above expects snapshot at this path:
   * const ariaSnapshotPath = test.info().snapshotPath('main.aria.yml', { kind: 'aria' });
   *
   * expect('some text').toMatchSnapshot('snapshot.txt');
   * // Snapshot assertion above expects snapshot at this path:
   * const snapshotPath = test.info().snapshotPath('snapshot.txt');
   *
   * expect('some text').toMatchSnapshot(['dir', 'subdir', 'snapshot.txt']);
   * // Snapshot assertion above expects snapshot at this path:
   * const nestedPath = test.info().snapshotPath('dir', 'subdir', 'snapshot.txt');
   * ```
   *
   * @param name The name of the snapshot or the path segments to define the snapshot file path. Snapshots with the same name in the
   * same test file are expected to be the same.
   *
   * When passing [`kind`](https://playwright.dev/docs/api/class-testinfo#test-info-snapshot-path-option-kind), multiple
   * name segments are not supported.
   * @param options
   */
  snapshotPath(...name: ReadonlyArray<string>): string;
  /**
   * Returns a path to a snapshot file with the given `name`. Pass
   * [`kind`](https://playwright.dev/docs/api/class-testinfo#test-info-snapshot-path-option-kind) to obtain a specific
   * path:
   * - `kind: 'screenshot'` for
   *   [expect(page).toHaveScreenshot(name[, options])](https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot-1);
   * - `kind: 'aria'` for
   *   [expect(locator).toMatchAriaSnapshot(expected[, options])](https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-match-aria-snapshot);
   * - `kind: 'snapshot'` for
   *   [expect(value).toMatchSnapshot(name[, options])](https://playwright.dev/docs/api/class-snapshotassertions#snapshot-assertions-to-match-snapshot-1).
   *
   * **Usage**
   *
   * ```js
   * await expect(page).toHaveScreenshot('header.png');
   * // Screenshot assertion above expects screenshot at this path:
   * const screenshotPath = test.info().snapshotPath('header.png', { kind: 'screenshot' });
   *
   * await expect(page.getByRole('main')).toMatchAriaSnapshot({ name: 'main.aria.yml' });
   * // Aria snapshot assertion above expects snapshot at this path:
   * const ariaSnapshotPath = test.info().snapshotPath('main.aria.yml', { kind: 'aria' });
   *
   * expect('some text').toMatchSnapshot('snapshot.txt');
   * // Snapshot assertion above expects snapshot at this path:
   * const snapshotPath = test.info().snapshotPath('snapshot.txt');
   *
   * expect('some text').toMatchSnapshot(['dir', 'subdir', 'snapshot.txt']);
   * // Snapshot assertion above expects snapshot at this path:
   * const nestedPath = test.info().snapshotPath('dir', 'subdir', 'snapshot.txt');
   * ```
   *
   * @param name The name of the snapshot or the path segments to define the snapshot file path. Snapshots with the same name in the
   * same test file are expected to be the same.
   *
   * When passing [`kind`](https://playwright.dev/docs/api/class-testinfo#test-info-snapshot-path-option-kind), multiple
   * name segments are not supported.
   * @param options
   */
  snapshotPath(name: string, options: { kind: 'snapshot' | 'screenshot' | 'aria' }): string;
  /**
   * Attach a value or a file from disk to the current test. Some reporters show test attachments. Either
   * [`path`](https://playwright.dev/docs/api/class-testinfo#test-info-attach-option-path) or
   * [`body`](https://playwright.dev/docs/api/class-testinfo#test-info-attach-option-body) must be specified, but not
   * both.
   *
   * For example, you can attach a screenshot to the test:
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('basic test', async ({ page }, testInfo) => {
   *   await page.goto('https://playwright.dev');
   *   const screenshot = await page.screenshot();
   *   await testInfo.attach('screenshot', { body: screenshot, contentType: 'image/png' });
   * });
   * ```
   *
   * Or you can attach files returned by your APIs:
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   * import { download } from './my-custom-helpers';
   *
   * test('basic test', async ({}, testInfo) => {
   *   const tmpPath = await download('a');
   *   await testInfo.attach('downloaded', { path: tmpPath });
   * });
   * ```
   *
   * **NOTE** [testInfo.attach(name[, options])](https://playwright.dev/docs/api/class-testinfo#test-info-attach)
   * automatically takes care of copying attached files to a location that is accessible to reporters. You can safely
   * remove the attachment after awaiting the attach call.
   *
   * @param name Attachment name. The name will also be sanitized and used as the prefix of file name when saving to disk.
   * @param options
   */
  attach(name: string, options?: {
    /**
     * Attachment body. Mutually exclusive with
     * [`path`](https://playwright.dev/docs/api/class-testinfo#test-info-attach-option-path).
     */
    body?: string|Buffer;

    /**
     * Content type of this attachment to properly present in the report, for example `'application/json'` or
     * `'image/png'`. If omitted, content type is inferred based on the
     * [`path`](https://playwright.dev/docs/api/class-testinfo#test-info-attach-option-path), or defaults to `text/plain`
     * for [string] attachments and `application/octet-stream` for [Buffer] attachments.
     */
    contentType?: string;

    /**
     * Path on the filesystem to the attached file. Mutually exclusive with
     * [`body`](https://playwright.dev/docs/api/class-testinfo#test-info-attach-option-body).
     */
    path?: string;
  }): Promise<void>;

  /**
   * Marks the currently running test as "should fail". Playwright Test runs this test and ensures that it is actually
   * failing. This is useful for documentation purposes to acknowledge that some functionality is broken until it is
   * fixed. This is similar to
   * [test.fail([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fail).
   */
  fail(): void;

  /**
   * Conditionally mark the currently running test as "should fail" with an optional description. This is similar to
   * [test.fail([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fail).
   * @param condition Test is marked as "should fail" when the condition is `true`.
   * @param description Optional description that will be reflected in a test report.
   */
  fail(condition: boolean, description?: string): void;

  /**
   * Mark a test as "fixme", with the intention to fix it. Test is immediately aborted. This is similar to
   * [test.fixme([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fixme).
   */
  fixme(): void;

  /**
// … truncated — the full declaration is in node_modules/playwright/types/test.d.ts

TestType

Playwright Test provides a test function to declare tests and expect function to write assertions.

import { test, expect } from '@playwright/test'

test('basic test', async ({ page }) => {
  await page.goto('https://playwright.dev/')
  const name = await page.innerText('.navbar__title')
  expect(name).toBe('Playwright')
})
interface TestType<TestArgs extends {}, WorkerArgs extends {}> {
  /**
   * Declares a test.
   * - `test(title, body)`
   * - `test(title, details, body)`
   *
   * **Usage**
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('basic test', async ({ page }) => {
   *   await page.goto('https://playwright.dev/');
   *   // ...
   * });
   * ```
   *
   * **Tags**
   *
   * You can tag tests by providing additional test details. Alternatively, you can include tags in the test title. Note
   * that each tag must start with `@` symbol.
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('basic test', {
   *   tag: '@smoke',
   * }, async ({ page }) => {
   *   await page.goto('https://playwright.dev/');
   *   // ...
   * });
   *
   * test('another test @smoke', async ({ page }) => {
   *   await page.goto('https://playwright.dev/');
   *   // ...
   * });
   * ```
   *
   * Test tags are displayed in the test report, and are available to a custom reporter via `TestCase.tags` property.
   *
   * You can also filter tests by their tags during test execution:
   * - in the [command line](https://playwright.dev/docs/test-cli#all-options);
   * - in the config with [testConfig.grep](https://playwright.dev/docs/api/class-testconfig#test-config-grep) and
   *   [testProject.grep](https://playwright.dev/docs/api/class-testproject#test-project-grep);
   *
   * Learn more about [tagging](https://playwright.dev/docs/test-annotations#tag-tests).
   *
   * **Annotations**
   *
   * You can annotate tests by providing additional test details.
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('basic test', {
   *   annotation: {
   *     type: 'issue',
   *     description: 'https://github.com/microsoft/playwright/issues/23180',
   *   },
   * }, async ({ page }) => {
   *   await page.goto('https://playwright.dev/');
   *   // ...
   * });
   * ```
   *
   * Test annotations are displayed in the test report, and are available to a custom reporter via
   * `TestCase.annotations` property.
   *
   * You can also add annotations during runtime by manipulating
   * [testInfo.annotations](https://playwright.dev/docs/api/class-testinfo#test-info-annotations).
   *
   * Learn more about [test annotations](https://playwright.dev/docs/test-annotations).
   *
   * **Locks**
   *
   * You can declare named locks to prevent specific tests from running at the same time, while all other tests continue
   * to run in parallel. Tests that share a lock name never run concurrently, even when they are declared in different
   * files or belong to different [projects](https://playwright.dev/docs/test-projects). This is useful when a few tests access a shared
   * resource that does not support concurrent access.
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('update user settings', {
   *   lock: 'user-settings',
   * }, async ({ page }) => {
   *   // This test never runs concurrently with other tests
   *   // that declare the 'user-settings' lock.
   * });
   * ```
   *
   * Learn more about [test locks](https://playwright.dev/docs/test-parallel#test-locks).
   * @param title Test title.
   * @param details Additional test details.
   * @param body Test body that takes one or two arguments: an object with fixtures and optional
   * [TestInfo](https://playwright.dev/docs/api/class-testinfo).
   */
  (title: string, body: TestBody<TestArgs & WorkerArgs>): void;
  /**
   * Declares a test.
   * - `test(title, body)`
   * - `test(title, details, body)`
   *
   * **Usage**
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('basic test', async ({ page }) => {
   *   await page.goto('https://playwright.dev/');
   *   // ...
   * });
   * ```
   *
   * **Tags**
   *
   * You can tag tests by providing additional test details. Alternatively, you can include tags in the test title. Note
   * that each tag must start with `@` symbol.
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('basic test', {
   *   tag: '@smoke',
   * }, async ({ page }) => {
   *   await page.goto('https://playwright.dev/');
   *   // ...
   * });
   *
   * test('another test @smoke', async ({ page }) => {
   *   await page.goto('https://playwright.dev/');
   *   // ...
   * });
   * ```
   *
   * Test tags are displayed in the test report, and are available to a custom reporter via `TestCase.tags` property.
   *
   * You can also filter tests by their tags during test execution:
   * - in the [command line](https://playwright.dev/docs/test-cli#all-options);
   * - in the config with [testConfig.grep](https://playwright.dev/docs/api/class-testconfig#test-config-grep) and
   *   [testProject.grep](https://playwright.dev/docs/api/class-testproject#test-project-grep);
   *
   * Learn more about [tagging](https://playwright.dev/docs/test-annotations#tag-tests).
   *
   * **Annotations**
   *
   * You can annotate tests by providing additional test details.
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('basic test', {
   *   annotation: {
   *     type: 'issue',
   *     description: 'https://github.com/microsoft/playwright/issues/23180',
   *   },
   * }, async ({ page }) => {
   *   await page.goto('https://playwright.dev/');
   *   // ...
   * });
   * ```
   *
   * Test annotations are displayed in the test report, and are available to a custom reporter via
   * `TestCase.annotations` property.
   *
   * You can also add annotations during runtime by manipulating
   * [testInfo.annotations](https://playwright.dev/docs/api/class-testinfo#test-info-annotations).
   *
   * Learn more about [test annotations](https://playwright.dev/docs/test-annotations).
   *
   * **Locks**
   *
   * You can declare named locks to prevent specific tests from running at the same time, while all other tests continue
   * to run in parallel. Tests that share a lock name never run concurrently, even when they are declared in different
   * files or belong to different [projects](https://playwright.dev/docs/test-projects). This is useful when a few tests access a shared
   * resource that does not support concurrent access.
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('update user settings', {
   *   lock: 'user-settings',
   * }, async ({ page }) => {
   *   // This test never runs concurrently with other tests
   *   // that declare the 'user-settings' lock.
   * });
   * ```
   *
   * Learn more about [test locks](https://playwright.dev/docs/test-parallel#test-locks).
   * @param title Test title.
   * @param details Additional test details.
   * @param body Test body that takes one or two arguments: an object with fixtures and optional
   * [TestInfo](https://playwright.dev/docs/api/class-testinfo).
   */
  (title: string, details: TestDetails, body: TestBody<TestArgs & WorkerArgs>): void;

  /**
   * Declares a focused test. If there are some focused tests or suites, all of them will be run but nothing else.
   * - `test.only(title, body)`
   * - `test.only(title, details, body)`
   *
   * **Usage**
   *
   * ```js
   * test.only('focus this test', async ({ page }) => {
   *   // Run only focused tests in the entire project.
   * });
   * ```
   *
   * @param title Test title.
   * @param details See [test.(call)(title[, details, body])](https://playwright.dev/docs/api/class-test#test-call) for test details
   * description.
   * @param body Test body that takes one or two arguments: an object with fixtures and optional
   * [TestInfo](https://playwright.dev/docs/api/class-testinfo).
   */
  only(title: string, body: TestBody<TestArgs & WorkerArgs>): void;
  /**
   * Declares a focused test. If there are some focused tests or suites, all of them will be run but nothing else.
   * - `test.only(title, body)`
   * - `test.only(title, details, body)`
   *
// … truncated — the full declaration is in node_modules/playwright/types/test.d.ts

PlaywrightWorkerOptions

Playwright Test provides many options to configure test environment, Browser, BrowserContext and more.

These options are usually provided in the configuration file through testConfig.use and testProject.use.

// playwright.config.ts
import { defineConfig } from '@playwright/test'
export default defineConfig({
  use: {
    headless: false,
    viewport: { width: 1280, height: 720 },
    ignoreHTTPSErrors: true,
    video: 'on-first-retry',
  },
})

Alternatively, with test.use(options) you can override some options for a file.

// example.spec.ts
import { test, expect } from '@playwright/test'

// Run tests in this file with portrait-like viewport.
test.use({ viewport: { width: 600, height: 900 } })

test('my portrait test', async ({ page }) => {
  // ...
})
interface PlaywrightWorkerOptions {
  /**
   * Name of the browser that runs tests. Defaults to `'chromium'`. Most of the time you should set `browserName` in
   * your [TestConfig](https://playwright.dev/docs/api/class-testconfig):
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig, devices } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     browserName: 'firefox',
   *   },
   * });
   * ```
   *
   */
  browserName: BrowserName;
  defaultBrowserType: BrowserName;
  /**
   * Whether to run browser in headless mode. More details for
   * [Chromium](https://developers.google.com/web/updates/2017/04/headless-chrome) and
   * [Firefox](https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/). Defaults to `true`.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     headless: false
   *   },
   * });
   * ```
   *
   */
  headless: boolean;
  /**
   * Browser distribution channel.
   *
   * Use "chromium" to [opt in to new headless mode](https://playwright.dev/docs/browsers#chromium-new-headless-mode).
   *
   * Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or
   * "msedge-canary" to use branded [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge).
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   projects: [
   *     {
   *       name: 'Microsoft Edge',
   *       use: {
   *         ...devices['Desktop Edge'],
   *         channel: 'msedge'
   *       },
   *     },
   *   ]
   * });
   * ```
   *
   */
  channel: BrowserChannel | undefined;
  /**
   * Options used to launch the browser, as passed to
   * [browserType.launch([options])](https://playwright.dev/docs/api/class-browsertype#browser-type-launch). Specific
   * options [testOptions.headless](https://playwright.dev/docs/api/class-testoptions#test-options-headless) and
   * [testOptions.channel](https://playwright.dev/docs/api/class-testoptions#test-options-channel) take priority over
   * this.
   *
   * **NOTE** Use custom browser args at your own risk, as some of them may break Playwright functionality.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   projects: [
   *     {
   *       name: 'chromium',
   *       use: {
   *         ...devices['Desktop Chrome'],
   *         launchOptions: {
   *           args: ['--start-maximized']
   *         }
   *       }
   *     }
   *   ]
   * });
   * ```
   *
   */
  launchOptions: Omit<LaunchOptions, 'tracesDir'>;
  /**
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     connectOptions: {
   *       wsEndpoint: 'ws://localhost:5678',
   *     },
   *   },
   * });
   * ```
   *
   * When connect options are specified, default
   * [fixtures.browser](https://playwright.dev/docs/api/class-fixtures#fixtures-browser),
   * [fixtures.context](https://playwright.dev/docs/api/class-fixtures#fixtures-context) and
   * [fixtures.page](https://playwright.dev/docs/api/class-fixtures#fixtures-page) use the remote browser instead of
   * launching a browser locally, and any launch options like
   * [testOptions.headless](https://playwright.dev/docs/api/class-testoptions#test-options-headless) or
   * [testOptions.channel](https://playwright.dev/docs/api/class-testoptions#test-options-channel) are ignored.
   */
  connectOptions: ConnectOptions | undefined;
  /**
   * **NOTE** This option trades test isolation for speed and is intended for component tests that drive a story gallery. Leave
   * it unset for end-to-end tests - a fresh browser context per test is one of the core guarantees of Playwright Test.
   *
   * **Experimental.** When set to `true`, all tests in a worker process run in a single browser context that is reused
   * between tests, instead of getting a brand new context per test. Defaults to `false`.
   *
   * Between tests, Playwright resets the state that component tests typically touch: it clears cookies, cache, local
   * storage and IndexedDB of visited origins, unregisters service workers, closes extra pages, removes routes, bindings
   * and init scripts, and re-applies the configured storage state, viewport and emulation options.
   *
   * This reset is best-effort, not a guarantee of isolation. State that is **not** reset includes:
   * - Permissions granted with
   *   [browserContext.grantPermissions(permissions[, options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-grant-permissions)
   *   during a test.
   * - Runtime changes made through
   *   [browserContext.setGeolocation(geolocation)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-geolocation),
   *   [browserContext.setOffline(offline)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-offline)
   *   and
   *   [browserContext.setExtraHTTPHeaders(headers)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-extra-http-headers).
   * - Browsing history, `window.name` and any browser-process-wide state.
   *
   * Additional restrictions:
   * - The option is ignored when
   *   [testOptions.video](https://playwright.dev/docs/api/class-testoptions#test-options-video) recording is enabled.
   * - Only a few context options may differ between consecutive tests: `colorScheme`, `forcedColors`,
   *   `reducedMotion`, `contrast`, `screen`, `userAgent`, `viewport` and `testIdAttribute`. Changing any other option
   *   in [test.use(options)](https://playwright.dev/docs/api/class-test#test-use), for example `locale` or
   *   `storageState`, silently forces a fresh context and negates the speedup.
   * - Do not combine with
   *   [testOptions.connectOptions](https://playwright.dev/docs/api/class-testoptions#test-options-connect-options)
   *   pointing multiple workers at a shared browser - workers would compete for the single reusable context.
   * - `recordHar` in
   *   [testOptions.contextOptions](https://playwright.dev/docs/api/class-testoptions#test-options-context-options) is
   *   not supported and produces no HAR file.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   projects: [
   *     {
   *       name: 'components',
   *       testDir: './tests/components',
   *       use: { reuseContext: true },
   *     },
   *   ],
   * });
   * ```
   *
   */
  reuseContext: boolean;
  /**
   * Whether to automatically capture a screenshot after each test. Defaults to `'off'`.
   * - `'off'`: Do not capture screenshots.
   * - `'on'`: Capture screenshot after each test.
   * - `'only-on-failure'`: Capture screenshot after each test failure.
   * - `'on-first-failure'`: Capture screenshot after each test's first failure.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     screenshot: 'only-on-failure',
   *   },
   * });
   * ```
   *
   * Learn more about [automatic screenshots](https://playwright.dev/docs/test-use-options#recording-options).
   */
  screenshot: ScreenshotMode | { mode: ScreenshotMode } & Pick<PageScreenshotOptions, 'fullPage' | 'omitBackground'>;
  /**
   * Whether to record trace for each test. Defaults to `'off'`. The initial run of a test is the "first run";
   * subsequent runs caused by [retries](https://playwright.dev/docs/test-retries) are "retries".
// … truncated — the full declaration is in node_modules/playwright/types/test.d.ts

PlaywrightTestOptions

Playwright Test provides many options to configure test environment, Browser, BrowserContext and more.

These options are usually provided in the configuration file through testConfig.use and testProject.use.

// playwright.config.ts
import { defineConfig } from '@playwright/test'
export default defineConfig({
  use: {
    headless: false,
    viewport: { width: 1280, height: 720 },
    ignoreHTTPSErrors: true,
    video: 'on-first-retry',
  },
})

Alternatively, with test.use(options) you can override some options for a file.

// example.spec.ts
import { test, expect } from '@playwright/test'

// Run tests in this file with portrait-like viewport.
test.use({ viewport: { width: 600, height: 900 } })

test('my portrait test', async ({ page }) => {
  // ...
})
interface PlaywrightTestOptions {
  /**
   * Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     acceptDownloads: false,
   *   },
   * });
   * ```
   *
   */
  acceptDownloads: boolean;
  /**
   * Toggles bypassing page's Content-Security-Policy. Defaults to `false`.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     bypassCSP: true,
   *   }
   * });
   * ```
   *
   */
  bypassCSP: boolean;
  /**
   * Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme)
   * media feature, supported values are `'light'` and `'dark'`. See
   * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details.
   * Passing `null` resets emulation to system defaults. Defaults to `'light'`.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     colorScheme: 'dark',
   *   },
   * });
   * ```
   *
   */
  colorScheme: ColorScheme;
  /**
   * Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. See
   * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details.
   * Passing `null` resets emulation to system defaults. Defaults to `'no-preference'`.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     contrast: 'more',
   *   },
   * });
   * ```
   *
   */
  contrast: Contrast;
  /**
   * TLS Client Authentication allows the server to request a client certificate and verify it.
   *
   * **Details**
   *
   * An array of client certificates to be used. Each certificate object must have either both `certPath` and `keyPath`,
   * a single `pfxPath`, or their corresponding direct value equivalents (`cert` and `key`, or `pfx`). Optionally,
   * `passphrase` property should be provided if the certificate is encrypted. The `origin` property should be provided
   * with an exact match to the request origin that the certificate is valid for.
   *
   * Client certificate authentication is only active when at least one client certificate is provided. If you want to
   * reject all client certificates sent by the server, you need to provide a client certificate with an `origin` that
   * does not match any of the domains you plan to visit.
   *
   * **NOTE** When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it
   * work by replacing `localhost` with `local.playwright`.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     clientCertificates: [{
   *       origin: 'https://example.com',
   *       certPath: './cert.pem',
   *       keyPath: './key.pem',
   *       passphrase: 'mysecretpassword',
   *     }],
   *   },
   * });
   * ```
   *
   */
  clientCertificates: ClientCertificate[] | undefined;
  /**
   * Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
   * [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     viewport: { width: 2560, height: 1440 },
   *     deviceScaleFactor: 2,
   *   },
   * });
   * ```
   *
   */
  deviceScaleFactor: number | undefined;
  /**
   * An object containing additional HTTP headers to be sent with every request. Defaults to none.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     extraHTTPHeaders: {
   *       'X-My-Header': 'value',
   *     },
   *   },
   * });
   * ```
   *
   */
  extraHTTPHeaders: ExtraHTTPHeaders | undefined;
  /**
   * Emulates `'forced-colors'` media feature, supported values are `'active'`, `'none'`. See
   * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details.
   * Passing `null` resets emulation to system defaults. Defaults to `'none'`.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     forcedColors: 'active',
   *   },
   * });
   * ```
   *
   */
  forcedColors: ForcedColors;
  /**
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     geolocation: { longitude: 12.492507, latitude: 41.889938 },
   *   },
   * });
   * ```
   *
   * Learn more about [geolocation](https://playwright.dev/docs/emulation#color-scheme-and-media).
   */
  geolocation: Geolocation | undefined;
  /**
   * Specifies if viewport supports touch events. Defaults to false. Learn more about
   * [mobile emulation](https://playwright.dev/docs/emulation#devices).
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     hasTouch: true
   *   },
   * });
   * ```
   *
   */
  hasTouch: boolean;
  /**
   * Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). If no
   * origin is specified, the username and password are sent to any servers upon unauthorized responses.
   *
   * Pass an array to use different credentials for different origins. The first entry that matches the request origin
   * is used, and entries with no origin match any request.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     httpCredentials: {
   *       username: 'user',
   *       password: 'pass',
   *     },
   *   },
   * });
   * ```
   *
   */
  httpCredentials: HTTPCredentials | HTTPCredentials[] | undefined;
  /**
   * Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     ignoreHTTPSErrors: true,
   *   },
   * });
   * ```
   *
   */
  ignoreHTTPSErrors: boolean;
  /**
   * Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device,
   * so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more
   * about [mobile emulation](https://playwright.dev/docs/emulation#ismobile).
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
   *   use: {
   *     isMobile: false,
   *   },
   * });
   * ```
   *
   */
  isMobile: boolean;
  /**
   * Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about
   * [disabling JavaScript](https://playwright.dev/docs/emulation#javascript-enabled).
   *
   * **Usage**
   *
   * ```js
   * // playwright.config.ts
   * import { defineConfig } from '@playwright/test';
   *
   * export default defineConfig({
// … truncated — the full declaration is in node_modules/playwright/types/test.d.ts

PlaywrightWorkerArgs

Playwright Test is based on the concept of the test fixtures. Test fixtures are used to establish environment for each test, giving the test everything it needs and nothing else.

Playwright Test looks at each test declaration, analyses the set of fixtures the test needs and prepares those fixtures specifically for the test. Values prepared by the fixtures are merged into a single object that is available to the test, hooks, annotations and other fixtures as a first parameter.

import { test, expect } from '@playwright/test'

test('basic test', async ({ page }) => {
  // ...
})

Given the test above, Playwright Test will set up the page fixture before running the test, and tear it down after the test has finished. page fixture provides a Page object that is available to the test.

Playwright Test comes with builtin fixtures listed below, and you can add your own fixtures as well. Playwright Test also [provides options]TestOptions to configure fixtures.browser, fixtures.context and fixtures.page.

interface PlaywrightWorkerArgs {
  playwright: typeof import('playwright-core')
  /**
   * [Browser](https://playwright.dev/docs/api/class-browser) instance is shared between all tests in the
   * [same worker](https://playwright.dev/docs/test-parallel) - this makes testing efficient. However, each test runs in an isolated
   * [BrowserContext](https://playwright.dev/docs/api/class-browsercontext)  and gets a fresh environment.
   *
   * Learn how to [configure browser](https://playwright.dev/docs/test-configuration) and see
   * [available options][TestOptions](https://playwright.dev/docs/api/class-testoptions).
   *
   * **Usage**
   *
   * ```js
   * test.beforeAll(async ({ browser }) => {
   *   const page = await browser.newPage();
   *   // ...
   * });
   * ```
   *
   */
  browser: Browser
}

PlaywrightTestArgs

Playwright Test is based on the concept of the test fixtures. Test fixtures are used to establish environment for each test, giving the test everything it needs and nothing else.

Playwright Test looks at each test declaration, analyses the set of fixtures the test needs and prepares those fixtures specifically for the test. Values prepared by the fixtures are merged into a single object that is available to the test, hooks, annotations and other fixtures as a first parameter.

import { test, expect } from '@playwright/test'

test('basic test', async ({ page }) => {
  // ...
})

Given the test above, Playwright Test will set up the page fixture before running the test, and tear it down after the test has finished. page fixture provides a Page object that is available to the test.

Playwright Test comes with builtin fixtures listed below, and you can add your own fixtures as well. Playwright Test also [provides options]TestOptions to configure fixtures.browser, fixtures.context and fixtures.page.

interface PlaywrightTestArgs {
  /**
   * Isolated [BrowserContext](https://playwright.dev/docs/api/class-browsercontext) instance, created for each test.
   * Since contexts are isolated between each other, every test gets a fresh environment, even when multiple tests run
   * in a single [Browser](https://playwright.dev/docs/api/class-browser) for maximum efficiency.
   *
   * Learn how to [configure context](https://playwright.dev/docs/test-configuration) and see
   * [available options][TestOptions](https://playwright.dev/docs/api/class-testoptions).
   *
   * Default [fixtures.page](https://playwright.dev/docs/api/class-fixtures#fixtures-page) belongs to this context.
   *
   * **Usage**
   *
   * ```js
   * test('example test', async ({ page, context }) => {
   *   await context.route('*external.com/*', route => route.abort());
   *   // ...
   * });
   * ```
   *
   */
  context: BrowserContext
  /**
   * Isolated [Page](https://playwright.dev/docs/api/class-page) instance, created for each test. Pages are isolated
   * between tests due to [fixtures.context](https://playwright.dev/docs/api/class-fixtures#fixtures-context) isolation.
   *
   * This is the most common fixture used in a test.
   *
   * **Usage**
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('basic test', async ({ page }) => {
   *   await page.goto('/signin');
   *   await page.getByLabel('User Name').fill('user');
   *   await page.getByLabel('Password').fill('password');
   *   await page.getByText('Sign in').click();
   *   // ...
   * });
   * ```
   *
   */
  page: Page
  /**
   * Isolated [APIRequestContext](https://playwright.dev/docs/api/class-apirequestcontext) instance for each test.
   *
   * **Usage**
   *
   * ```js
   * import { test, expect } from '@playwright/test';
   *
   * test('basic test', async ({ request }) => {
   *   await request.post('/signin', {
   *     data: {
   *       username: 'user',
   *       password: 'password'
   *     }
   *   });
   *   // ...
   * });
   * ```
   *
   */
  request: APIRequestContext
  /**
   * Mounts a component story and returns a [Locator](https://playwright.dev/docs/api/class-locator) pointing to the
   * root element the story was rendered into. Scope your queries from the returned locator:
   * `component.getByRole('button')`, not `page.getByRole('button')`.
   *
   * A **story** is a small wrapper component that embeds the component under test in one specific scenario: hard-coded
   * props, mock data, providers, recorded callbacks. Stories are rendered by a **gallery** page that you implement and
   * serve at [testOptions.baseURL](https://playwright.dev/docs/api/class-testoptions#test-options-base-url). The
   * gallery exposes `window.mount(params)` and `window.unmount()` functions that render a story into its root element.
   * Each call to [fixtures.mount(storyId[, props])](https://playwright.dev/docs/api/class-fixtures#fixtures-mount)
   * navigates to [testOptions.baseURL](https://playwright.dev/docs/api/class-testoptions#test-options-base-url) and
   * calls `window.mount()` with the story id and props, so tests are fully isolated from each other.
   *
   * **Usage**
   *
   * ```js
   * test('click should expand', async ({ mount }) => {
   *   const component = await mount('components/Expandable/Stateful');
   *   await component.getByRole('button').click();
   *   await expect(component.getByTestId('expanded')).toHaveValue('true');
   * });
   * ```
   *
   * Pass the story type as a template argument to type-check the props:
   *
   * ```js
   * import type { WithTitle } from './Button.story';
   *
   * test('renders the title', async ({ mount }) => {
   *   const component = await mount<typeof WithTitle>('Button/WithTitle', { title: 'Hello' });
   *   await expect(component).toContainText('Hello');
   * });
   * ```
   *
   * The returned locator is augmented with two methods:
   * - `update(props)` - re-renders the same story with new props without remounting, preserving component state;
   * - `unmount()` - unmounts the story.
   * @param storyId Identifier of the story to mount, as resolved by the gallery page. Conventionally, the story file path plus the
   * exported story name, for example `'components/Button/Primary'`.
   * @param props Optional plain, serializable props passed to the story.
   */
  mount: <Story = never, Id extends StoryId = StoryId>(
    storyId: Id,
    props?: MountProps<Story, Id>,
  ) => Promise<
    Locator & { update(props?: MountProps<Story, Id>): Promise<void>; unmount(): Promise<void> }
  >
}

ConsoleErrorEntry

One captured browser error.

interface ConsoleErrorEntry {
  type: 'pageerror' | 'console.error'
  text: string
  location?: string
}

ConsoleGuardFixtures

The fixture object withConsoleGuard adds to a test.

interface ConsoleGuardFixtures {
  consoleGuard: void
}

TextMatch

Serialised text matcher (a RegExp cannot cross the wire).

interface TextMatch {
  s?: string
  exact?: boolean
  ignoreCase?: boolean
  re?: { source: string; flags: string }
}

RuntimeCall

The page-side dispatcher's request shape.

interface RuntimeCall {
  fn: string
  args: unknown[]
}

Types

TestFixture

type TestFixture<R, Args extends {}> = (
  args: Args,
  use: (r: R) => Promise<void>,
  testInfo: TestInfo,
) => any

WorkerFixture

type WorkerFixture<R, Args extends {}> = (
  args: Args,
  use: (r: R) => Promise<void>,
  workerInfo: WorkerInfo,
) => any

Fixtures

type Fixtures<T extends {} = {}, W extends {} = {}, PT extends {} = {}, PW extends {} = {}> = {
  [K in keyof PW]?:
    | WorkerFixtureValue<PW[K], W & PW>
    | [
        WorkerFixtureValue<PW[K], W & PW>,
        { scope: 'worker'; timeout?: number | undefined; title?: string; box?: boolean | 'self' },
      ]
} & {
  [K in keyof PT]?:
    | TestFixtureValue<PT[K], T & W & PT & PW>
    | [
        TestFixtureValue<PT[K], T & W & PT & PW>,
        { scope: 'test'; timeout?: number | undefined; title?: string; box?: boolean | 'self' },
      ]
} & {
  [K in Exclude<keyof W, keyof PW | keyof PT>]?: [
    WorkerFixtureValue<W[K], W & PW>,
    {
      scope: 'worker'
      auto?: boolean
      option?: boolean
      timeout?: number | undefined
      title?: string
      box?: boolean | 'self'
    },
  ]
} & {
  [K in Exclude<keyof T, keyof PW | keyof PT>]?:
    | TestFixtureValue<T[K], T & W & PT & PW>
    | [
        TestFixtureValue<T[K], T & W & PT & PW>,
        {
          scope?: 'test'
          auto?: boolean
          option?: boolean
          timeout?: number | undefined
          title?: string
          box?: boolean | 'self'
        },
      ]
}

PlaywrightTestProject

type PlaywrightTestProject<TestArgs = {}, WorkerArgs = {}> = Project<
  PlaywrightTestOptions & CustomProperties<TestArgs>,
  PlaywrightWorkerOptions & CustomProperties<WorkerArgs>
>

PlaywrightTestConfig

type PlaywrightTestConfig<TestArgs = {}, WorkerArgs = {}> = Config<
  PlaywrightTestOptions & CustomProperties<TestArgs>,
  PlaywrightWorkerOptions & CustomProperties<WorkerArgs>
>

Expect

type Expect<ExtendedMatchers = {}> = {
  <T = unknown>(
    actual: T,
    messageOrOptions?: string | { message?: string },
  ): MakeMatchers<void, T, ExtendedMatchers>
  soft: Expect<ExtendedMatchers>
  poll: <T = unknown>(
    actual: () => T | Promise<T>,
    messageOrOptions?: string | { message?: string; timeout?: number; intervals?: number[] },
  ) => PollMatchers<Promise<void>, T, ExtendedMatchers>
  extend<
    MoreMatchers extends Record<
      string,
      (
        this: ExpectMatcherState,
        receiver: any,
        ...args: any[]
      ) => MatcherReturnType | Promise<MatcherReturnType>
    >,
  >(
    matchers: MoreMatchers,
  ): Expect<ExtendedMatchers & MoreMatchers>
  configure: (configuration: {
    message?: string
    timeout?: number
    soft?: boolean
  }) => Expect<ExtendedMatchers>
  getState(): unknown
  not: Omit<AsymmetricMatchers, 'any' | 'anything'>
} & AsymmetricMatchers

LocatorStep

One step of a locator chain.

type LocatorStep =
  | { k: 'css'; sel: string }
  /** A Playwright selector string, parsed in the page (`>>`, `text=`, `xpath=`, `nth=`, `:has-text()`...). */
  | { k: 'raw'; sel: string }
  | { k: 'text'; m: TextMatch }
  | { k: 'xpath'; expr: string }
  | {
      k: 'role'
      role: string
      name?: TextMatch
      level?: number
      checked?: boolean
      pressed?: boolean
      expanded?: boolean
      selected?: boolean
      disabled?: boolean
      includeHidden?: boolean
    }
  | { k: 'label'; m: TextMatch }
  | { k: 'placeholder'; m: TextMatch }
  | { k: 'testid'; attr: string; m: TextMatch }
  | { k: 'title'; m: TextMatch }
  | { k: 'alt'; m: TextMatch }
  | { k: 'nth'; i: number }
  | { k: 'visible' }
  | {
      k: 'filter'
      hasText?: TextMatch
      hasNotText?: TextMatch
      has?: LocatorStep[]
      hasNot?: LocatorStep[]
    }

Classes

E2ELocatorImpl

A Playwright-shaped Locator: a lazy chain of steps resolved inside the page on every action.

class LocatorImpl {
  readonly [E2E_LOCATOR] = true
  constructor(
    private readonly owner: PageImpl,
    readonly steps: LocatorStep[],
  ) {}

  /** A new locator with more steps (locators are immutable). */
  private extend(step: LocatorStep | LocatorStep[]): LocatorImpl {
    return new LocatorImpl(this.owner, this.steps.concat(step))
  }
  /** Steps for a selector string (parsed in the page) or another locator. */
  private stepsOf(sel: string | LocatorImpl): LocatorStep[] {
    // A string is a Playwright selector (CSS, `text=`, `xpath=`, `>>`...); the page parses it.
    return typeof sel === 'string' ? [{ k: 'raw', sel }] : sel.steps
  }
  /** The filter steps a `filter()` / `locator()` options object adds. */
  private filterStep(opts?: {
    hasText?: string | RegExp
    hasNotText?: string | RegExp
    has?: LocatorImpl
    hasNot?: LocatorImpl
    visible?: boolean
  }): LocatorStep[] {
    const out: LocatorStep[] = []
    if (
      opts &&
      (opts.hasText !== undefined || opts.hasNotText !== undefined || opts.has || opts.hasNot)
    ) {
      out.push({
        k: 'filter',
        hasText: opts.hasText !== undefined ? toMatch(opts.hasText) : undefined,
        hasNotText: opts.hasNotText !== undefined ? toMatch(opts.hasNotText) : undefined,
        has: opts.has ? opts.has.steps : undefined,
        hasNot: opts.hasNot ? opts.hasNot.steps : undefined,
      })
    }
    if (opts?.visible) out.push({ k: 'visible' })
    return out
  }

  // ---- building ----
  /** Playwright's `locator()`: narrow to descendants matching a selector, with optional `hasText` / `has` filters. */
  locator(
    sel: string | LocatorImpl,
    opts?: {
      hasText?: string | RegExp
      hasNotText?: string | RegExp
      has?: LocatorImpl
      hasNot?: LocatorImpl
    },
  ): LocatorImpl {
    return this.extend(this.stepsOf(sel).concat(this.filterStep(opts)))
  }
  /** Playwright's `getByRole()`: by ARIA role, with accessible-name, heading-level and state options. */
  getByRole(role: string, opts: Dict = {}): LocatorImpl {
    return this.extend({
      k: 'role',
      role,
      name:
        opts.name !== undefined
          ? toMatch(opts.name as string | RegExp, { exact: opts.exact as boolean | undefined })
          : undefined,
      level: opts.level as number | undefined,
      checked: opts.checked as boolean | undefined,
      pressed: opts.pressed as boolean | undefined,
      expanded: opts.expanded as boolean | undefined,
      selected: opts.selected as boolean | undefined,
      disabled: opts.disabled as boolean | undefined,
      includeHidden: opts.includeHidden as boolean | undefined,
    })
  }
  /** Playwright's `getByText()`: the smallest elements whose text matches. */
  getByText(text: string | RegExp, opts?: { exact?: boolean }): LocatorImpl {
    return this.extend({ k: 'text', m: toMatch(text, { exact: opts?.exact }) })
  }
  /** Playwright's `getByLabel()`: form controls by their label text (also `aria-label`). */
  getByLabel(text: string | RegExp, opts?: { exact?: boolean }): LocatorImpl {
    return this.extend({ k: 'label', m: toMatch(text, { exact: opts?.exact }) })
  }
  /** Playwright's `getByPlaceholder()`. */
  getByPlaceholder(text: string | RegExp, opts?: { exact?: boolean }): LocatorImpl {
    return this.extend({ k: 'placeholder', m: toMatch(text, { exact: opts?.exact }) })
  }
  /** Playwright's `getByTitle()`. */
  getByTitle(text: string | RegExp, opts?: { exact?: boolean }): LocatorImpl {
    return this.extend({ k: 'title', m: toMatch(text, { exact: opts?.exact }) })
  }
  /** Playwright's `getByAltText()`. */
  getByAltText(text: string | RegExp, opts?: { exact?: boolean }): LocatorImpl {
    return this.extend({ k: 'alt', m: toMatch(text, { exact: opts?.exact }) })
  }
  /** Playwright's `getByTestId()` on the configured test-id attribute (default `data-testid`). */
  getByTestId(id: string | RegExp): LocatorImpl {
    return this.extend({ k: 'testid', attr: this.owner.testIdAttribute, m: toFull(id) })
  }
  /** Playwright's `locator.filter()`: keep matches by text, by a descendant locator, or by visibility. */
  filter(
    opts: {
      hasText?: string | RegExp
      hasNotText?: string | RegExp
      has?: LocatorImpl
      hasNot?: LocatorImpl
      visible?: boolean
    } = {},
  ): LocatorImpl {
    return this.extend(this.filterStep(opts))
  }
  /** The first match. */
  first(): LocatorImpl {
    return this.extend({ k: 'nth', i: 0 })
  }
  /** The last match. */
  last(): LocatorImpl {
    return this.extend({ k: 'nth', i: -1 })
  }
  /** The i-th match (a negative index counts from the end). */
  nth(i: number): LocatorImpl {
    return this.extend({ k: 'nth', i })
  }
  /** The page this belongs to (null for a console message over the preview). */
  page(): Page {
    return this.owner.asPage()
  }
  /** The locator chain, Playwright-style, for error messages. */
  toString(): string {
    return describeSteps(this.steps)
  }
  /** The locator chain as text. */
  describe(): string {
    return describeSteps(this.steps)
  }

  // ---- runtime calls ----
  /** Run one runtime call for this locator. */
  private async call(fn: string, args: unknown[], timeout?: number): Promise<Dict> {
    return this.owner.rt(fn, args, timeout)
  }
  /** Turn a runtime reply into a value, throwing strict-mode, timeout or plain errors. */
  private unwrap(res: Dict, what: string): unknown {
    if (res.strict) throw new E2EStrictModeError(this.describe(), Number(res.count))
    if (res.ok === false) {
      const message = `${what}: ${String(res.error ?? 'failed')}`
      throw res.timeout
        ? new E2ETimeoutError(`${message} (timeout ${this.owner.defaultTimeout}ms)`)
        : new Error(message)
    }
    return res.value
  }
  /** Run a single-target action with auto-wait and actionability checks. */
  private async act(action: string, opts: Dict = {}): Promise<void> {
    const timeout = (opts.timeout as number | undefined) ?? this.owner.defaultTimeout
    const res = await this.call(
      'act',
      [this.steps, action, { ...opts, timeout: undefined }],
      timeout,
    )
    this.unwrap(res, `locator.${action}()`)
  }
  /** Read one value from the single strict target. */
  private async read(what: string, args: unknown[] = [], timeout?: number): Promise<unknown> {
    return this.unwrap(
      await this.call('read', [this.steps, what, args], timeout ?? this.owner.defaultTimeout),
      `locator.${what}()`,
    )
  }

  // ---- actions ----
  /** Playwright's `click()`: waits until the element is visible, enabled and not covered, then clicks its centre (or `position`). */
  click(opts?: Dict): Promise<void> {
    return this.act('click', opts)
  }
  /** Playwright's `dblclick()`. */
  dblclick(opts?: Dict): Promise<void> {
    return this.act('dblclick', opts)
  }
  /** Playwright's `hover()`: moves the pointer over the element. */
  hover(opts?: Dict): Promise<void> {
    return this.act('hover', opts)
  }
  /** Playwright's `tap()`: touch events followed by a click. */
  tap(opts?: Dict): Promise<void> {
    return this.act('tap', opts)
  }
  /** Playwright's `fill()`: focuses, replaces the value through the native setter and fires `input` / `change`. */
  fill(value: string, opts?: Dict): Promise<void> {
    return this.act('fill', { ...opts, value })
  }
  /** Playwright's `clear()`: fills with an empty string. */
  clear(opts?: Dict): Promise<void> {
    return this.act('clear', opts)
  }
  /** Playwright's `type()`: presses each character in turn (or, on a console message, its level). */
  type(text: string, opts?: Dict): Promise<void> {
    return this.act('type', { ...opts, text })
  }
  /** Playwright's `pressSequentially()`: presses each character in turn. */
  pressSequentially(text: string, opts?: Dict): Promise<void> {
    return this.act('type', { ...opts, text })
  }
  /** Playwright's `press()`: a key or chord (`Enter`, `Control+a`); Enter submits a form. */
// … truncated — the full declaration is in node_modules/@molecule/app-e2e-fixtures-default/dist/page.d.ts

E2EPageImpl

A Playwright-shaped Page over an E2ETransport; createEvaluatePage wraps it in a Proxy.

class PageImpl {
  readonly [E2E_PAGE] = true
  defaultTimeout: number
  navigationTimeout: number
  readonly testIdAttribute: string
  private viewport: E2EViewport | null
  /**
   * The size the SPEC asked for, as opposed to `viewport`, the size the
   * host last reported. Re-asserted after every navigation so a phone-width
   * measurement is never silently taken at the host's own width.
   */
  private requestedViewport: E2EViewport | null = null
  private closed = false
  private proxy!: Page
  private readonly listeners = new Map<string, Set<Listener>>()
  private readonly warned = new Set<string>()
  private readonly unsubscribe: Array<() => void> = []
  readonly mouse: Dict
  readonly keyboard: Dict
  readonly touchscreen: Dict
  readonly request: Dict

  constructor(
    private readonly transport: E2ETransport,
    private readonly options: E2EPageOptions,
  ) {
    this.defaultTimeout = options.timeout ?? 10_000
    this.navigationTimeout = options.navigationTimeout ?? 15_000
    this.testIdAttribute =
      (options as { testIdAttribute?: string }).testIdAttribute ?? 'data-testid'
    this.viewport = options.viewport ?? null
    this.unsubscribe.push(
      transport.on('console', (payload) =>
        this.emit('console', new ConsoleMessageImpl(payload as E2EConsolePayload)),
      ),
      transport.on('pageerror', (payload) => {
        const p = payload as E2EErrorPayload
        const err = new Error(p.message)
        if (p.stack) err.stack = p.stack
        this.emit('pageerror', err)
      }),
      transport.on('close', () => {
        this.closed = true
        this.emit('close', this.proxy)
      }),
    )
    const mouseCall = (action: string, x: number, y: number, opts: Dict = {}): Promise<void> =>
      this.rt('mouse', [action, x, y, opts])
        .then((r) => this.check(r, `mouse.${action}()`))
        .then(() => undefined)
    this.mouse = {
      click: (x: number, y: number, opts?: Dict) => mouseCall('click', x, y, opts),
      dblclick: (x: number, y: number, opts?: Dict) => mouseCall('dblclick', x, y, opts),
      move: (x: number, y: number) => mouseCall('move', x, y),
      down: () => mouseCall('down', 0, 0),
      up: () => mouseCall('up', 0, 0),
      wheel: (dx: number, dy: number) => mouseCall('wheel', dx, dy),
    }
    const keyCall = (action: string, arg: string): Promise<void> =>
      this.rt('keyboard', [action, arg])
        .then((r) => this.check(r, `keyboard.${action}()`))
        .then(() => undefined)
    this.keyboard = {
      press: (key: string) => keyCall('press', key),
      type: (text: string) => keyCall('type', text),
      insertText: (text: string) => keyCall('insertText', text),
      down: (key: string) => keyCall('down', key),
      up: (key: string) => keyCall('up', key),
    }
    this.touchscreen = { tap: (x: number, y: number) => mouseCall('click', x, y) }
    const fetchCall = async (
      method: string,
      url: string,
      opts: Dict = {},
    ): Promise<APIResponse> => {
      const res = await this.rt(
        'fetch',
        [url, { ...opts, method }],
        opts.timeout as number | undefined,
      )
      this.check(res, `request.${method.toLowerCase()}()`)
      return new ResponseImpl(
        res.value as ConstructorParameters<typeof ResponseImpl>[0],
      ) as unknown as APIResponse
    }
    this.request = {
      get: (url: string, opts?: Dict) => fetchCall('GET', url, opts),
      post: (url: string, opts?: Dict) => fetchCall('POST', url, opts),
      put: (url: string, opts?: Dict) => fetchCall('PUT', url, opts),
      patch: (url: string, opts?: Dict) => fetchCall('PATCH', url, opts),
      delete: (url: string, opts?: Dict) => fetchCall('DELETE', url, opts),
      head: (url: string, opts?: Dict) => fetchCall('HEAD', url, opts),
      fetch: (url: string, opts?: Dict) => fetchCall(String(opts?.method ?? 'GET'), url, opts),
      dispose: async () => undefined,
      storageState: () => {
        throw new E2EUnsupportedError(
          'request.storageState()',
          'Read storage with page.evaluate(() => ({ ...localStorage })).',
          this.bondName,
        )
      },
    }
  }

  /** The bond's name, for error messages. */
  get bondName(): string {
    return this.options.bondName ?? 'this e2e bond'
  }
  /** The branded Page proxy. */
  asPage(): Page {
    return this.proxy
  }
  /** Called once by `createEvaluatePage` with the proxy that wraps this instance. */
  attachProxy(proxy: Page): void {
    this.proxy = proxy
  }
  /** Fire the listeners of one event. */
  private emit(event: string, payload: unknown): void {
    for (const fn of this.listeners.get(event) ?? []) {
      try {
        fn(payload)
      } catch (error) {
        console.error(`[app-e2e] listener for '${event}' threw`, error)
      }
    }
  }
  /** Playwright's `check()`: clicks until checked (or, on the page, throws on a failed runtime reply). */
  private check(res: Dict, what: string): Dict {
    if (res.ok === false) {
      const message = `${what}: ${String(res.error ?? 'failed')}`
      throw res.timeout ? new E2ETimeoutError(message) : new Error(message)
    }
    return res
  }

  /**
   * Run a runtime call inside the page, installing the runtime on a fresh
   * document. The page answers every call at once; a call that has to WAIT
   * (an element not there yet, not visible, covered) comes back `retry` and
   * is asked again from here, on this process's clock — so a preview in a
   * background tab, whose own timers are throttled, waits no longer than one
   * in front.
   */
  async rt(fn: string, args: unknown[], timeout?: number): Promise<Dict> {
    if (this.closed) throw new Error('Target page, context or browser has been closed')
    const budget = (timeout ?? this.defaultTimeout) + 2_000
    const deadline = Date.now() + (timeout ?? this.defaultTimeout)
    const once = async (): Promise<Dict> => {
      let res = (await this.transport.evaluate(
        CALL_SOURCE,
        { fn, args },
        { timeout: budget },
      )) as Dict | null
      if (res && (res as Dict).__needInstall) {
        await this.transport.evaluate(RUNTIME_SOURCE, undefined, { timeout: 5_000 })
        res = (await this.transport.evaluate(
          CALL_SOURCE,
          { fn, args },
          { timeout: budget },
        )) as Dict | null
      }
      return (res ?? {}) as Dict
    }
    let res = await once()
    while (res.retry) {
      if (Date.now() >= deadline) return { ok: false, error: res.error, timeout: true }
      await new Promise((r) => setTimeout(r, RETRY_INTERVAL_MS))
      res = await once()
    }
    return res
  }

  // ---- navigation ----
  /** Resolve a spec URL against `baseURL` when it is relative. */
  private resolveUrl(url: string): string {
    if (/^[a-z]+:/i.test(url)) return url
    const base = this.options.baseURL
    if (base) return new URL(url, base.endsWith('/') ? base : base + '/').href
    return url
  }
  /** Playwright's `page.goto()`: navigate and wait for the new document to load. */
  async goto(url: string, opts: { timeout?: number } = {}): Promise<null> {
    await this.transport.navigate('goto', this.resolveUrl(url), {
      timeout: opts.timeout ?? this.navigationTimeout,
    })
    await this.reassertViewport()
    this.emit('load', this.proxy)
    return null
  }
  /** Playwright's `page.reload()`. */
  async reload(opts: { timeout?: number } = {}): Promise<null> {
    await this.transport.navigate('reload', undefined, {
      timeout: opts.timeout ?? this.navigationTimeout,
    })
    await this.reassertViewport()
    this.emit('load', this.proxy)
    return null
  }
  /** Playwright's `page.goBack()`. */
  async goBack(opts: { timeout?: number } = {}): Promise<null> {
    await this.transport.navigate('back', undefined, {
      timeout: opts.timeout ?? this.navigationTimeout,
    })
    await this.reassertViewport()
    return null
  }
  /** Playwright's `page.goForward()`. */
// … truncated — the full declaration is in node_modules/@molecule/app-e2e-fixtures-default/dist/page.d.ts

Functions

defineConfig(config)

Defines Playwright config

function defineConfig(config: PlaywrightTestConfig<{}, {}>): PlaywrightTestConfig<{}, {}>

withConsoleGuard(base)

Extend a Playwright test with the auto-attached console-error guard.

To intentionally let a known error through (rare — almost always a smell that should be fixed in the app), use test.info().annotations.push({ type: 'allow-console-error', description: 'why' }) inside the test body BEFORE the error fires. The description is matched against the error text as a regular expression; if it is not a valid regex it is matched as a plain substring instead. An annotation with no description allows every error — always provide one.

function withConsoleGuard(
  base: BaseTest,
): TestType<
  PlaywrightTestArgs & PlaywrightTestOptions & ConsoleGuardFixtures,
  PlaywrightWorkerArgs & PlaywrightWorkerOptions
>

textMatch(value, opts?)

function textMatch(
  value: string | RegExp,
  opts?: { exact?: boolean; ignoreCase?: boolean },
): TextMatch

textMatchFull(value, opts?)

Full-text match (expect's toHaveText): a string must equal the whole text; a RegExp tests it.

function textMatchFull(value: string | RegExp, opts?: { ignoreCase?: boolean }): TextMatch

createEvaluatePage(transport, options?)

Build a Playwright-shaped Page over a transport. Bonds call this from connect(); the returned object carries the documented subset and throws an E2EUnsupportedError naming the alternative for the rest.

function createEvaluatePage(transport: E2ETransport, options?: E2EPageOptions): Promise<Page>

isE2ELocator(value)

Whether a value is a locator built by createEvaluatePage.

function isE2ELocator(value: unknown): boolean

isE2EPage(value)

Whether a value is a page built by createEvaluatePage.

function isE2EPage(value: unknown): boolean

installE2ERuntime()

Install the runtime. Runs INSIDE the page — see the module doc; the body must stay self-contained.

The runtime never waits: every call is ONE attempt, and a call that would have to wait (an element not there yet, not visible yet, covered) answers { retry: true, error } so the DRIVER polls with its own clock. A page in a background tab has its timers throttled to once a second (a minute, after a while) — a setTimeout in here would stretch every auto-wait by that much, while the WebSocket messages that carry the calls are delivered on time.

function installE2ERuntime(): { version: number }

Constants

devices

const devices: Devices

chromium

This object can be used to launch or connect to Chromium, returning instances of Browser.

const chromium: BrowserType<{}>

firefox

This object can be used to launch or connect to Firefox, returning instances of Browser.

const firefox: BrowserType<{}>

request

Exposes API that can be used for the Web API testing.

const request: APIRequest

webkit

This object can be used to launch or connect to WebKit, returning instances of Browser.

const webkit: BrowserType<{}>

ALWAYS_IGNORE

Substrings that are always ignored — browser noise that doesn't reflect app bugs.

const ALWAYS_IGNORE: readonly RegExp[]

expect

Playwright's expect, plus polling matchers for pages and locators built over the preview. expect(value), expect.soft, expect.poll, expect.configure and the asymmetric matchers behave exactly as in Playwright.

const expect: Expect<{}>

E2E_LOCATOR

Brand on locators created here (the expect wrapper routes on it).

const E2E_LOCATOR: typeof E2E_LOCATOR

E2E_PAGE

Brand on pages created here.

const E2E_PAGE: typeof E2E_PAGE

E2E_RUNTIME_VERSION

Bumped when the in-page runtime's protocol changes; a page holding an older one is re-installed.

const E2E_RUNTIME_VERSION: 2

e2eProviderName

The provider name this process resolved at import time (see resolveE2EProviderName).

const e2eProviderName: E2EProviderName

test

Drop-in for import { test } from '@playwright/test'.

With the playwright provider this IS Playwright's test — real browsers, traces, videos, every fixture untouched. With any other provider (the live preview inside a molecule sandbox) the page fixture comes from the bonded provider's connect(), honouring the project's baseURL, viewport, actionTimeout and navigationTimeout options, and no browser is launched. Either way the console-error guard is attached to every test.

const test: TestType<
  PlaywrightTestArgs & PlaywrightTestOptions & ConsoleGuardFixtures,
  PlaywrightWorkerArgs & PlaywrightWorkerOptions
>

Injection Notes

Requirements

Peer dependencies:

  • @molecule/app-bond ^1.0.1
  • @molecule/app-e2e ^1.0.0
  • @playwright/test ^1.50.0

Runtime Dependencies

  • @molecule/app-bond

  • @molecule/app-e2e

  • @playwright/test

  • What works over the preview (the @molecule/app-e2e-preview bond): page.goto/reload/goBack/goForward/url/title/content, page.evaluate/$eval/$$eval, page.locator and every getBy* (role with name/level/checked/pressed/expanded/selected, text, label, placeholder, title, alt text, test id), first/last/nth/filter/count/all, click/dblclick/hover/tap/fill/clear/type/press/check/uncheck/setChecked/ selectOption/focus/blur/dispatchEvent/scrollIntoViewIfNeeded, textContent/innerText/innerHTML/inputValue/getAttribute/isVisible/isHidden/ isEnabled/isDisabled/isEditable/isChecked/boundingBox/evaluate/evaluateAll/ waitFor, page.setViewportSize/viewportSize, page.mouse.*, page.keyboard.*, page.request.get/post/put/patch/delete/fetch (runs fetch inside the page, cookies included), waitForSelector/waitForURL/ waitForFunction/waitForLoadState/waitForTimeout, page.on('console' | 'pageerror' | 'dialog' | 'close'), and expect(locator) with toBeVisible/toBeHidden/toBeAttached/toHaveCount/toHaveText/toContainText/ toHaveAttribute/toHaveClass/toContainClass/toHaveCSS/toHaveValue/toHaveId/ toBeChecked/toBeEnabled/toBeDisabled/toBeEditable/toBeEmpty/toBeFocused/ toBeInViewport/toHaveAccessibleName/toHaveRole (+ .not, expect.soft, expect.configure), expect(page).toHaveTitle/toHaveURL.

  • The escape hatch is page.evaluate(). Anything the list above does not cover — a computed style, a scroll position, matchMedia, a fetch — is one evaluate away; the function runs inside the real page and returns JSON.

  • Not available over the preview, and the method THROWS naming the alternative: screenshots and toHaveScreenshot (assert layout with boundingBox() and computed styles instead), page.route/waitForResponse/ waitForRequest (read the response with page.request or fetch in evaluate), element handles ($, $$, elementHandle — use locators), setInputFiles, dragTo, iframes inside the preview, emulateMedia, addInitScript/exposeFunction, context.cookies/storageState (read document.cookie/localStorage in evaluate). The playwright bond supports all of them.

  • Viewport. page.setViewportSize asks the IDE to resize the preview frame and throws if the host did not (a preview opened in a plain tab keeps the tab's width). Test phone layouts at 390×844 this way. The size is RE-ASSERTED after every goto/reload/goBack/goForward, because the viewport belongs to the host's frame and not to the document: without that, a navigation could land at the host's own width while the page kept reporting the phone size, and every measurement after it was a desktop number wearing a phone label. The re-assert WARNS instead of throwing (a navigation must not fail over a frame size), so read page.viewportSize() when a measurement has to be provably at the width you asked for.

  • Events. page.on('response')/'request' never fire over the preview (a one-time warning says so); 'console' and 'pageerror' do, so the console-error guard works there too.

  • Over the preview, the person's browser is the renderer. If no tab shows the preview, connect() fails within seconds — once per run, not once per test — with a message naming the cause and the alternative (MOL_E2E_PROVIDER=playwright, a real browser that needs no tab; every sandbox ships one). Keep the IDE tab open (the IDE holds a screen wake lock while a build runs) or open the preview URL in any other tab — any connected viewer will do.

  • createEvaluatePage() is how a bond that can only run code inside a page (an E2ETransport) gets the whole Playwright-shaped page; the preview bond uses it, and so can any future one.

  • @playwright/test is a peer dependency: it supplies the runner (npx playwright test), expect for plain values, and the Page types. It never downloads browsers on install; only the playwright bond needs npx playwright install.