mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: update navigation and timers docs (#22941)
This commit is contained in:
parent
4d41535081
commit
e41b21dc7b
@ -2243,6 +2243,8 @@ class FrameExamples
|
||||
|
||||
## async method: Frame.waitForTimeout
|
||||
* since: v1.8
|
||||
* discouraged: Never wait for timeout in production. Tests that wait for time are
|
||||
inherently flaky. Use [Locator] actions and web assertions that wait automatically.
|
||||
|
||||
Waits for the given [`param: timeout`] in milliseconds.
|
||||
|
||||
|
||||
@ -584,6 +584,12 @@ Math.random = () => 42;
|
||||
await page.addInitScript({ path: './preload.js' });
|
||||
```
|
||||
|
||||
```js
|
||||
await page.addInitScript(mock => {
|
||||
window.mock = mock;
|
||||
}, mock);
|
||||
```
|
||||
|
||||
```java
|
||||
// In your playwright script, assuming the preload.js file is in same directory
|
||||
page.addInitScript(Paths.get("./preload.js"));
|
||||
|
||||
@ -3,9 +3,152 @@ 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.
|
||||
Playwright can navigate to URLs and handle navigations caused by the page interactions.
|
||||
|
||||
## Navigation lifecycle
|
||||
## Basic navigation
|
||||
|
||||
Simplest form of a navigation is opening a URL:
|
||||
|
||||
```js
|
||||
// Navigate the page
|
||||
await page.goto('https://example.com');
|
||||
```
|
||||
|
||||
```java
|
||||
// Navigate the page
|
||||
page.navigate("https://example.com");
|
||||
```
|
||||
|
||||
```python async
|
||||
# Navigate the page
|
||||
await page.goto("https://example.com")
|
||||
```
|
||||
|
||||
```python sync
|
||||
# Navigate the page
|
||||
page.goto("https://example.com")
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Navigate the page
|
||||
await page.GotoAsync("https://example.com");
|
||||
```
|
||||
|
||||
The code above loads the page and waits for the web page to fire the
|
||||
[load](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event) event.
|
||||
The load event is fired when the whole page has loaded, including all dependent
|
||||
resources such as stylesheets, scripts, iframes, and images.
|
||||
|
||||
:::note
|
||||
If the page does a client-side redirect before `load`, [`method: Page.goto`] will
|
||||
wait for the redirected page to fire the `load` event.
|
||||
:::
|
||||
|
||||
## When is the page loaded?
|
||||
|
||||
Modern pages perform numerous activities after the `load` event was fired. They
|
||||
fetch data lazily, populate UI, load expensive resources, scripts and styles after
|
||||
the `load` event was fired. There is no way to tell that the page is `loaded`,
|
||||
it depends on the page, framework, etc. So when can you start interacting with
|
||||
it?
|
||||
|
||||
In Playwright you can interact with the page at any moment. It will automatically
|
||||
wait for the target elements to become [actionable](./actionability.md).
|
||||
|
||||
```js
|
||||
// Navigate and click element
|
||||
// Click will auto-wait for the element
|
||||
await page.goto('https://example.com');
|
||||
await page.getByText('Example Domain').click();
|
||||
```
|
||||
|
||||
```java
|
||||
// Navigate and click element
|
||||
// Click will auto-wait for the element
|
||||
page.navigate("https://example.com");
|
||||
page.getByText("Example Domain").click();
|
||||
```
|
||||
|
||||
```python async
|
||||
# Navigate and click element
|
||||
# Click will auto-wait for the element
|
||||
await page.goto("https://example.com")
|
||||
await page.get_by_text("example domain").click()
|
||||
```
|
||||
|
||||
```python sync
|
||||
# Navigate and click element
|
||||
# Click will auto-wait for the element
|
||||
page.goto("https://example.com")
|
||||
page.get_by_text("example domain").click()
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Navigate and click element
|
||||
// Click will auto-wait for the element
|
||||
await page.GotoAsync("https://example.com");
|
||||
await page.GetByText("Example Domain").ClickAsync();
|
||||
```
|
||||
|
||||
For the scenario above, Playwright will wait for the text to become visible,
|
||||
will wait for the rest of the actionability checks to pass for that element,
|
||||
and will click it.
|
||||
|
||||
Playwright operates as a very fast user - the moment it sees the button, it
|
||||
clicks it. In the general case, you don't need to worry about whether all the
|
||||
resources loaded, etc.
|
||||
|
||||
## Hydration
|
||||
|
||||
At some point in time, you'll stumble upon a use case where Playwright performs
|
||||
an action, but nothing seemingly happens. Or you enter some text into the input
|
||||
field and will disappear. The most probable reason behind that is a poor page
|
||||
[hydration](https://en.wikipedia.org/wiki/Hydration_(web_development)).
|
||||
|
||||
When page is hydrated, first, a static version of the page is sent to the browser.
|
||||
Then the dynamic part is sent and the page becomes "live". As a very fast user,
|
||||
Playwright will start interacting with the page the moment it sees it. And if
|
||||
the button on a page is enabled, but the listeners have not yet been added,
|
||||
Playwright will do its job, but the click won't have any effect.
|
||||
|
||||
A simple way to verify if your page suffers from a poor hydration is to open Chrome
|
||||
DevTools, pick "Slow 3G" network emulation in the Network panel and reload the page.
|
||||
Once you see the element of interest, interact with it. You'll see that the button
|
||||
clicks will be ignored and the entered text will be reset by the subsequent page
|
||||
load code. The right fix for this issue is to make sure that all the interactive
|
||||
controls are disabled until after the hydration, when the page is fully functional.
|
||||
|
||||
## Waiting for navigation
|
||||
|
||||
Clicking an element could trigger multiple navigations. In these cases, it is
|
||||
recommended to explicitly [`method: Page.waitForURL`] to a specific url.
|
||||
|
||||
```js
|
||||
await page.getByText('Click me').click();
|
||||
await page.waitForURL('**/login');
|
||||
```
|
||||
|
||||
```java
|
||||
page.getByText("Click me").click();
|
||||
page.waitForURL("**/login");
|
||||
```
|
||||
|
||||
```python async
|
||||
await page.get_by_text("Click me").click()
|
||||
await page.wait_for_url("**/login")
|
||||
```
|
||||
|
||||
```python sync
|
||||
page.get_by_text("Click me").click()
|
||||
page.wait_for_url("**/login")
|
||||
```
|
||||
|
||||
```csharp
|
||||
await page.GetByText("Click me").ClickAsync();
|
||||
await page.WaitForURL("**/login");
|
||||
```
|
||||
|
||||
## Navigation events
|
||||
|
||||
Playwright splits the process of showing a new document in a page into **navigation** and **loading**.
|
||||
|
||||
@ -23,391 +166,3 @@ events:
|
||||
- page executes some scripts and loads resources like stylesheets and images
|
||||
- [`event: Page.load`] event is fired
|
||||
- page executes dynamically loaded scripts
|
||||
|
||||
## Scenarios initiated by browser UI
|
||||
|
||||
Navigations can be initiated by changing the URL bar, reloading the page or going back or forward in session history.
|
||||
|
||||
### Auto-wait
|
||||
|
||||
Navigating to a URL auto-waits for the page to fire the `load` event. If the page does a client-side redirect before
|
||||
`load`, [`method: Page.goto`] will auto-wait for the redirected page to fire the `load` event.
|
||||
|
||||
```js
|
||||
// Navigate the page
|
||||
await page.goto('https://example.com');
|
||||
```
|
||||
|
||||
```java
|
||||
// Navigate the page
|
||||
page.navigate("https://example.com");
|
||||
```
|
||||
|
||||
```python async
|
||||
# Navigate the page
|
||||
await page.goto("https://example.com")
|
||||
```
|
||||
|
||||
```python sync
|
||||
# Navigate the page
|
||||
page.goto("https://example.com")
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Navigate the page
|
||||
await page.GotoAsync("https://example.com");
|
||||
```
|
||||
|
||||
### Wait for element
|
||||
|
||||
In lazy-loaded pages, it can be useful to wait until an element is visible with [`method: Locator.waitFor`].
|
||||
Alternatively, page interactions like [`method: Page.click`] auto-wait for elements.
|
||||
|
||||
```js
|
||||
// Navigate and wait for element
|
||||
await page.goto('https://example.com');
|
||||
await page.getByText('Example Domain').waitFor();
|
||||
|
||||
// Navigate and click element
|
||||
// Click will auto-wait for the element
|
||||
await page.goto('https://example.com');
|
||||
await page.getByText('Example Domain').click();
|
||||
```
|
||||
|
||||
```java
|
||||
// Navigate and wait for element
|
||||
page.navigate("https://example.com");
|
||||
page.getByText("Example Domain").waitFor();
|
||||
|
||||
// Navigate and click element
|
||||
// Click will auto-wait for the element
|
||||
page.navigate("https://example.com");
|
||||
page.getByText("Example Domain").click();
|
||||
```
|
||||
|
||||
```python async
|
||||
# Navigate and wait for element
|
||||
await page.goto("https://example.com")
|
||||
await page.get_by_text("example domain").wait_for()
|
||||
|
||||
# Navigate and click element
|
||||
# Click will auto-wait for the element
|
||||
await page.goto("https://example.com")
|
||||
await page.get_by_text("example domain").click()
|
||||
```
|
||||
|
||||
```python sync
|
||||
# Navigate and wait for element
|
||||
page.goto("https://example.com")
|
||||
page.get_by_text("example domain").wait_for()
|
||||
|
||||
# Navigate and click element
|
||||
# Click will auto-wait for the element
|
||||
page.goto("https://example.com")
|
||||
page.get_by_text("example domain").click()
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Navigate and wait for element
|
||||
await page.GotoAsync("https://example.com");
|
||||
await page.GetByText("Example Domain").WaitForAsync();
|
||||
|
||||
// Navigate and click element
|
||||
// Click will auto-wait for the element
|
||||
await page.GotoAsync("https://example.com");
|
||||
await page.GetByText("Example Domain").ClickAsync();
|
||||
```
|
||||
|
||||
## Scenarios initiated by page interaction
|
||||
|
||||
In the scenarios below, [`method: Locator.click`] initiates a navigation and then waits for the navigation to complete.
|
||||
|
||||
### Auto-wait
|
||||
|
||||
By default, [`method: Locator.click`] will wait for the navigation step to complete. This can be combined with a page interaction on the navigated page which would auto-wait for an element.
|
||||
|
||||
```js
|
||||
// Click will auto-wait for navigation to complete
|
||||
await page.getByText('Login').click();
|
||||
|
||||
// Fill will auto-wait for element on navigated page
|
||||
await page.getByLabel('User Name').fill('John Doe');
|
||||
```
|
||||
|
||||
```java
|
||||
// Click will auto-wait for navigation to complete
|
||||
page.getByText("Login").click();
|
||||
|
||||
// Fill will auto-wait for element on navigated page
|
||||
page.getByLabel("User Name").fill("John Doe");
|
||||
```
|
||||
|
||||
```python async
|
||||
# Click will auto-wait for navigation to complete
|
||||
await page.get_by_text("Login").click()
|
||||
|
||||
# Fill will auto-wait for element on navigated page
|
||||
await page.get_by_label("User Name").fill("John Doe")
|
||||
```
|
||||
|
||||
```python sync
|
||||
# Click will auto-wait for navigation to complete
|
||||
page.get_by_text("Login").click()
|
||||
|
||||
# Fill will auto-wait for element on navigated page
|
||||
page.get_by_label("User Name").fill("John Doe")
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Click will auto-wait for navigation to complete
|
||||
await page.GetByText("Login").ClickAsync();
|
||||
|
||||
// Fill will auto-wait for element on navigated page
|
||||
await page.GetByLabel("User Name").FillAsync("John Doe");
|
||||
```
|
||||
|
||||
### Wait for element
|
||||
|
||||
In lazy-loaded pages, it can be useful to wait until an element is visible with [`method: Locator.waitFor`].
|
||||
Alternatively, page interactions like [`method: Locator.click`] auto-wait for elements.
|
||||
|
||||
```js
|
||||
// Click will auto-wait for the element and trigger navigation
|
||||
await page.getByText('Login').click();
|
||||
// Wait for the element
|
||||
await page.getByLabel('User Name').waitFor();
|
||||
|
||||
// Click triggers navigation
|
||||
await page.getByText('Login').click();
|
||||
// Fill will auto-wait for element
|
||||
await page.getByLabel('User Name').fill('John Doe');
|
||||
```
|
||||
|
||||
```java
|
||||
// Click will auto-wait for the element and trigger navigation
|
||||
page.getByText("Login").click();
|
||||
// Wait for the element
|
||||
page.getByLabel("User Name").waitFor();
|
||||
|
||||
// Click triggers navigation
|
||||
page.getByText("Login").click();
|
||||
// Fill will auto-wait for element
|
||||
page.getByLabel("User Name").fill("John Doe");
|
||||
```
|
||||
|
||||
```python async
|
||||
# Click will auto-wait for the element and trigger navigation
|
||||
await page.get_by_text("Login").click()
|
||||
# Wait for the element
|
||||
await page.get_by_label("User Name").wait_for()
|
||||
|
||||
# Click triggers navigation
|
||||
await page.get_by_text("Login").click()
|
||||
# Fill will auto-wait for element
|
||||
await page.get_by_label("User Name").fill("John Doe")
|
||||
```
|
||||
|
||||
```python sync
|
||||
# Click triggers navigation
|
||||
page.get_by_text("Login").click()
|
||||
# Click will auto-wait for the element
|
||||
page.get_by_label("User Name").wait_for()
|
||||
|
||||
# Click triggers navigation
|
||||
page.get_by_text("Login").click()
|
||||
# Fill will auto-wait for element
|
||||
page.get_by_label("User Name").fill("John Doe")
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Click will auto-wait for the element and trigger navigation
|
||||
await page.GetByText("Login").ClickAsync();
|
||||
// Wait for the element
|
||||
await page.GetByLabel("User Name").WaitForAsync();
|
||||
|
||||
// Click triggers navigation
|
||||
await page.GetByText("Login").ClickAsync();
|
||||
// Fill will auto-wait for element
|
||||
await page.GetByLabel("User Name").FillAsync("John Doe");
|
||||
```
|
||||
|
||||
### Asynchronous navigation
|
||||
|
||||
Clicking an element could trigger asynchronous processing before initiating the navigation. In these cases, it is
|
||||
recommended to explicitly call [`method: Page.waitForNavigation`]. For example:
|
||||
* Navigation is triggered from a `setTimeout`
|
||||
* Page waits for network requests before navigation
|
||||
|
||||
```js
|
||||
// Start waiting for navigation before clicking. Note no await.
|
||||
const navigationPromise = page.waitForNavigation();
|
||||
await page.getByText('Navigate after timeout').click();
|
||||
await navigationPromise;
|
||||
```
|
||||
|
||||
```java
|
||||
// Using waitForNavigation with a callback prevents a race condition
|
||||
// between clicking and waiting for a navigation.
|
||||
page.waitForNavigation(() -> { // Waits for the next navigation
|
||||
page.getByText("Navigate after timeout").click(); // Triggers a navigation after a timeout
|
||||
});
|
||||
```
|
||||
|
||||
```python async
|
||||
# Waits for the next navigation. Using Python context manager
|
||||
# prevents a race condition between clicking and waiting for a navigation.
|
||||
async with page.expect_navigation():
|
||||
# Triggers a navigation after a timeout
|
||||
await page.get_by_text("Navigate after timeout").click()
|
||||
```
|
||||
|
||||
```python sync
|
||||
# Waits for the next navigation. Using Python context manager
|
||||
# prevents a race condition between clicking and waiting for a navigation.
|
||||
with page.expect_navigation():
|
||||
# Triggers a navigation after a timeout
|
||||
page.get_by_text("Navigate after timeout").click()
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Using waitForNavigation with a callback prevents a race condition
|
||||
// between clicking and waiting for a navigation.
|
||||
await page.RunAndWaitForNavigationAsync(async () =>
|
||||
{
|
||||
// Triggers a navigation after a timeout
|
||||
await page.GetByText("Navigate after timeout").ClickAsync();
|
||||
});
|
||||
```
|
||||
|
||||
### Multiple navigations
|
||||
|
||||
Clicking an element could trigger multiple navigations. In these cases, it is recommended to explicitly
|
||||
[`method: Page.waitForNavigation`] to a specific url. For example:
|
||||
* Client-side redirects issued after the `load` event
|
||||
* Multiple pushes to history state
|
||||
|
||||
```js
|
||||
// Start waiting for navigation before clicking. Note no await.
|
||||
const navigationPromise = page.waitForNavigation({ url: '**/login' });
|
||||
// This action triggers the navigation with a script redirect.
|
||||
await page.getByText('Click me').click();
|
||||
await navigationPromise;
|
||||
```
|
||||
|
||||
```java
|
||||
// Running action in the callback of waitForNavigation prevents a race
|
||||
// condition between clicking and waiting for a navigation.
|
||||
page.waitForNavigation(new Page.WaitForNavigationOptions().setUrl("**/login"), () -> {
|
||||
page.getByText("Click me").click(); // Triggers a navigation with a script redirect
|
||||
});
|
||||
```
|
||||
|
||||
```python async
|
||||
# Using Python context manager prevents a race condition
|
||||
# between clicking and waiting for a navigation.
|
||||
async with page.expect_navigation(url="**/login"):
|
||||
# Triggers a navigation with a script redirect
|
||||
await page.get_by_text("Click me").click()
|
||||
```
|
||||
|
||||
```python sync
|
||||
# Using Python context manager prevents a race condition
|
||||
# between clicking and waiting for a navigation.
|
||||
with page.expect_navigation(url="**/login"):
|
||||
# Triggers a navigation with a script redirect
|
||||
page.get_by_text("Click me").click()
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Running action in the callback of waitForNavigation prevents a race
|
||||
// condition between clicking and waiting for a navigation.
|
||||
await page.RunAndWaitForNavigationAsync(async () =>
|
||||
{
|
||||
// Triggers a navigation with a script redirect.
|
||||
await page.GetByText("Click me").ClickAsync();
|
||||
}, new()
|
||||
{
|
||||
UrlString = "**/login"
|
||||
});
|
||||
```
|
||||
|
||||
### Loading a popup
|
||||
|
||||
When popup is opened, explicitly calling [`method: Page.waitForLoadState`] ensures that popup is loaded to the desired state.
|
||||
|
||||
```js
|
||||
// Start waiting for popup before clicking. Note no await.
|
||||
const popupPromise = page.waitForEvent('popup');
|
||||
await page.getByText('Open popup').click();
|
||||
const popup = await popupPromise;
|
||||
// Wait for the popup to load.
|
||||
await popup.waitForLoadState('load');
|
||||
```
|
||||
|
||||
```java
|
||||
Page popup = page.waitForPopup(() -> {
|
||||
page.getByText("Open popup").click(); // Opens popup
|
||||
});
|
||||
popup.waitForLoadState(LoadState.LOAD);
|
||||
```
|
||||
|
||||
```python async
|
||||
async with page.expect_popup() as popup_info:
|
||||
await page.get_by_text("Open popup").click() # Opens popup
|
||||
popup = await popup_info.value
|
||||
await popup.wait_for_load_state("load")
|
||||
```
|
||||
|
||||
```python sync
|
||||
with page.expect_popup() as popup_info:
|
||||
page.get_by_text("Open popup").click() # Opens popup
|
||||
popup = popup_info.value
|
||||
popup.wait_for_load_state("load")
|
||||
```
|
||||
|
||||
```csharp
|
||||
var popup = await page.RunAndWaitForPopupAsync(async () =>
|
||||
{
|
||||
await page.GetByText("Open popup").ClickAsync(); // Opens popup
|
||||
});
|
||||
popup.WaitForLoadStateAsync(LoadState.Load);
|
||||
```
|
||||
|
||||
## Advanced patterns
|
||||
|
||||
For pages that have complicated loading patterns, [`method: Page.waitForFunction`] is a powerful and extensible approach to define a custom wait criteria.
|
||||
|
||||
```js
|
||||
await page.goto('http://example.com');
|
||||
await page.waitForFunction(() => window.amILoadedYet());
|
||||
// Ready to take a screenshot, according to the page itself.
|
||||
await page.screenshot();
|
||||
```
|
||||
|
||||
```java
|
||||
page.navigate("http://example.com");
|
||||
page.waitForFunction("() => window.amILoadedYet()");
|
||||
// Ready to take a screenshot, according to the page itself.
|
||||
page.screenshot();
|
||||
```
|
||||
|
||||
```python async
|
||||
await page.goto("http://example.com")
|
||||
await page.wait_for_function("() => window.amILoadedYet()")
|
||||
# Ready to take a screenshot, according to the page itself.
|
||||
await page.screenshot()
|
||||
```
|
||||
|
||||
```python sync
|
||||
page.goto("http://example.com")
|
||||
page.wait_for_function("() => window.amILoadedYet()")
|
||||
# Ready to take a screenshot, according to the page itself.
|
||||
page.screenshot()
|
||||
```
|
||||
|
||||
```csharp
|
||||
await page.GotoAsync("http://example.com");
|
||||
await page.WaitForFunctionAsync("() => window.amILoadedYet()");
|
||||
// Ready to take a screenshot, according to the page itself.
|
||||
await page.ScreenshotAsync();
|
||||
```
|
||||
|
||||
@ -9,11 +9,6 @@ Playwright Test has multiple configurable timeouts for various tasks.
|
||||
|:----------|:----------------|:--------------------------------|
|
||||
|Test timeout|30000 ms|Timeout for each test, includes test, hooks and fixtures:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set default</span><br/><code>{`config = { timeout: 60000 }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.6'}}>Override</span><br/>`test.setTimeout(120000)` |
|
||||
|Expect timeout|5000 ms|Timeout for each assertion:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set default</span><br/><code>{`config = { expect: { timeout: 10000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.6'}}>Override</span><br/>`expect(locator).toBeVisible({ timeout: 10000 })` |
|
||||
|Action timeout| no timeout |Timeout for each action:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set default</span><br/><code>{`config = { use: { actionTimeout: 10000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.6'}}>Override</span><br/>`locator.click({ timeout: 10000 })` |
|
||||
|Navigation timeout| no timeout |Timeout for each navigation action:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set default</span><br/><code>{`config = { use: { navigationTimeout: 30000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.6'}}>Override</span><br/>`page.goto('/', { timeout: 30000 })` |
|
||||
|Global timeout|no timeout |Global timeout for the whole test run:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set in config</span><br/>`config = { globalTimeout: 60*60*1000 }`<br/> |
|
||||
|`beforeAll`/`afterAll` timeout|30000 ms|Timeout for the hook:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set in hook</span><br/>`test.setTimeout(60000)`<br/> |
|
||||
|Fixture timeout|no timeout |Timeout for an individual fixture:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set in fixture</span><br/>`{ scope: 'test', timeout: 30000 }`<br/> |
|
||||
|
||||
## Test timeout
|
||||
|
||||
@ -115,7 +110,44 @@ export default defineConfig({
|
||||
});
|
||||
```
|
||||
|
||||
API reference: [`property: TestConfig.expect`].
|
||||
## Global timeout
|
||||
|
||||
Playwright Test supports a timeout for the whole test run. This prevents excess resource usage when everything went wrong. There is no default global timeout, but you can set a reasonable one in the config, for example one hour. Global timeout produces the following error:
|
||||
|
||||
```
|
||||
Running 1000 tests using 10 workers
|
||||
|
||||
514 skipped
|
||||
486 passed
|
||||
Timed out waiting 3600s for the entire test run
|
||||
```
|
||||
|
||||
You can set global timeout in the config.
|
||||
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
globalTimeout: 60 * 60 * 1000,
|
||||
});
|
||||
```
|
||||
|
||||
API reference: [`property: TestConfig.globalTimeout`].
|
||||
|
||||
## Advanced: low level timeouts
|
||||
|
||||
These are the low-level timeouts that are pre-configured by the test runner, you should not need to change these.
|
||||
If you happen to be in this section because your test are flaky, it is very likely that you should be looking for the solution elsewhere.
|
||||
|
||||
|Timeout |Default |Description |
|
||||
|:----------|:----------------|:--------------------------------|
|
||||
|Action timeout| no timeout |Timeout for each action:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set default</span><br/><code>{`config = { use: { actionTimeout: 10000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.6'}}>Override</span><br/>`locator.click({ timeout: 10000 })` |
|
||||
|Navigation timeout| no timeout |Timeout for each navigation action:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set default</span><br/><code>{`config = { use: { navigationTimeout: 30000 } }`}</code><br/><span style={{textTransform: 'uppercase',fontSize: 'smaller', fontWeight: 'bold', opacity: '0.6'}}>Override</span><br/>`page.goto('/', { timeout: 30000 })` |
|
||||
|Global timeout|no timeout |Global timeout for the whole test run:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set in config</span><br/>`config = { globalTimeout: 60*60*1000 }`<br/> |
|
||||
|`beforeAll`/`afterAll` timeout|30000 ms|Timeout for the hook:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set in hook</span><br/>`test.setTimeout(60000)`<br/> |
|
||||
|Fixture timeout|no timeout |Timeout for an individual fixture:<br/><span style={{textTransform:'uppercase',fontSize:'smaller',fontWeight:'bold',opacity:'0.6'}}>Set in fixture</span><br/>`{ scope: 'test', timeout: 30000 }`<br/> |
|
||||
|
||||
|
||||
### Set timeout for a single assertion
|
||||
|
||||
@ -126,22 +158,6 @@ test('basic test', async ({ page }) => {
|
||||
await expect(page.getByRole('button')).toHaveText('Sign in', { timeout: 10000 });
|
||||
});
|
||||
```
|
||||
|
||||
## Action and navigation timeouts
|
||||
|
||||
Test usually performs some actions by calling Playwright APIs, for example `locator.click()`. These actions do not have a timeout by default, but you can set one. Action that timed out produces the following error:
|
||||
|
||||
```
|
||||
example.spec.ts:3:1 › basic test ===========================
|
||||
|
||||
locator.click: Timeout 1000ms exceeded.
|
||||
=========================== logs ===========================
|
||||
waiting for "locator('button')"
|
||||
============================================================
|
||||
```
|
||||
|
||||
Playwright also allows to set a separate timeout for navigation actions like `page.goto()` because loading a page is usually slower.
|
||||
|
||||
### Set action and navigation timeouts in the config
|
||||
|
||||
```js title="playwright.config.ts"
|
||||
@ -168,30 +184,6 @@ test('basic test', async ({ page }) => {
|
||||
});
|
||||
```
|
||||
|
||||
## Global timeout
|
||||
|
||||
Playwright Test supports a timeout for the whole test run. This prevents excess resource usage when everything went wrong. There is no default global timeout, but you can set a reasonable one in the config, for example one hour. Global timeout produces the following error:
|
||||
|
||||
```
|
||||
Running 1000 tests using 10 workers
|
||||
|
||||
514 skipped
|
||||
486 passed
|
||||
Timed out waiting 3600s for the entire test run
|
||||
```
|
||||
|
||||
You can set global timeout in the config.
|
||||
|
||||
```js title="playwright.config.ts"
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
globalTimeout: 60 * 60 * 1000,
|
||||
});
|
||||
```
|
||||
|
||||
API reference: [`property: TestConfig.globalTimeout`].
|
||||
|
||||
## Fixture timeout
|
||||
|
||||
By default, [fixture](./test-fixtures) shares timeout with the test. However, for slow fixtures, especially [worker-scoped](./test-fixtures#worker-scoped-fixtures) ones, it is convenient to have a separate timeout. This way you can keep the overall test timeout small, and give the slow fixture more time.
|
||||
|
||||
9
packages/playwright-core/types/types.d.ts
vendored
9
packages/playwright-core/types/types.d.ts
vendored
@ -276,6 +276,12 @@ export interface Page {
|
||||
* await page.addInitScript({ path: './preload.js' });
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* await page.addInitScript(mock => {
|
||||
* window.mock = mock;
|
||||
* }, mock);
|
||||
* ```
|
||||
*
|
||||
* **NOTE** The order of evaluation of multiple scripts installed via
|
||||
* [browserContext.addInitScript(script[, arg])](https://playwright.dev/docs/api/class-browsercontext#browser-context-add-init-script)
|
||||
* and [page.addInitScript(script[, arg])](https://playwright.dev/docs/api/class-page#page-add-init-script) is not
|
||||
@ -7289,6 +7295,9 @@ export interface Frame {
|
||||
}): Promise<null|Response>;
|
||||
|
||||
/**
|
||||
* **NOTE** Never wait for timeout in production. Tests that wait for time are inherently flaky. Use [Locator] actions and web
|
||||
* assertions that wait automatically.
|
||||
*
|
||||
* Waits for the given `timeout` in milliseconds.
|
||||
*
|
||||
* Note that `frame.waitForTimeout()` should only be used for debugging. Tests using the timer in production are going
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user