diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 242a970ab8..b914cdff78 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,5 @@ # Contributing - - [How to Contribute](#how-to-contribute) * [Getting Code](#getting-code) * [Code reviews](#code-reviews) @@ -13,7 +12,6 @@ * [Public API Coverage](#public-api-coverage) - [Contributor License Agreement](#contributor-license-agreement) * [Code of Conduct](#code-of-conduct) - ## How to Contribute diff --git a/docs-src/README.md b/docs-src/README.md new file mode 100644 index 0000000000..e6273e14bd --- /dev/null +++ b/docs-src/README.md @@ -0,0 +1,53 @@ +--- +id: README +title: "Documentation" +--- + +### Capabilities + +Playwright is a library to automate [Chromium](https://www.chromium.org/Home), [Firefox](https://www.mozilla.org/en-US/firefox/new/) and [WebKit](https://webkit.org/) with a single API. Playwright is built to enable cross-browser web automation that is **ever-green**, **capable**, **reliable** and **fast**. + +* Ever-green browser engines +* Headless execution +* Scenarios that span multiple pages, domains and iframes +* Auto-wait for elements to be ready before executing actions (like click, fill) +* Reliable signals instead of timeouts (like network response, popup, navigation) +* Intercept network activity for stubbing and mocking network requests +* Emulate mobile devices, geolocation, permissions +* Support for web components via shadow-piercing selectors +* Native input events for mouse and keyboard +* Upload and download files + +### Table of contents + +1. Introduction + - [Why Playwright?](./why-playwright.md) + - [Get started](./intro.md) + - [Core concepts](./core-concepts.md) + - [Debugging](./debug.md) + - [Supported languages](./languages.md) +1. Guides + - [Selectors](./selectors.md) + - [Input](./input.md) + - [Emulation](./emulation.md) + - [Network](./network.md) + - [Assertions](./assertions.md) + - [Verification](./verification.md) + - [Navigations](./navigations.md) + - [Multi-page scenarios](./multi-pages.md) +1. Tutorials + - [Authentication](./auth.md) + - [Page object models](./pom.md) +1. Integrations + - [Test runners](./test-runners.md) + - [Docker](./docker/README.md) + - [Continuous integration](./ci.md) +1. Reference + - [API Reference](./api.md) + - [Actionability](./actionability.md) + - [Advanced installation](./installation.md) + - [Extensibility](./extensibility.md) +1. Get help + - [Slack community](https://join.slack.com/t/playwright/shared_invite/enQtOTEyMTUxMzgxMjIwLThjMDUxZmIyNTRiMTJjNjIyMzdmZDA3MTQxZWUwZTFjZjQwNGYxZGM5MzRmNzZlMWI5ZWUyOTkzMjE5Njg1NDg) + - [Stack Overflow](https://stackoverflow.com/tags/playwright) + - [GitHub](https://github.com/microsoft/playwright/issues) diff --git a/docs-src/actionability.md b/docs-src/actionability.md index 6e7e133019..d20b7f6c34 100644 --- a/docs-src/actionability.md +++ b/docs-src/actionability.md @@ -1,4 +1,7 @@ -# Actionability +--- +id: actionability +title: "Actionability" +--- Playwright does a range of actionability checks on the elements before performing certain actions. These checks ensure that action behaves as expected, for example Playwright does not click on a disabled button. diff --git a/docs-src/api-body.md b/docs-src/api-body.md index 0087e2b98a..e7f039aef4 100644 --- a/docs-src/api-body.md +++ b/docs-src/api-body.md @@ -71,7 +71,7 @@ This object can be used to launch or connect to Firefox, returning instances of ## property: Playwright.selectors - type: <[Selectors]> -Selectors can be used to install custom selector engines. See [Working with selectors](#working-with-selectors) for more information. +Selectors can be used to install custom selector engines. See [Working with selectors](./selectors.md#working-with-selectors) for more information. ## property: Playwright.webkit - type: <[BrowserType]> @@ -2476,7 +2476,7 @@ console.log(text); Returns the ElementHandle pointing to the frame element. The method finds an element matching the specified selector within the frame. See [Working with -selectors](#working-with-selectors) for more details. If no elements match the selector, returns `null`. +selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, returns `null`. ### param: Frame.$.selector = %%-query-selector-%% @@ -2486,7 +2486,7 @@ selectors](#working-with-selectors) for more details. If no elements match the s Returns the ElementHandles pointing to the frame elements. The method finds all elements matching the specified selector within the frame. See [Working with -selectors](#working-with-selectors) for more details. If no elements match the selector, returns empty array. +selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, returns empty array. ### param: Frame.$$.selector = %%-query-selector-%% @@ -2496,7 +2496,7 @@ selectors](#working-with-selectors) for more details. If no elements match the s Returns the return value of [`param: pageFunction`] The method finds an element matching the specified selector within the frame and passes it as a first argument to -[`param: pageFunction`]. See [Working with selectors](#working-with-selectors) for more details. If no elements match +[`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, the method throws an error. If [`param: pageFunction`] returns a [Promise], then `frame.$eval` would wait for the promise to resolve and return @@ -2528,7 +2528,7 @@ Optional argument to pass to [`param: pageFunction`] Returns the return value of [`param: pageFunction`] The method finds all elements matching the specified selector within the frame and passes an array of matched elements -as a first argument to [`param: pageFunction`]. See [Working with selectors](#working-with-selectors) for more +as a first argument to [`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) for more details. If [`param: pageFunction`] returns a [Promise], then `frame.$$eval` would wait for the promise to resolve and return @@ -3326,7 +3326,7 @@ ElementHandle instances can be used as an argument in [`method: Page.$eval`] and - returns: <[null]|[ElementHandle]> The method finds an element matching the specified selector in the `ElementHandle`'s subtree. See [Working with -selectors](#working-with-selectors) for more details. If no elements match the selector, returns `null`. +selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, returns `null`. ### param: ElementHandle.$.selector = %%-query-selector-%% @@ -3334,7 +3334,7 @@ selectors](#working-with-selectors) for more details. If no elements match the s - returns: <[Array]<[ElementHandle]>> The method finds all elements matching the specified selector in the `ElementHandle`s subtree. See [Working with -selectors](#working-with-selectors) for more details. If no elements match the selector, returns empty array. +selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, returns empty array. ### param: ElementHandle.$$.selector = %%-query-selector-%% @@ -3344,7 +3344,7 @@ selectors](#working-with-selectors) for more details. If no elements match the s Returns the return value of [`param: pageFunction`] The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a first -argument to [`param: pageFunction`]. See [Working with selectors](#working-with-selectors) for more details. If no +argument to [`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector, the method throws an error. If [`param: pageFunction`] returns a [Promise], then `frame.$eval` would wait for the promise to resolve and return @@ -3376,7 +3376,7 @@ Optional argument to pass to [`param: pageFunction`] Returns the return value of [`param: pageFunction`] The method finds all elements matching the specified selector in the `ElementHandle`'s subtree and passes an array of -matched elements as a first argument to [`param: pageFunction`]. See [Working with selectors](#working-with-selectors) +matched elements as a first argument to [`param: pageFunction`]. See [Working with selectors](./selectors.md#working-with-selectors) for more details. If [`param: pageFunction`] returns a [Promise], then `frame.$$eval` would wait for the promise to resolve and return @@ -4650,7 +4650,7 @@ Contains the URL of the response. # class: Selectors -Selectors can be used to install custom selector engines. See [Working with selectors](#working-with-selectors) for more +Selectors can be used to install custom selector engines. See [Working with selectors](./selectors.md#working-with-selectors) for more information. ## async method: Selectors.register diff --git a/docs-src/api-footer.md b/docs-src/api-footer.md deleted file mode 100644 index 111d0d4207..0000000000 --- a/docs-src/api-footer.md +++ /dev/null @@ -1,157 +0,0 @@ -### EvaluationArgument - -Playwright evaluation methods like [`method: Page.evaluate`] take a single optional argument. This argument can be a mix of [Serializable] values and [JSHandle] or [ElementHandle] instances. Handles are automatically converted to the value they represent. - -See examples for various scenarios: - -```js -// A primitive value. -await page.evaluate(num => num, 42); - -// An array. -await page.evaluate(array => array.length, [1, 2, 3]); - -// An object. -await page.evaluate(object => object.foo, { foo: 'bar' }); - -// A single handle. -const button = await page.$('button'); -await page.evaluate(button => button.textContent, button); - -// Alternative notation using elementHandle.evaluate. -await button.evaluate((button, from) => button.textContent.substring(from), 5); - -// Object with multiple handles. -const button1 = await page.$('.button1'); -const button2 = await page.$('.button2'); -await page.evaluate( - o => o.button1.textContent + o.button2.textContent, - { button1, button2 }); - -// Obejct destructuring works. Note that property names must match -// between the destructured object and the argument. -// Also note the required parenthesis. -await page.evaluate( - ({ button1, button2 }) => button1.textContent + button2.textContent, - { button1, button2 }); - -// Array works as well. Arbitrary names can be used for destructuring. -// Note the required parenthesis. -await page.evaluate( - ([b1, b2]) => b1.textContent + b2.textContent, - [button1, button2]); - -// Any non-cyclic mix of serializables and handles works. -await page.evaluate( - x => x.button1.textContent + x.list[0].textContent + String(x.foo), - { button1, list: [button2], foo: null }); -``` - -### Environment Variables - -> **NOTE** [playwright-core](https://www.npmjs.com/package/playwright-core) **does not** respect environment variables. - -Playwright looks for certain [environment variables](https://en.wikipedia.org/wiki/Environment_variable) to aid its operations. -If Playwright doesn't find them in the environment, a lowercased variant of these variables will be used from the [npm config](https://docs.npmjs.com/cli/config). - -- `PLAYWRIGHT_DOWNLOAD_HOST` - overwrite URL prefix that is used to download browsers. Note: this includes protocol and might even include path prefix. By default, Playwright uses `https://storage.googleapis.com` to download Chromium and `https://playwright.azureedge.net` to download Webkit & Firefox. You can also use browser-specific download hosts that superceed the `PLAYWRIGHT_DOWNLOAD_HOST` variable: - - `PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST` - host to specify Chromium downloads - - `PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST` - host to specify Firefox downloads - - `PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST` - host to specify Webkit downloads -- `PLAYWRIGHT_BROWSERS_PATH` - specify a shared directory that playwright will use to download browsers and to look for browsers when launching browser instances. -- `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` - set to non-empty value to skip browser downloads altogether. - -```sh -# Linux/macOS -# Install browsers to the shared location. -$ PLAYWRIGHT_BROWSERS_PATH=$HOME/playwright-browsers npm install --save-dev playwright -# Use shared location to find browsers. -$ PLAYWRIGHT_BROWSERS_PATH=$HOME/playwright-browsers node playwright-script.js - -# Windows -# Install browsers to the shared location. -$ set PLAYWRIGHT_BROWSERS_PATH=%USERPROFILE%\playwright-browsers -$ npm install --save-dev playwright -# Use shared location to find browsers. -$ set PLAYWRIGHT_BROWSERS_PATH=%USERPROFILE%\playwright-browsers -$ node playwright-script.js -``` - - -### Working with selectors - -Selector describes an element in the page. It can be used to obtain `ElementHandle` (see [`method: Page.$`] for example) or shortcut element operations to avoid intermediate handle (see [`method: Page.click`] for example). - -Selector has the following format: `engine=body [>> engine=body]*`. Here `engine` is one of the supported [selector engines](./selectors.md) (e.g. `css` or `xpath`), and `body` is a selector body in the format of the particular engine. When multiple `engine=body` clauses are present (separated by `>>`), next one is queried relative to the previous one's result. - -Playwright also supports the following CSS extensions: -* `:text("string")` - Matches elements that contain specific text node. Learn more about [text selector](./selectors.md#css-extension-text). -* `:visible` - Matches only visible elements. Learn more about [visible selector](./selectors.md#css-extension-visible). -* `:light(selector)` - Matches in the light DOM only as opposite to piercing open shadow roots. Learn more about [shadow piercing](./selectors.md#shadow-piercing). - - -For convenience, selectors in the wrong format are heuristically converted to the right format: -- selector starting with `//` or `..` is assumed to be `xpath=selector`; -- selector starting and ending with a quote (either `"` or `'`) is assumed to be `text=selector`; -- otherwise selector is assumed to be `css=selector`. - -```js -// queries 'div' css selector -const handle = await page.$('css=div'); - -// queries '//html/body/div' xpath selector -const handle = await page.$('xpath=//html/body/div'); - -// queries '"foo"' text selector -const handle = await page.$('text="foo"'); - -// queries 'span' css selector inside the result of '//html/body/div' xpath selector -const handle = await page.$('xpath=//html/body/div >> css=span'); - -// converted to 'css=div' -const handle = await page.$('div'); - -// converted to 'xpath=//html/body/div' -const handle = await page.$('//html/body/div'); - -// converted to 'text="foo"' -const handle = await page.$('"foo"'); - -// queries '../span' xpath selector starting with the result of 'div' css selector -const handle = await page.$('div >> ../span'); - -// queries 'span' css selector inside the div handle -const handle = await divHandle.$('css=span'); -``` - -### Working with Chrome Extensions - -Playwright can be used for testing Chrome Extensions. - -> **NOTE** Extensions in Chrome / Chromium currently only work in non-headless mode. - -The following is code for getting a handle to the [background page](https://developer.chrome.com/extensions/background_pages) of an extension whose source is located in `./my-extension`: -```js -const { chromium } = require('playwright'); - -(async () => { - const pathToExtension = require('path').join(__dirname, 'my-extension'); - const userDataDir = '/tmp/test-user-data-dir'; - const browserContext = await chromium.launchPersistentContext(userDataDir,{ - headless: false, - args: [ - `--disable-extensions-except=${pathToExtension}`, - `--load-extension=${pathToExtension}` - ] - }); - const backgroundPage = browserContext.backgroundPages()[0]; - // Test the background page as you would any other page. - await browserContext.close(); -})(); -``` - -> **NOTE** It is not yet possible to test extension popups or content scripts. - - diff --git a/docs-src/api-header.md b/docs-src/api-header.md deleted file mode 100644 index bb1fe1acbc..0000000000 --- a/docs-src/api-header.md +++ /dev/null @@ -1,7 +0,0 @@ - -# Playwright API Tip-Of-Tree - -##### Table of Contents - - - diff --git a/docs-src/api-params.md b/docs-src/api-params.md index f198d8884c..c88a192b8c 100644 --- a/docs-src/api-params.md +++ b/docs-src/api-params.md @@ -45,7 +45,7 @@ Whether to bypass the [actionability](./actionability.md) checks. Defaults to `f - `selector` <[string]> A selector to search for element. If there are multiple elements satisfying the selector, the first will be used. See -[working with selectors](#working-with-selectors) for more details. +[working with selectors](./selectors.md#working-with-selectors) for more details. ## input-position - `position` <[Object]> @@ -85,7 +85,7 @@ defaults to 1. See [UIEvent.detail]. ## query-selector - `selector` <[string]> -A selector to query for. See [working with selectors](#working-with-selectors) for more details. +A selector to query for. See [working with selectors](./selectors.md#working-with-selectors) for more details. ## wait-for-selector-state - `state` <"attached"|"detached"|"visible"|"hidden"> diff --git a/docs-src/assertions.md b/docs-src/assertions.md index 7c0bf3b4c5..79a36b0a32 100644 --- a/docs-src/assertions.md +++ b/docs-src/assertions.md @@ -1,14 +1,14 @@ -# Assertions +--- +id: assertions +title: "Assertions" +--- The Playwright API can be used to read element contents and properties for test assertions. These values are fetched from the browser page and asserted in Node.js. The examples in this guide use the built-in [`assert` module](https://nodejs.org/api/assert.html), but they can be used with any assertion library (like [Expect](https://www.npmjs.com/package/expect) or [Chai](https://www.npmjs.com/package/chai)). See [Test runners](test-runners.md) for more info. - - - -
+ ## Common patterns diff --git a/docs-src/auth.md b/docs-src/auth.md index 5e1100398a..c77c0221c7 100644 --- a/docs-src/auth.md +++ b/docs-src/auth.md @@ -1,4 +1,8 @@ -# Authentication +--- +id: auth +title: "Authentication" +--- + Playwright can be used to automate scenarios that require authentication. Tests written with Playwright execute in isolated clean-slate environments called @@ -11,8 +15,7 @@ login in every context and speeds up test execution. app UI). For [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) use [`browser.newContext`](./network.md#http-authentication). - - + ## Automate logging in diff --git a/docs-src/ci.md b/docs-src/ci.md index b9a0f681cc..436fdf24dc 100644 --- a/docs-src/ci.md +++ b/docs-src/ci.md @@ -1,10 +1,12 @@ -# Continuous Integration +--- +id: ci +title: "Continuous Integration" +--- Playwright tests can be executed in CI environments. We have created sample configurations for common CI providers. - - + ## Introduction diff --git a/docs-src/cli.md b/docs-src/cli.md index 33e64be1ad..bc02374335 100644 --- a/docs-src/cli.md +++ b/docs-src/cli.md @@ -1,9 +1,11 @@ -# Playwright CLI +--- +id: cli +title: "Command Line Interface" +--- Playwright comes with the command line tools that run via `npx` or as a part of the `npm` scripts. - - + ## Usage diff --git a/docs-src/core-concepts.md b/docs-src/core-concepts.md index fe95bf2d4e..c98735972a 100644 --- a/docs-src/core-concepts.md +++ b/docs-src/core-concepts.md @@ -1,4 +1,7 @@ -# Core concepts +--- +id: core-concepts +title: "Core concepts" +--- Playwright provides a set of APIs to automate Chromium, Firefox and WebKit browsers. By using the Playwright API, you can write JavaScript code to create @@ -8,8 +11,7 @@ Along with a test runner Playwright can be used to automate user interactions to validate and test web applications. The Playwright API enables this through the following primitives. - - +
@@ -245,10 +247,53 @@ const status = await page.evaluate(async () => { }); ``` -### Evaluation +## Evaluation Argument + +Playwright evaluation methods like [`method: Page.evaluate`] take a single optional argument. This argument can be a mix of [Serializable] values and [JSHandle] or [ElementHandle] instances. Handles are automatically converted to the value they represent. + +```js +// A primitive value. +await page.evaluate(num => num, 42); + +// An array. +await page.evaluate(array => array.length, [1, 2, 3]); + +// An object. +await page.evaluate(object => object.foo, { foo: 'bar' }); + +// A single handle. +const button = await page.$('button'); +await page.evaluate(button => button.textContent, button); + +// Alternative notation using elementHandle.evaluate. +await button.evaluate((button, from) => button.textContent.substring(from), 5); + +// Object with multiple handles. +const button1 = await page.$('.button1'); +const button2 = await page.$('.button2'); +await page.evaluate( + o => o.button1.textContent + o.button2.textContent, + { button1, button2 }); + +// Object destructuring works. Note that property names must match +// between the destructured object and the argument. +// Also note the required parenthesis. +await page.evaluate( + ({ button1, button2 }) => button1.textContent + button2.textContent, + { button1, button2 }); + +// Array works as well. Arbitrary names can be used for destructuring. +// Note the required parenthesis. +await page.evaluate( + ([b1, b2]) => b1.textContent + b2.textContent, + [button1, button2]); + +// Any non-cyclic mix of serializables and handles works. +await page.evaluate( + x => x.button1.textContent + x.list[0].textContent + String(x.foo), + { button1, list: [button2], foo: null }); +``` -Functions passed inside [`method: Page.evaluate`] can accept parameters. These parameters are -serialized and sent into your web page over the wire. You can pass primitive types, JSON-alike objects and remote object handles received from the page. Right: diff --git a/docs-src/debug.md b/docs-src/debug.md index 098947ed91..9e900e6aa8 100644 --- a/docs-src/debug.md +++ b/docs-src/debug.md @@ -1,11 +1,13 @@ -# Debugging tools +--- +id: debug +title: "Debugging tools" +--- Playwright scripts work with existing debugging tools, like Node.js debuggers and browser developer tools. Playwright also introduces new debugging features for browser automation. - - + ## Run in headful mode diff --git a/docs-src/emulation.md b/docs-src/emulation.md index cf9403f796..5f2bf49a24 100644 --- a/docs-src/emulation.md +++ b/docs-src/emulation.md @@ -1,4 +1,7 @@ -# Device and environment emulation +--- +id: emulation +title: "Device and environment emulation" +--- Playwright allows overriding various parameters of the device where the browser is running: - viewport size, device scale factor, touch support @@ -8,8 +11,7 @@ Playwright allows overriding various parameters of the device where the browser Most of these parameters are configured during the browser context construction, but some of them such as viewport size can be changed for individual pages. - - +
diff --git a/docs-src/extensibility.md b/docs-src/extensibility.md index b439fcd687..5372921381 100644 --- a/docs-src/extensibility.md +++ b/docs-src/extensibility.md @@ -1,7 +1,9 @@ -# Extensibility +--- +id: extensibility +title: "Extensibility" +--- - - + ## Custom selector engines diff --git a/docs-src/input.md b/docs-src/input.md index e2b4f51ac8..fcfd6278ac 100644 --- a/docs-src/input.md +++ b/docs-src/input.md @@ -1,9 +1,9 @@ -# Input +--- +id: input +title: "Input" +--- - - - -
+ ## Text input diff --git a/docs-src/installation.md b/docs-src/installation.md index 7aaa2320c3..1d647eb24a 100644 --- a/docs-src/installation.md +++ b/docs-src/installation.md @@ -1,9 +1,9 @@ -# Advanced installation +--- +id: installation +title: "Advanced installation" +--- - - - -
+ ## Managing browser binaries diff --git a/docs-src/intro.md b/docs-src/intro.md index 941b0b0dfc..7310bafeff 100644 --- a/docs-src/intro.md +++ b/docs-src/intro.md @@ -1,7 +1,9 @@ -# Getting Started +--- +id: intro +title: "Getting Started" +--- - - + ## Installation diff --git a/docs-src/languages.md b/docs-src/languages.md index 70942b8f21..a187c4224f 100644 --- a/docs-src/languages.md +++ b/docs-src/languages.md @@ -1,9 +1,11 @@ -# Supported languages +--- +id: languages +title: "Supported languages" +--- The Playwright API is available in multiple languages. - - + ## JavaScript and TypeScript diff --git a/docs-src/api-links.md b/docs-src/links.md similarity index 96% rename from docs-src/api-links.md rename to docs-src/links.md index 3a3cd3cf4b..74f2e36253 100644 --- a/docs-src/api-links.md +++ b/docs-src/links.md @@ -3,7 +3,7 @@ [ChildProcess]: https://nodejs.org/api/child_process.html "ChildProcess" [Element]: https://developer.mozilla.org/en-US/docs/Web/API/element "Element" [Error]: https://nodejs.org/api/errors.html#errors_class_error "Error" -[EvaluationArgument]: #evaluationargument "Evaluation Argument" +[Evaluation Argument]: ./core-concepts.md#evaluationargument "Evaluation Argument" [Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map "Map" [Object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object "Object" [Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise "Promise" diff --git a/docs-src/mobile.md b/docs-src/mobile.md index a14eb1a0d5..9ece9a1615 100644 --- a/docs-src/mobile.md +++ b/docs-src/mobile.md @@ -1,4 +1,9 @@ -# Experimental support for Chrome for Android +--- +id: mobile +title: "Experimental support for Chrome for Android" +--- + + You can try Playwright against Chrome for Android today. This support is experimental. Support for devices is tracked in the issue [#1122](https://github.com/microsoft/playwright/issues/1122). diff --git a/docs-src/multi-pages.md b/docs-src/multi-pages.md index 91f9db1ea8..b6375e7bb0 100644 --- a/docs-src/multi-pages.md +++ b/docs-src/multi-pages.md @@ -1,10 +1,12 @@ -# Multi-page scenarios +--- +id: multi-pages +title: "Multi-page scenarios" +--- Playwright can automate scenarios that span multiple browser contexts or multiple tabs in a browser window. - - + ## Multiple contexts diff --git a/docs-src/navigations.md b/docs-src/navigations.md index 98fd1b63f2..86f40b6b7d 100644 --- a/docs-src/navigations.md +++ b/docs-src/navigations.md @@ -1,9 +1,11 @@ -# Navigations +--- +id: navigations +title: "Navigations" +--- Playwright can navigate to URLs and handle navigations caused by page interactions. This guide covers common scenarios to wait for page navigations and loading to complete. - - + ## Navigation lifecycle Playwright splits the process of showing a new document in a page into **navigation** and **loading**. diff --git a/docs-src/network.md b/docs-src/network.md index 73ac24195a..8af4fe6487 100644 --- a/docs-src/network.md +++ b/docs-src/network.md @@ -1,11 +1,13 @@ -# Network +--- +id: network +title: "Network" +--- Playwright provides APIs to **monitor** and **modify** network traffic, both HTTP and HTTPS. Any requests that page does, including [XHRs](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) and [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) requests, can be tracked, modified and handled. - - +
diff --git a/docs-src/pom.md b/docs-src/pom.md index 8d4992e357..ce294f60ac 100644 --- a/docs-src/pom.md +++ b/docs-src/pom.md @@ -1,9 +1,12 @@ -# Page Object Models +--- +id: pom +title: "Page Object Models" +--- + Large test suites can be structured to optimize ease of authoring and maintenance. Page object models are one such approach to structure your test suite. - - + ## Introduction A page object represents a part of your web application. An e-commerce web diff --git a/docs-src/selectors.md b/docs-src/selectors.md index f0ff5349a4..5715d35042 100644 --- a/docs-src/selectors.md +++ b/docs-src/selectors.md @@ -1,9 +1,85 @@ -# Element selectors +--- +id: selectors +title: "Element selectors" +--- Selectors query elements on the web page for interactions, like [`method: Page.click`], and to obtain `ElementHandle` through [`method: Page.$`]. Built-in selectors auto-pierce [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM). - - + + +## Working with selectors + +Selector describes an element in the page. It can be used to obtain `ElementHandle` (see [`method: Page.$`] for example) or shortcut element operations to avoid intermediate handle (see [`method: Page.click`] for example). + +Selector has the following format: `engine=body [>> engine=body]*`. Here `engine` is one of the supported [selector engines](./selectors.md) (e.g. `css` or `xpath`), and `body` is a selector body in the format of the particular engine. When multiple `engine=body` clauses are present (separated by `>>`), next one is queried relative to the previous one's result. + +Playwright also supports the following CSS extensions: +* `:text("string")` - Matches elements that contain specific text node. Learn more about [text selector](./selectors.md#css-extension-text). +* `:visible` - Matches only visible elements. Learn more about [visible selector](./selectors.md#css-extension-visible). +* `:light(selector)` - Matches in the light DOM only as opposite to piercing open shadow roots. Learn more about [shadow piercing](./selectors.md#shadow-piercing). + + +For convenience, selectors in the wrong format are heuristically converted to the right format: +- selector starting with `//` or `..` is assumed to be `xpath=selector`; +- selector starting and ending with a quote (either `"` or `'`) is assumed to be `text=selector`; +- otherwise selector is assumed to be `css=selector`. + +```js +// queries 'div' css selector +const handle = await page.$('css=div'); + +// queries '//html/body/div' xpath selector +const handle = await page.$('xpath=//html/body/div'); + +// queries '"foo"' text selector +const handle = await page.$('text="foo"'); + +// queries 'span' css selector inside the result of '//html/body/div' xpath selector +const handle = await page.$('xpath=//html/body/div >> css=span'); + +// converted to 'css=div' +const handle = await page.$('div'); + +// converted to 'xpath=//html/body/div' +const handle = await page.$('//html/body/div'); + +// converted to 'text="foo"' +const handle = await page.$('"foo"'); + +// queries '../span' xpath selector starting with the result of 'div' css selector +const handle = await page.$('div >> ../span'); + +// queries 'span' css selector inside the div handle +const handle = await divHandle.$('css=span'); +``` + +### Working with Chrome Extensions + +Playwright can be used for testing Chrome Extensions. + +> **NOTE** Extensions in Chrome / Chromium currently only work in non-headless mode. + +The following is code for getting a handle to the [background page](https://developer.chrome.com/extensions/background_pages) of an extension whose source is located in `./my-extension`: +```js +const { chromium } = require('playwright'); + +(async () => { + const pathToExtension = require('path').join(__dirname, 'my-extension'); + const userDataDir = '/tmp/test-user-data-dir'; + const browserContext = await chromium.launchPersistentContext(userDataDir,{ + headless: false, + args: [ + `--disable-extensions-except=${pathToExtension}`, + `--load-extension=${pathToExtension}` + ] + }); + const backgroundPage = browserContext.backgroundPages()[0]; + // Test the background page as you would any other page. + await browserContext.close(); +})(); +``` ## Syntax Selectors are defined by selector engine name and selector body, `engine=body`. diff --git a/docs-src/showcase.md b/docs-src/showcase.md index fe2c4564fb..bf91c581e4 100644 --- a/docs-src/showcase.md +++ b/docs-src/showcase.md @@ -1,4 +1,7 @@ -# Community Showcase +--- +id: showcase +title: "Community Showcase" +--- ## Users diff --git a/docs-src/test-runners.md b/docs-src/test-runners.md index f1f6d10bc7..a1305e370c 100644 --- a/docs-src/test-runners.md +++ b/docs-src/test-runners.md @@ -1,13 +1,11 @@ -# Test Runners +--- +id: test-runners +title: "Test Runners" +--- With a few lines of code, you can hook up Playwright to your favorite JavaScript test runner. - - - -
- -
+ ## Jest / Jasmine diff --git a/docs-src/troubleshooting.md b/docs-src/troubleshooting.md index 40a53ae199..025b948000 100644 --- a/docs-src/troubleshooting.md +++ b/docs-src/troubleshooting.md @@ -1,7 +1,9 @@ -# Troubleshooting +--- +id: troubleshooting +title: "Troubleshooting" +--- - - + ## Browser dependencies diff --git a/docs-src/verification.md b/docs-src/verification.md index 172c59a34a..fbcf4e14f0 100644 --- a/docs-src/verification.md +++ b/docs-src/verification.md @@ -1,9 +1,9 @@ -# Verification +--- +id: verification +title: "Verification" +--- - - - -
+ ## Videos diff --git a/docs-src/why-playwright.md b/docs-src/why-playwright.md index 3a10ae0d4d..26cb7dbbba 100644 --- a/docs-src/why-playwright.md +++ b/docs-src/why-playwright.md @@ -1,9 +1,11 @@ -# Why Playwright? +--- +id: why-playwright +title: "Why Playwright?" +--- Playwright enables fast, reliable and capable automation across all modern browsers. This guide covers those key differentiators to help you decide on the right tool for your automated tests. - - + ## Support for all browsers * **Test on Chromium, Firefox and WebKit**. Playwright has full API coverage for all modern browsers, including Google Chrome and Microsoft Edge (with [Chromium](https://www.chromium.org/)), Apple Safari (with [WebKit](https://webkit.org/)) and Mozilla Firefox. diff --git a/docs/README.md b/docs/README.md index 7f3e657812..1599dcdd09 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,9 +1,11 @@ -# Documentation +--- +id: README +title: "Documentation" +--- ### Capabilities Playwright is a library to automate [Chromium](https://www.chromium.org/Home), [Firefox](https://www.mozilla.org/en-US/firefox/new/) and [WebKit](https://webkit.org/) with a single API. Playwright is built to enable cross-browser web automation that is **ever-green**, **capable**, **reliable** and **fast**. - * Ever-green browser engines * Headless execution * Scenarios that span multiple pages, domains and iframes @@ -16,36 +18,91 @@ Playwright is a library to automate [Chromium](https://www.chromium.org/Home), [ * Upload and download files ### Table of contents - 1. Introduction - - [Why Playwright?](./why-playwright.md) - - [Get started](./intro.md) - - [Core concepts](./core-concepts.md) - - [Debugging](./debug.md) - - [Supported languages](./languages.md) - - [Using Playwright CLI](./cli.md) + - [Why Playwright?](./why-playwright.md) + - [Get started](./intro.md) + - [Core concepts](./core-concepts.md) + - [Debugging](./debug.md) + - [Supported languages](./languages.md) 1. Guides - - [Selectors](./selectors.md) - - [Input](./input.md) - - [Emulation](./emulation.md) - - [Network](./network.md) - - [Assertions](./assertions.md) - - [Verification](./verification.md) - - [Navigations](./navigations.md) - - [Multi-page scenarios](./multi-pages.md) + - [Selectors](./selectors.md) + - [Input](./input.md) + - [Emulation](./emulation.md) + - [Network](./network.md) + - [Assertions](./assertions.md) + - [Verification](./verification.md) + - [Navigations](./navigations.md) + - [Multi-page scenarios](./multi-pages.md) 1. Tutorials - - [Authentication](./auth.md) - - [Page object models](./pom.md) + - [Authentication](./auth.md) + - [Page object models](./pom.md) 1. Integrations - - [Test runners](./test-runners.md) - - [Docker](./docker/README.md) - - [Continuous integration](./ci.md) + - [Test runners](./test-runners.md) + - [Docker](./docker/README.md) + - [Continuous integration](./ci.md) 1. Reference - - [API Reference](./api.md) - - [Actionability](./actionability.md) - - [Advanced installation](./installation.md) - - [Extensibility](./extensibility.md) + - [API Reference](./api.md) + - [Actionability](./actionability.md) + - [Advanced installation](./installation.md) + - [Extensibility](./extensibility.md) 1. Get help - - [Slack community](https://join.slack.com/t/playwright/shared_invite/enQtOTEyMTUxMzgxMjIwLThjMDUxZmIyNTRiMTJjNjIyMzdmZDA3MTQxZWUwZTFjZjQwNGYxZGM5MzRmNzZlMWI5ZWUyOTkzMjE5Njg1NDg) - - [Stack Overflow](https://stackoverflow.com/tags/playwright) - - [GitHub](https://github.com/microsoft/playwright/issues) + - [Slack community](https://join.slack.com/t/playwright/shared_invite/enQtOTEyMTUxMzgxMjIwLThjMDUxZmIyNTRiMTJjNjIyMzdmZDA3MTQxZWUwZTFjZjQwNGYxZGM5MzRmNzZlMWI5ZWUyOTkzMjE5Njg1NDg) + - [Stack Overflow](https://stackoverflow.com/tags/playwright) + - [GitHub](https://github.com/microsoft/playwright/issues) +[Playwright]: api/class-playwright.md "Playwright" +[Browser]: api/class-browser.md "Browser" +[BrowserContext]: api/class-browsercontext.md "BrowserContext" +[Page]: api/class-page.md "Page" +[Frame]: api/class-frame.md "Frame" +[ElementHandle]: api/class-elementhandle.md "ElementHandle" +[JSHandle]: api/class-jshandle.md "JSHandle" +[ConsoleMessage]: api/class-consolemessage.md "ConsoleMessage" +[Dialog]: api/class-dialog.md "Dialog" +[Download]: api/class-download.md "Download" +[Video]: api/class-video.md "Video" +[FileChooser]: api/class-filechooser.md "FileChooser" +[Keyboard]: api/class-keyboard.md "Keyboard" +[Mouse]: api/class-mouse.md "Mouse" +[Touchscreen]: api/class-touchscreen.md "Touchscreen" +[Request]: api/class-request.md "Request" +[Response]: api/class-response.md "Response" +[Selectors]: api/class-selectors.md "Selectors" +[Route]: api/class-route.md "Route" +[WebSocket]: api/class-websocket.md "WebSocket" +[TimeoutError]: api/class-timeouterror.md "TimeoutError" +[Accessibility]: api/class-accessibility.md "Accessibility" +[Worker]: api/class-worker.md "Worker" +[BrowserServer]: api/class-browserserver.md "BrowserServer" +[BrowserType]: api/class-browsertype.md "BrowserType" +[Logger]: api/class-logger.md "Logger" +[ChromiumBrowser]: api/class-chromiumbrowser.md "ChromiumBrowser" +[ChromiumBrowserContext]: api/class-chromiumbrowsercontext.md "ChromiumBrowserContext" +[ChromiumCoverage]: api/class-chromiumcoverage.md "ChromiumCoverage" +[CDPSession]: api/class-cdpsession.md "CDPSession" +[FirefoxBrowser]: api/class-firefoxbrowser.md "FirefoxBrowser" +[WebKitBrowser]: api/class-webkitbrowser.md "WebKitBrowser" +[Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array "Array" +[Buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer "Buffer" +[ChildProcess]: https://nodejs.org/api/child_process.html "ChildProcess" +[Element]: https://developer.mozilla.org/en-US/docs/Web/API/element "Element" +[Error]: https://nodejs.org/api/errors.html#errors_class_error "Error" +[Evaluation Argument]: ./core-concepts.md#evaluationargument "Evaluation Argument" +[Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map "Map" +[Object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object "Object" +[Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise "Promise" +[RegExp]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp "RegExp" +[Serializable]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Description "Serializable" +[UIEvent.detail]: https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail "UIEvent.detail" +[URL]: https://nodejs.org/api/url.html "URL" +[USKeyboardLayout]: ../src/usKeyboardLayout.ts "USKeyboardLayout" +[UnixTime]: https://en.wikipedia.org/wiki/Unix_time "Unix Time" +[boolean]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type "Boolean" +[function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function "Function" +[iterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols "Iterator" +[null]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null "null" +[number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type "Number" +[origin]: https://developer.mozilla.org/en-US/docs/Glossary/Origin "Origin" +[selector]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors "selector" +[Readable]: https://nodejs.org/api/stream.html#stream_class_stream_readable "Readable" +[string]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type "string" +[xpath]: https://developer.mozilla.org/en-US/docs/Web/XPath "xpath" diff --git a/docs/actionability.md b/docs/actionability.md index e2eafc01af..a776cf910a 100644 --- a/docs/actionability.md +++ b/docs/actionability.md @@ -1,18 +1,13 @@ - +--- +id: actionability +title: "Actionability" +--- -# Actionability +Playwright does a range of actionability checks on the elements before performing certain actions. These checks ensure that action behaves as expected, for example Playwright does not click on a disabled button. -Playwright does a range of actionability checks on the elements before -performing certain actions. These checks ensure that action behaves as expected, -for example Playwright does not click on a disabled button. +Playwright waits until all the relevant actionability checks pass before performing an action. This means that action will fail with `TimeoutError` if checks do not pass within the specified `timeout`. -Playwright waits until all the relevant actionability checks pass before -performing an action. This means that action will fail with `TimeoutError` if -checks do not pass within the specified `timeout`. - -Some actions like `page.click()` support `{force: true}` option that disable -non-essential actionability checks, for example passing `force` to `click()` -method will not check that the target element actually receives click events. +Some actions like `page.click()` support `{force: true}` option that disable non-essential actionability checks, for example passing `force` to `click()` method will not check that the target element actually receives click events. | Actions | Performed checks | | ------ | ------- | @@ -26,19 +21,15 @@ method will not check that the target element actually receives click events. ### Visible -Element is considered visible when it has non-empty bounding box and does not -have `visibility:hidden` computed style. Note that elements of zero size or with -`display:none` are not considered visible. +Element is considered visible when it has non-empty bounding box and does not have `visibility:hidden` computed style. Note that elements of zero size or with `display:none` are not considered visible. ### Stable -Element is considered stable when it has maintained the same bounding box for at -least two consecutive animation frames. +Element is considered stable when it has maintained the same bounding box for at least two consecutive animation frames. ### Enabled -Element is considered enabled when it is not a ` -
- `); - await page.click('button'); -})(); -``` - -An example of passing an element handle: - -```js -await context.exposeBinding('clicked', async (source, element) => { - console.log(await element.textContent()); -}, { handle: true }); -await page.setContent(` - -
Click me
-
Or click me
-`); -``` - -#### browserContext.exposeFunction(name, playwrightFunction) -- `name` <[string]> Name of the function on the window object. -- `playwrightFunction` <[function]> Callback function that will be called in the Playwright's context. -- returns: <[Promise]> - -The method adds a function called `name` on the `window` object of every frame in every page in the context. When called, the function executes `playwrightFunction` and returns a [Promise] which resolves to the return value of `playwrightFunction`. - -If the `playwrightFunction` returns a [Promise], it will be awaited. - -See [page.exposeFunction(name, playwrightFunction)](./api.md#pageexposefunctionname-playwrightfunction) for page-only version. - -An example of adding an `md5` function to all pages in the context: - -```js -const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. -const crypto = require('crypto'); - -(async () => { - const browser = await webkit.launch({ headless: false }); - const context = await browser.newContext(); - await context.exposeFunction('md5', text => crypto.createHash('md5').update(text).digest('hex')); - const page = await context.newPage(); - await page.setContent(` - - -
- `); - await page.click('button'); -})(); -``` - -#### browserContext.grantPermissions(permissions[, options]) -- `permissions` <[Array]<[string]>> A permission or an array of permissions to grant. Permissions can be one of the following values: - * `'geolocation'` - * `'midi'` - * `'midi-sysex'` (system-exclusive midi) - * `'notifications'` - * `'push'` - * `'camera'` - * `'microphone'` - * `'background-sync'` - * `'ambient-light-sensor'` - * `'accelerometer'` - * `'gyroscope'` - * `'magnetometer'` - * `'accessibility-events'` - * `'clipboard-read'` - * `'clipboard-write'` - * `'payment-handler'` -- `options` <[Object]> - - `origin` <[string]> The [origin] to grant permissions to, e.g. "https://example.com". -- returns: <[Promise]> - -Grants specified permissions to the browser context. Only grants corresponding permissions to the given origin if specified. - -#### browserContext.newPage() -- returns: <[Promise]<[Page]>> - -Creates a new page in the browser context. - -#### browserContext.pages() -- returns: <[Array]<[Page]>> - -Returns all open pages in the context. Non visible pages, such as `"background_page"`, will not be listed here. You can find them using [chromiumBrowserContext.backgroundPages()](./api.md#chromiumbrowsercontextbackgroundpages). - -#### browserContext.route(url, handler) -- `url` <[string]|[RegExp]|[function]\([URL]\):[boolean]> A glob pattern, regex pattern or predicate receiving [URL] to match while routing. -- `handler` <[function]\([Route], [Request]\)> handler function to route the request. -- returns: <[Promise]> - -Routing provides the capability to modify network requests that are made by any page in the browser context. Once route is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted. - -An example of a naïve handler that aborts all image requests: - -```js -const context = await browser.newContext(); -await context.route('**/*.{png,jpg,jpeg}', route => route.abort()); -const page = await context.newPage(); -await page.goto('https://example.com'); -await browser.close(); -``` - -or the same snippet using a regex pattern instead: - -```js -const context = await browser.newContext(); -await context.route(/(\.png$)|(\.jpg$)/, route => route.abort()); -const page = await context.newPage(); -await page.goto('https://example.com'); -await browser.close(); -``` - -Page routes (set up with [page.route(url, handler)](./api.md#pagerouteurl-handler)) take precedence over browser context routes when request matches both handlers. - -> **NOTE** Enabling routing disables http cache. - -#### browserContext.setDefaultNavigationTimeout(timeout) -- `timeout` <[number]> Maximum navigation time in milliseconds - -This setting will change the default maximum navigation time for the following methods and related shortcuts: -* [page.goBack([options])](./api.md#pagegobackoptions) -* [page.goForward([options])](./api.md#pagegoforwardoptions) -* [page.goto(url[, options])](./api.md#pagegotourl-options) -* [page.reload([options])](./api.md#pagereloadoptions) -* [page.setContent(html[, options])](./api.md#pagesetcontenthtml-options) -* [page.waitForNavigation([options])](./api.md#pagewaitfornavigationoptions) - -> **NOTE** [page.setDefaultNavigationTimeout(timeout)](./api.md#pagesetdefaultnavigationtimeouttimeout) and [page.setDefaultTimeout(timeout)](./api.md#pagesetdefaulttimeouttimeout) take priority over [browserContext.setDefaultNavigationTimeout(timeout)](./api.md#browsercontextsetdefaultnavigationtimeouttimeout). - -#### browserContext.setDefaultTimeout(timeout) -- `timeout` <[number]> Maximum time in milliseconds - -This setting will change the default maximum time for all the methods accepting `timeout` option. - -> **NOTE** [page.setDefaultNavigationTimeout(timeout)](./api.md#pagesetdefaultnavigationtimeouttimeout), [page.setDefaultTimeout(timeout)](./api.md#pagesetdefaulttimeouttimeout) and [browserContext.setDefaultNavigationTimeout(timeout)](./api.md#browsercontextsetdefaultnavigationtimeouttimeout) take priority over [browserContext.setDefaultTimeout(timeout)](./api.md#browsercontextsetdefaulttimeouttimeout). - -#### browserContext.setExtraHTTPHeaders(headers) -- `headers` <[Object]<[string], [string]>> An object containing additional HTTP headers to be sent with every request. All header values must be strings. -- returns: <[Promise]> - -The extra HTTP headers will be sent with every request initiated by any page in the context. These headers are merged with page-specific extra HTTP headers set with [page.setExtraHTTPHeaders(headers)](./api.md#pagesetextrahttpheadersheaders). If page overrides a particular header, page-specific header value will be used instead of the browser context header value. - -> **NOTE** `browserContext.setExtraHTTPHeaders` does not guarantee the order of headers in the outgoing requests. - -#### browserContext.setGeolocation(geolocation) -- `geolocation` <[null]|[Object]> - - `latitude` <[number]> Latitude between -90 and 90. **required** - - `longitude` <[number]> Longitude between -180 and 180. **required** - - `accuracy` <[number]> Non-negative accuracy value. Defaults to `0`. -- returns: <[Promise]> - -Sets the context's geolocation. Passing `null` or `undefined` emulates position unavailable. - -```js -await browserContext.setGeolocation({latitude: 59.95, longitude: 30.31667}); -``` - -> **NOTE** Consider using [browserContext.grantPermissions(permissions[, options])](./api.md#browsercontextgrantpermissionspermissions-options) to grant permissions for the browser context pages to read its geolocation. - -#### browserContext.setHTTPCredentials(httpCredentials) -- `httpCredentials` <[null]|[Object]> - - `username` <[string]> **required** - - `password` <[string]> **required** -- returns: <[Promise]> - -Provide credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). - -> **NOTE** Browsers may cache credentials after successful authentication. Passing different credentials or passing `null` to disable authentication will be unreliable. To remove or replace credentials, create a new browser context instead. - -#### browserContext.setOffline(offline) -- `offline` <[boolean]> Whether to emulate network being offline for the browser context. -- returns: <[Promise]> - -#### browserContext.storageState([options]) -- `options` <[Object]> - - `path` <[string]> The file path to save the storage state to. If `path` is a relative path, then it is resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd). If no path is provided, storage state is still returned, but won't be saved to the disk. -- returns: <[Promise]<[Object]>> - - `cookies` <[Array]<[Object]>> - - `name` <[string]> - - `value` <[string]> - - `domain` <[string]> - - `path` <[string]> - - `expires` <[number]> Unix time in seconds. - - `httpOnly` <[boolean]> - - `secure` <[boolean]> - - `sameSite` <"Strict"|"Lax"|"None"> - - `origins` <[Array]<[Object]>> - - `origin` <[string]> - - `localStorage` <[Array]<[Object]>> - - `name` <[string]> - - `value` <[string]> - -Returns storage state for this browser context, contains current cookies and local storage snapshot. - -#### browserContext.unroute(url[, handler]) -- `url` <[string]|[RegExp]|[function]\([URL]\):[boolean]> A glob pattern, regex pattern or predicate receiving [URL] used to register a routing with [browserContext.route(url, handler)](./api.md#browsercontextrouteurl-handler). -- `handler` <[function]\([Route], [Request]\)> Optional handler function used to register a routing with [browserContext.route(url, handler)](./api.md#browsercontextrouteurl-handler). -- returns: <[Promise]> - -Removes a route created with [browserContext.route(url, handler)](./api.md#browsercontextrouteurl-handler). When `handler` is not specified, removes all routes for the `url`. - -#### browserContext.waitForEvent(event[, optionsOrPredicate]) -- `event` <[string]> Event name, same one would pass into `browserContext.on(event)`. -- `optionsOrPredicate` <[Function]|[Object]> Either a predicate that receives an event or an options object. Optional. - - `predicate` <[Function]> receives the event data and resolves to truthy value when the waiting should resolve. - - `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can be changed by using the [browserContext.setDefaultTimeout(timeout)](./api.md#browsercontextsetdefaulttimeouttimeout). -- returns: <[Promise]<[Object]>> - -Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy value. Will throw an error if the context closes before the event is fired. Returns the event data value. - -```js -const context = await browser.newContext(); -await context.grantPermissions(['geolocation']); -``` - -### class: Page -* extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) - -Page provides methods to interact with a single tab in a [Browser], or an [extension background page](https://developer.chrome.com/extensions/background_pages) 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: - -```js -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`](https://nodejs.org/api/events.html#events_class_eventemitter) methods, such as `on`, `once` or `removeListener`. - -This example logs a message for a single page `load` event: - -```js -page.once('load', () => console.log('Page loaded!')); -``` - -To unsubscribe from events use the `removeListener` method: - -```js -function logRequest(interceptedRequest) { - console.log('A request was made:', interceptedRequest.url()); -} -page.on('request', logRequest); -// Sometime later... -page.removeListener('request', logRequest); -``` - - -- [page.on('close')](./api.md#pageonclose) -- [page.on('console')](./api.md#pageonconsole) -- [page.on('crash')](./api.md#pageoncrash) -- [page.on('dialog')](./api.md#pageondialog) -- [page.on('domcontentloaded')](./api.md#pageondomcontentloaded) -- [page.on('download')](./api.md#pageondownload) -- [page.on('filechooser')](./api.md#pageonfilechooser) -- [page.on('frameattached')](./api.md#pageonframeattached) -- [page.on('framedetached')](./api.md#pageonframedetached) -- [page.on('framenavigated')](./api.md#pageonframenavigated) -- [page.on('load')](./api.md#pageonload) -- [page.on('pageerror')](./api.md#pageonpageerror) -- [page.on('popup')](./api.md#pageonpopup) -- [page.on('request')](./api.md#pageonrequest) -- [page.on('requestfailed')](./api.md#pageonrequestfailed) -- [page.on('requestfinished')](./api.md#pageonrequestfinished) -- [page.on('response')](./api.md#pageonresponse) -- [page.on('websocket')](./api.md#pageonwebsocket) -- [page.on('worker')](./api.md#pageonworker) -- [page.$(selector)](./api.md#pageselector) -- [page.$$(selector)](./api.md#pageselector-1) -- [page.$eval(selector, pageFunction[, arg])](./api.md#pageevalselector-pagefunction-arg) -- [page.$$eval(selector, pageFunction[, arg])](./api.md#pageevalselector-pagefunction-arg-1) -- [page.accessibility](./api.md#pageaccessibility) -- [page.addInitScript(script[, arg])](./api.md#pageaddinitscriptscript-arg) -- [page.addScriptTag(params)](./api.md#pageaddscripttagparams) -- [page.addStyleTag(params)](./api.md#pageaddstyletagparams) -- [page.bringToFront()](./api.md#pagebringtofront) -- [page.check(selector[, options])](./api.md#pagecheckselector-options) -- [page.click(selector[, options])](./api.md#pageclickselector-options) -- [page.close([options])](./api.md#pagecloseoptions) -- [page.content()](./api.md#pagecontent) -- [page.context()](./api.md#pagecontext) -- [page.coverage](./api.md#pagecoverage) -- [page.dblclick(selector[, options])](./api.md#pagedblclickselector-options) -- [page.dispatchEvent(selector, type[, eventInit, options])](./api.md#pagedispatcheventselector-type-eventinit-options) -- [page.emulateMedia(params)](./api.md#pageemulatemediaparams) -- [page.evaluate(pageFunction[, arg])](./api.md#pageevaluatepagefunction-arg) -- [page.evaluateHandle(pageFunction[, arg])](./api.md#pageevaluatehandlepagefunction-arg) -- [page.exposeBinding(name, playwrightBinding[, options])](./api.md#pageexposebindingname-playwrightbinding-options) -- [page.exposeFunction(name, playwrightFunction)](./api.md#pageexposefunctionname-playwrightfunction) -- [page.fill(selector, value[, options])](./api.md#pagefillselector-value-options) -- [page.focus(selector[, options])](./api.md#pagefocusselector-options) -- [page.frame(frameSelector)](./api.md#pageframeframeselector) -- [page.frames()](./api.md#pageframes) -- [page.getAttribute(selector, name[, options])](./api.md#pagegetattributeselector-name-options) -- [page.goBack([options])](./api.md#pagegobackoptions) -- [page.goForward([options])](./api.md#pagegoforwardoptions) -- [page.goto(url[, options])](./api.md#pagegotourl-options) -- [page.hover(selector[, options])](./api.md#pagehoverselector-options) -- [page.innerHTML(selector[, options])](./api.md#pageinnerhtmlselector-options) -- [page.innerText(selector[, options])](./api.md#pageinnertextselector-options) -- [page.isClosed()](./api.md#pageisclosed) -- [page.keyboard](./api.md#pagekeyboard) -- [page.mainFrame()](./api.md#pagemainframe) -- [page.mouse](./api.md#pagemouse) -- [page.opener()](./api.md#pageopener) -- [page.pdf([options])](./api.md#pagepdfoptions) -- [page.press(selector, key[, options])](./api.md#pagepressselector-key-options) -- [page.reload([options])](./api.md#pagereloadoptions) -- [page.route(url, handler)](./api.md#pagerouteurl-handler) -- [page.screenshot([options])](./api.md#pagescreenshotoptions) -- [page.selectOption(selector, values[, options])](./api.md#pageselectoptionselector-values-options) -- [page.setContent(html[, options])](./api.md#pagesetcontenthtml-options) -- [page.setDefaultNavigationTimeout(timeout)](./api.md#pagesetdefaultnavigationtimeouttimeout) -- [page.setDefaultTimeout(timeout)](./api.md#pagesetdefaulttimeouttimeout) -- [page.setExtraHTTPHeaders(headers)](./api.md#pagesetextrahttpheadersheaders) -- [page.setInputFiles(selector, files[, options])](./api.md#pagesetinputfilesselector-files-options) -- [page.setViewportSize(viewportSize)](./api.md#pagesetviewportsizeviewportsize) -- [page.tap(selector[, options])](./api.md#pagetapselector-options) -- [page.textContent(selector[, options])](./api.md#pagetextcontentselector-options) -- [page.title()](./api.md#pagetitle) -- [page.touchscreen](./api.md#pagetouchscreen) -- [page.type(selector, text[, options])](./api.md#pagetypeselector-text-options) -- [page.uncheck(selector[, options])](./api.md#pageuncheckselector-options) -- [page.unroute(url[, handler])](./api.md#pageunrouteurl-handler) -- [page.url()](./api.md#pageurl) -- [page.video()](./api.md#pagevideo) -- [page.viewportSize()](./api.md#pageviewportsize) -- [page.waitForEvent(event[, optionsOrPredicate])](./api.md#pagewaitforeventevent-optionsorpredicate) -- [page.waitForFunction(pageFunction[, arg, options])](./api.md#pagewaitforfunctionpagefunction-arg-options) -- [page.waitForLoadState([state, options])](./api.md#pagewaitforloadstatestate-options) -- [page.waitForNavigation([options])](./api.md#pagewaitfornavigationoptions) -- [page.waitForRequest(urlOrPredicate[, options])](./api.md#pagewaitforrequesturlorpredicate-options) -- [page.waitForResponse(urlOrPredicate[, options])](./api.md#pagewaitforresponseurlorpredicate-options) -- [page.waitForSelector(selector[, options])](./api.md#pagewaitforselectorselector-options) -- [page.waitForTimeout(timeout)](./api.md#pagewaitfortimeouttimeout) -- [page.workers()](./api.md#pageworkers) - -#### page.on('close') - -Emitted when the page closes. - -#### page.on('console') -- type: <[ConsoleMessage]> - -Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`. Also emitted if the page throws an error or a warning. - -The arguments passed into `console.log` appear as arguments on the event handler. - -An example of handling `console` event: - -```js -page.on('console', msg => { - for (let i = 0; i < msg.args().length; ++i) - console.log(`${i}: ${msg.args()[i]}`); -}); -page.evaluate(() => console.log('hello', 5, {foo: 'bar'})); -``` - -#### page.on('crash') - -Emitted when the page crashes. Browser pages might crash if they try to allocate too much memory. When the page crashes, ongoing and subsequent operations will throw. - -The most common way to deal with crashes is to catch an exception: - -```js -try { - // Crash might happen during a click. - await page.click('button'); - // Or while waiting for an event. - await page.waitForEvent('popup'); -} catch (e) { - // When the page crashes, exception message contains 'crash'. -} -``` - -However, when manually listening to events, it might be useful to avoid stalling when the page crashes. In this case, handling `crash` event helps: - -```js -await new Promise((resolve, reject) => { - page.on('requestfinished', async request => { - if (await someProcessing(request)) - resolve(request); - }); - page.on('crash', error => reject(error)); -}); -``` - -#### page.on('dialog') -- type: <[Dialog]> - -Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` or `beforeunload`. Playwright can respond to the dialog via [dialog.accept([promptText])](./api.md#dialogacceptprompttext) or [dialog.dismiss()](./api.md#dialogdismiss) methods. - -#### page.on('domcontentloaded') - -Emitted when the JavaScript [`DOMContentLoaded`](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded) event is dispatched. - -#### page.on('download') -- type: <[Download]> - -Emitted when attachment download started. User can access basic file operations on downloaded content via the passed [Download] instance. - -> **NOTE** Browser context **must** be created with the `acceptDownloads` set to `true` when user needs access to the downloaded content. If `acceptDownloads` is not set or set to `false`, download events are emitted, but the actual download is not performed and user has no access to the downloaded files. - -#### page.on('filechooser') -- type: <[FileChooser]> - -Emitted when a file chooser is supposed to appear, such as after clicking the ``. Playwright can respond to it via setting the input files using [fileChooser.setFiles(files[, options])](./api.md#filechoosersetfilesfiles-options) that can be uploaded after that. - -```js -page.on('filechooser', async (fileChooser) => { - await fileChooser.setFiles('/tmp/myfile.pdf'); -}); -``` - -#### page.on('frameattached') -- type: <[Frame]> - -Emitted when a frame is attached. - -#### page.on('framedetached') -- type: <[Frame]> - -Emitted when a frame is detached. - -#### page.on('framenavigated') -- type: <[Frame]> - -Emitted when a frame is navigated to a new url. - -#### page.on('load') - -Emitted when the JavaScript [`load`](https://developer.mozilla.org/en-US/docs/Web/Events/load) event is dispatched. - -#### page.on('pageerror') -- type: <[Error]> - -Emitted when an uncaught exception happens within the page. - -#### page.on('popup') -- type: <[Page]> - -Emitted when the page opens a new tab or window. This event is emitted in addition to the [browserContext.on('page')](./api.md#browsercontextonpage), but only for popups relevant to this page. - -The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a popup with `window.open('http://example.com')`, this event will fire when the network request to "http://example.com" is done and its response has started loading in the popup. - -```js -const [popup] = await Promise.all([ - page.waitForEvent('popup'), - page.evaluate(() => window.open('https://example.com')), -]); -console.log(await popup.evaluate('location.href')); -``` - -> **NOTE** Use [page.waitForLoadState([state, options])](./api.md#pagewaitforloadstatestate-options) to wait until the page gets to a particular state (you should not need it in most cases). - -#### page.on('request') -- type: <[Request]> - -Emitted when a page issues a request. The [request] object is read-only. In order to intercept and mutate requests, see [page.route(url, handler)](./api.md#pagerouteurl-handler) or [browserContext.route(url, handler)](./api.md#browsercontextrouteurl-handler). - -#### page.on('requestfailed') -- type: <[Request]> - -Emitted when a request fails, for example by timing out. - -> **NOTE** HTTP Error responses, such as 404 or 503, are still successful responses from HTTP standpoint, so request will complete with [page.on('requestfinished')](./api.md#pageonrequestfinished) event and not with [page.on('requestfailed')](./api.md#pageonrequestfailed). - -#### page.on('requestfinished') -- type: <[Request]> - -Emitted when a request finishes successfully after downloading the response body. For a successful response, the sequence of events is `request`, `response` and `requestfinished`. - -#### page.on('response') -- type: <[Response]> - -Emitted when [response] status and headers are received for a request. For a successful response, the sequence of events is `request`, `response` and `requestfinished`. - -#### page.on('websocket') -- type: <[WebSocket]> - -Emitted when <[WebSocket]> request is sent. - -#### page.on('worker') -- type: <[Worker]> - -Emitted when a dedicated [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) is spawned by the page. - -#### page.$(selector) -- `selector` <[string]> A selector to query for. See [working with selectors](#working-with-selectors) for more details. -- returns: <[Promise]<[null]|[ElementHandle]>> - -The method finds an element matching the specified selector within the page. If no elements match the selector, the return value resolves to `null`. - -Shortcut for main frame's [frame.$(selector)](./api.md#frameselector). - -#### page.$$(selector) -- `selector` <[string]> A selector to query for. See [working with selectors](#working-with-selectors) for more details. -- returns: <[Promise]<[Array]<[ElementHandle]>>> - -The method finds all elements matching the specified selector within the page. If no elements match the selector, the return value resolves to `[]`. - -Shortcut for main frame's [frame.$$(selector)](./api.md#frameselector-1). - -#### page.$eval(selector, pageFunction[, arg]) -- `selector` <[string]> A selector to query for. See [working with selectors](#working-with-selectors) for more details. -- `pageFunction` <[function]\([Element]\)> Function to be evaluated in browser context -- `arg` <[EvaluationArgument]> Optional argument to pass to `pageFunction` -- returns: <[Promise]<[Serializable]>> - -The method finds an element matching the specified selector within the page and passes it as a first argument to `pageFunction`. If no elements match the selector, the method throws an error. Returns the value of `pageFunction`. - -If `pageFunction` returns a [Promise], then [page.$eval(selector, pageFunction[, arg])](./api.md#pageevalselector-pagefunction-arg) would wait for the promise to resolve and return its value. - -Examples: - -```js -const searchValue = await page.$eval('#search', el => el.value); -const preloadHref = await page.$eval('link[rel=preload]', el => el.href); -const html = await page.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello'); -``` - -Shortcut for main frame's [frame.$eval(selector, pageFunction[, arg])](./api.md#frameevalselector-pagefunction-arg). - -#### page.$$eval(selector, pageFunction[, arg]) -- `selector` <[string]> A selector to query for. See [working with selectors](#working-with-selectors) for more details. -- `pageFunction` <[function]\([Array]<[Element]>\)> Function to be evaluated in browser context -- `arg` <[EvaluationArgument]> Optional argument to pass to `pageFunction` -- returns: <[Promise]<[Serializable]>> - -The method finds all elements matching the specified selector within the page and passes an array of matched elements as a first argument to `pageFunction`. Returns the result of `pageFunction` invocation. - -If `pageFunction` returns a [Promise], then [page.$$eval(selector, pageFunction[, arg])](./api.md#pageevalselector-pagefunction-arg-1) would wait for the promise to resolve and return its value. - -Examples: - -```js -const divsCounts = await page.$$eval('div', (divs, min) => divs.length >= min, 10); -``` - -#### page.accessibility -- type: <[Accessibility]> - -#### page.addInitScript(script[, arg]) -- `script` <[function]|[string]|[Object]> Script to be evaluated in the page. - - `path` <[string]> Path to the JavaScript file. If `path` is a relative path, then it is resolved relative to the current working directory. Optional. - - `content` <[string]> Raw script content. Optional. -- `arg` <[Serializable]> Optional argument to pass to `script` (only supported when passing a function). -- returns: <[Promise]> - -Adds a script which would be evaluated in one of the following scenarios: -* Whenever the page is navigated. -* Whenever the child frame is attached or navigated. 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`. - -An example of overriding `Math.random` before the page loads: - -```js -// preload.js -Math.random = () => 42; - -// In your playwright script, assuming the preload.js file is in same directory -const preloadFile = fs.readFileSync('./preload.js', 'utf8'); -await page.addInitScript(preloadFile); -``` - -> **NOTE** The order of evaluation of multiple scripts installed via [browserContext.addInitScript(script[, arg])](./api.md#browsercontextaddinitscriptscript-arg) and [page.addInitScript(script[, arg])](./api.md#pageaddinitscriptscript-arg) is not defined. - -#### page.addScriptTag(params) -- `params` <[Object]> - - `url` <[string]> URL of a script to be added. Optional. - - `path` <[string]> Path to the JavaScript file to be injected into frame. If `path` is a relative path, then it is resolved relative to the current working directory. Optional. - - `content` <[string]> Raw JavaScript content to be injected into frame. Optional. - - `type` <[string]> Script type. Use 'module' in order to load a Javascript ES6 module. See [script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details. Optional. -- returns: <[Promise]<[ElementHandle]>> - -Adds a ` - -
- `); - await page.click('button'); -})(); -``` - -An example of passing an element handle: - -```js -await page.exposeBinding('clicked', async (source, element) => { - console.log(await element.textContent()); -}, { handle: true }); -await page.setContent(` - -
Click me
-
Or click me
-`); -``` - -#### page.exposeFunction(name, playwrightFunction) -- `name` <[string]> Name of the function on the window object -- `playwrightFunction` <[function]> Callback function which will be called in Playwright's context. -- returns: <[Promise]> - -The method adds a function called `name` on the `window` object of every frame in the page. When called, the function executes `playwrightFunction` and returns a [Promise] which resolves to the return value of `playwrightFunction`. - -If the `playwrightFunction` returns a [Promise], it will be awaited. - -See [browserContext.exposeFunction(name, playwrightFunction)](./api.md#browsercontextexposefunctionname-playwrightfunction) for context-wide exposed function. - -> **NOTE** Functions installed via `page.exposeFunction` survive navigations. - -An example of adding an `md5` function to the page: - -```js -const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'. -const crypto = require('crypto'); - -(async () => { - const browser = await webkit.launch({ headless: false }); - const page = await browser.newPage(); - await page.exposeFunction('md5', text => crypto.createHash('md5').update(text).digest('hex')); - await page.setContent(` - - -
- `); - await page.click('button'); -})(); -``` - -An example of adding a `window.readfile` function to the page: - -```js -const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'. -const fs = require('fs'); - -(async () => { - const browser = await chromium.launch(); - const page = await browser.newPage(); - page.on('console', msg => console.log(msg.text())); - await page.exposeFunction('readfile', async filePath => { - return new Promise((resolve, reject) => { - fs.readFile(filePath, 'utf8', (err, text) => { - if (err) - reject(err); - else - resolve(text); - }); - }); - }); - await page.evaluate(async () => { - // use window.readfile to read contents of a file - const content = await window.readfile('/etc/hosts'); - console.log(content); - }); - await browser.close(); -})(); -``` - -#### page.fill(selector, value[, options]) -- `selector` <[string]> A selector to search for element. If there are multiple elements satisfying the selector, the first will be used. See [working with selectors](#working-with-selectors) for more details. -- `value` <[string]> Value to fill for the ``, `