mirror of
https://github.com/microsoft/playwright.git
synced 2025-01-07 11:46:42 +03:00
docs: add titles for remaining examples (#22939)
Co-authored-by: Max Schmitt <max@schmitt.mx>
This commit is contained in:
parent
7e2a35ead4
commit
759d14b881
@ -223,8 +223,7 @@ The following example demonstrates creating and using a test fixture that covers
|
|||||||
|
|
||||||
This example fixture creates an `AxeBuilder` object which is pre-configured with shared `withTags()` and `exclude()` configuration.
|
This example fixture creates an `AxeBuilder` object which is pre-configured with shared `withTags()` and `exclude()` configuration.
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="axe-test.ts"
|
||||||
// axe-test.ts
|
|
||||||
import { test as base } from '@playwright/test';
|
import { test as base } from '@playwright/test';
|
||||||
import AxeBuilder from '@axe-core/playwright';
|
import AxeBuilder from '@axe-core/playwright';
|
||||||
|
|
||||||
|
@ -1666,8 +1666,7 @@ tests/
|
|||||||
|
|
||||||
And the following `page-click.spec.ts` that uses `toHaveScreenshot()` call:
|
And the following `page-click.spec.ts` that uses `toHaveScreenshot()` call:
|
||||||
|
|
||||||
```js
|
```js title="page-click.spec.ts"
|
||||||
// page-click.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test.describe('suite', () => {
|
test.describe('suite', () => {
|
||||||
|
@ -43,8 +43,7 @@ This is the **recommended** approach for tests **without server-side state**. Au
|
|||||||
|
|
||||||
Create `auth.setup.ts` that will prepare authenticated browser state for all other tests.
|
Create `auth.setup.ts` that will prepare authenticated browser state for all other tests.
|
||||||
|
|
||||||
```js
|
```js title="auth.setup.ts"
|
||||||
// auth.setup.ts
|
|
||||||
import { test as setup } from '@playwright/test';
|
import { test as setup } from '@playwright/test';
|
||||||
|
|
||||||
const authFile = 'playwright/.auth/user.json';
|
const authFile = 'playwright/.auth/user.json';
|
||||||
@ -104,8 +103,7 @@ export default defineConfig({
|
|||||||
|
|
||||||
Tests start already authenticated because we specified `storageState` in the config.
|
Tests start already authenticated because we specified `storageState` in the config.
|
||||||
|
|
||||||
```js
|
```js title="tests/example.spec.ts"
|
||||||
// tests/example.spec.ts
|
|
||||||
import { test } from '@playwright/test';
|
import { test } from '@playwright/test';
|
||||||
|
|
||||||
test('test', async ({ page }) => {
|
test('test', async ({ page }) => {
|
||||||
@ -131,8 +129,7 @@ We will authenticate once per [worker process](./test-parallel.md#worker-process
|
|||||||
|
|
||||||
Create `playwright/fixtures.ts` file that will [override `storageState` fixture](./test-fixtures.md#overriding-fixtures) to authenticate once per worker. Use [`property: TestInfo.parallelIndex`] to differentiate between workers.
|
Create `playwright/fixtures.ts` file that will [override `storageState` fixture](./test-fixtures.md#overriding-fixtures) to authenticate once per worker. Use [`property: TestInfo.parallelIndex`] to differentiate between workers.
|
||||||
|
|
||||||
```js
|
```js title="playwright/fixtures.ts"
|
||||||
// playwright/fixtures.ts
|
|
||||||
import { test as baseTest } from '@playwright/test';
|
import { test as baseTest } from '@playwright/test';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
@ -187,9 +184,7 @@ export const test = baseTest.extend<{}, { workerStorageState: string }>({
|
|||||||
|
|
||||||
Now, each test file should import `test` from our fixtures file instead of `@playwright/test`. No changes are needed in the config.
|
Now, each test file should import `test` from our fixtures file instead of `@playwright/test`. No changes are needed in the config.
|
||||||
|
|
||||||
```js
|
```js title="tests/example.spec.ts"
|
||||||
// tests/example.spec.ts
|
|
||||||
|
|
||||||
// Important: import our fixtures.
|
// Important: import our fixtures.
|
||||||
import { test, expect } from '../playwright/fixtures';
|
import { test, expect } from '../playwright/fixtures';
|
||||||
|
|
||||||
@ -319,8 +314,7 @@ We will send the API request with [APIRequestContext] and then save authenticate
|
|||||||
|
|
||||||
In the [setup project](#basic-shared-account-in-all-tests):
|
In the [setup project](#basic-shared-account-in-all-tests):
|
||||||
|
|
||||||
```js
|
```js title="auth.setup.ts"
|
||||||
// auth.setup.ts
|
|
||||||
import { test as setup } from '@playwright/test';
|
import { test as setup } from '@playwright/test';
|
||||||
|
|
||||||
const authFile = 'playwright/.auth/user.json';
|
const authFile = 'playwright/.auth/user.json';
|
||||||
@ -339,8 +333,7 @@ setup('authenticate', async ({ request }) => {
|
|||||||
|
|
||||||
Alternatively, in a [worker fixture](#moderate-one-account-per-parallel-worker):
|
Alternatively, in a [worker fixture](#moderate-one-account-per-parallel-worker):
|
||||||
|
|
||||||
```js
|
```js title="playwright/fixtures.ts"
|
||||||
// playwright/fixtures.ts
|
|
||||||
import { test as baseTest, request } from '@playwright/test';
|
import { test as baseTest, request } from '@playwright/test';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
@ -396,8 +389,7 @@ export const test = baseTest.extend<{}, { workerStorageState: string }>({
|
|||||||
|
|
||||||
We will authenticate multiple times in the setup project.
|
We will authenticate multiple times in the setup project.
|
||||||
|
|
||||||
```js
|
```js title="auth.setup.ts"
|
||||||
// auth.setup.ts
|
|
||||||
import { test as setup } from '@playwright/test';
|
import { test as setup } from '@playwright/test';
|
||||||
|
|
||||||
const adminFile = 'playwright/.auth/admin.json';
|
const adminFile = 'playwright/.auth/admin.json';
|
||||||
@ -445,8 +437,7 @@ setup('authenticate as user', async ({ page }) => {
|
|||||||
|
|
||||||
After that, specify `storageState` for each test file or test group, **instead of** setting it in the config.
|
After that, specify `storageState` for each test file or test group, **instead of** setting it in the config.
|
||||||
|
|
||||||
```js
|
```js title="tests/example.spec.ts"
|
||||||
// tests/example.spec.ts
|
|
||||||
import { test } from '@playwright/test';
|
import { test } from '@playwright/test';
|
||||||
|
|
||||||
test.use({ storageState: 'playwright/.auth/admin.json' });
|
test.use({ storageState: 'playwright/.auth/admin.json' });
|
||||||
@ -474,8 +465,7 @@ test.describe(() => {
|
|||||||
|
|
||||||
Use multiple [BrowserContext]s and [Page]s with different storage states in the same test.
|
Use multiple [BrowserContext]s and [Page]s with different storage states in the same test.
|
||||||
|
|
||||||
```js
|
```js title="tests/example.spec.ts"
|
||||||
// tests/example.spec.ts
|
|
||||||
import { test } from '@playwright/test';
|
import { test } from '@playwright/test';
|
||||||
|
|
||||||
test('admin and user', async ({ browser }) => {
|
test('admin and user', async ({ browser }) => {
|
||||||
@ -506,8 +496,7 @@ You can introduce fixtures that will provide a page authenticated as each role.
|
|||||||
|
|
||||||
Below is an example that [creates fixtures](./test-fixtures.md#creating-a-fixture) for two [Page Object Models](./pom.md) - admin POM and user POM. It assumes `adminStorageState.json` and `userStorageState.json` files were created in the global setup.
|
Below is an example that [creates fixtures](./test-fixtures.md#creating-a-fixture) for two [Page Object Models](./pom.md) - admin POM and user POM. It assumes `adminStorageState.json` and `userStorageState.json` files were created in the global setup.
|
||||||
|
|
||||||
```js
|
```js title="playwright/fixtures.ts"
|
||||||
// playwright/fixtures.ts
|
|
||||||
import { test as base, Page, Browser, Locator } from '@playwright/test';
|
import { test as base, Page, Browser, Locator } from '@playwright/test';
|
||||||
|
|
||||||
// Page Object Model for the "admin" page.
|
// Page Object Model for the "admin" page.
|
||||||
@ -562,8 +551,9 @@ export const test = base.extend<MyFixtures>({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
// tests/example.spec.ts
|
```js title="tests/example.spec.ts"
|
||||||
// Import test with our new fixtures.
|
// Import test with our new fixtures.
|
||||||
import { test, expect } from './fixtures';
|
import { test, expect } from './fixtures';
|
||||||
|
|
||||||
|
@ -101,8 +101,7 @@ To have the extension loaded when running tests you can use a test fixture to se
|
|||||||
|
|
||||||
First, add fixtures that will load the extension:
|
First, add fixtures that will load the extension:
|
||||||
|
|
||||||
```js
|
```js title="fixtures.ts"
|
||||||
// fixtures.ts
|
|
||||||
import { test as base, expect, chromium, type BrowserContext } from '@playwright/test';
|
import { test as base, expect, chromium, type BrowserContext } from '@playwright/test';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
@ -142,8 +141,7 @@ export const test = base.extend<{
|
|||||||
export const expect = test.expect;
|
export const expect = test.expect;
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python title="conftest.py"
|
||||||
# conftest.py
|
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from playwright.sync_api import Playwright, BrowserContext
|
from playwright.sync_api import Playwright, BrowserContext
|
||||||
@ -198,8 +196,7 @@ test('popup page', async ({ page, extensionId }) => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python title="test_foo.py"
|
||||||
# test_foo.py
|
|
||||||
from playwright.sync_api import expect, Page
|
from playwright.sync_api import expect, Page
|
||||||
|
|
||||||
|
|
||||||
@ -216,8 +213,8 @@ def test_popup_page(page: Page, extension_id: str) -> None:
|
|||||||
## Headless mode
|
## Headless mode
|
||||||
|
|
||||||
By default, Chrome's headless mode in Playwright does not support Chrome extensions. To overcome this limitation, you can run Chrome's persistent context with a new headless mode by using the following code:
|
By default, Chrome's headless mode in Playwright does not support Chrome extensions. To overcome this limitation, you can run Chrome's persistent context with a new headless mode by using the following code:
|
||||||
```js
|
|
||||||
// fixtures.ts
|
```js title="fixtures.ts"
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
const pathToExtension = path.join(__dirname, 'my-extension');
|
const pathToExtension = path.join(__dirname, 'my-extension');
|
||||||
@ -232,8 +229,7 @@ const context = await chromium.launchPersistentContext('', {
|
|||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python title="conftest.py"
|
||||||
# conftest.py
|
|
||||||
path_to_extension = Path(__file__).parent.joinpath("my-extension")
|
path_to_extension = Path(__file__).parent.joinpath("my-extension")
|
||||||
context = playwright.chromium.launch_persistent_context(
|
context = playwright.chromium.launch_persistent_context(
|
||||||
"",
|
"",
|
||||||
|
@ -20,8 +20,7 @@ Get started by installing Playwright and running the example file to see it in a
|
|||||||
}>
|
}>
|
||||||
<TabItem value="java">
|
<TabItem value="java">
|
||||||
|
|
||||||
```java
|
```java title="src/main/java/org/example/App.java"
|
||||||
// src/main/java/org/example/App.java
|
|
||||||
package org.example;
|
package org.example;
|
||||||
|
|
||||||
import com.microsoft.playwright.*;
|
import com.microsoft.playwright.*;
|
||||||
|
@ -125,8 +125,7 @@ python -m asyncio
|
|||||||
|
|
||||||
You can use Playwright with [Pyinstaller](https://www.pyinstaller.org/) to create standalone executables.
|
You can use Playwright with [Pyinstaller](https://www.pyinstaller.org/) to create standalone executables.
|
||||||
|
|
||||||
```py
|
```py title="main.py"
|
||||||
# main.py
|
|
||||||
from playwright.sync_api import sync_playwright
|
from playwright.sync_api import sync_playwright
|
||||||
|
|
||||||
with sync_playwright() as p:
|
with sync_playwright() as p:
|
||||||
|
@ -11,8 +11,7 @@ Playwright provides APIs to **monitor** and **modify** network traffic, both HTT
|
|||||||
|
|
||||||
You don't have to configure anything to mock network requests. Just define a custom [Route] that mocks network for a browser context.
|
You don't have to configure anything to mock network requests. Just define a custom [Route] that mocks network for a browser context.
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test.beforeEach(async ({ context }) => {
|
test.beforeEach(async ({ context }) => {
|
||||||
@ -28,8 +27,7 @@ test('loads page without css', async ({ page }) => {
|
|||||||
|
|
||||||
Alternatively, you can use [`method: Page.route`] to mock network in a single page.
|
Alternatively, you can use [`method: Page.route`] to mock network in a single page.
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test('loads page without images', async ({ page }) => {
|
test('loads page without images', async ({ page }) => {
|
||||||
|
@ -13,8 +13,7 @@ Page objects **simplify authoring** by creating a higher-level API which suits y
|
|||||||
|
|
||||||
We will create a `PlaywrightDevPage` helper class to encapsulate common operations on the `playwright.dev` page. Internally, it will use the `page` object.
|
We will create a `PlaywrightDevPage` helper class to encapsulate common operations on the `playwright.dev` page. Internally, it will use the `page` object.
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="playwright-dev-page.js"
|
||||||
// playwright-dev-page.js
|
|
||||||
const { expect } = require('@playwright/test');
|
const { expect } = require('@playwright/test');
|
||||||
|
|
||||||
exports.PlaywrightDevPage = class PlaywrightDevPage {
|
exports.PlaywrightDevPage = class PlaywrightDevPage {
|
||||||
@ -46,8 +45,7 @@ exports.PlaywrightDevPage = class PlaywrightDevPage {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="playwright-dev-page.ts"
|
||||||
// playwright-dev-page.ts
|
|
||||||
import { expect, Locator, Page } from '@playwright/test';
|
import { expect, Locator, Page } from '@playwright/test';
|
||||||
|
|
||||||
export class PlaywrightDevPage {
|
export class PlaywrightDevPage {
|
||||||
@ -81,8 +79,7 @@ export class PlaywrightDevPage {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-library
|
```js tab=js-library title="models/PlaywrightDevPage.js"
|
||||||
// models/PlaywrightDevPage.js
|
|
||||||
class PlaywrightDevPage {
|
class PlaywrightDevPage {
|
||||||
/**
|
/**
|
||||||
* @param {import('playwright').Page} page
|
* @param {import('playwright').Page} page
|
||||||
@ -109,8 +106,7 @@ module.exports = { PlaywrightDevPage };
|
|||||||
|
|
||||||
Now we can use the `PlaywrightDevPage` class in our tests.
|
Now we can use the `PlaywrightDevPage` class in our tests.
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="example.spec.js"
|
||||||
// example.spec.js
|
|
||||||
const { test, expect } = require('@playwright/test');
|
const { test, expect } = require('@playwright/test');
|
||||||
const { PlaywrightDevPage } = require('./playwright-dev-page');
|
const { PlaywrightDevPage } = require('./playwright-dev-page');
|
||||||
|
|
||||||
@ -138,8 +134,7 @@ test('should show Page Object Model article', async ({ page }) => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
import { PlaywrightDevPage } from './playwright-dev-page';
|
import { PlaywrightDevPage } from './playwright-dev-page';
|
||||||
|
|
||||||
@ -167,8 +162,7 @@ test('should show Page Object Model article', async ({ page }) => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-library
|
```js tab=js-library title="example.spec.js"
|
||||||
// example.spec.js
|
|
||||||
const { PlaywrightDevPage } = require('./playwright-dev-page');
|
const { PlaywrightDevPage } = require('./playwright-dev-page');
|
||||||
|
|
||||||
// In the test
|
// In the test
|
||||||
@ -192,8 +186,7 @@ await expect(playwrightDev.tocList).toHaveText([
|
|||||||
|
|
||||||
Page object models wrap over a Playwright [Page].
|
Page object models wrap over a Playwright [Page].
|
||||||
|
|
||||||
```java
|
```java title="models/SearchPage.java"
|
||||||
// models/SearchPage.java
|
|
||||||
package models;
|
package models;
|
||||||
|
|
||||||
import com.microsoft.playwright;
|
import com.microsoft.playwright;
|
||||||
@ -218,8 +211,7 @@ public class SearchPage {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```python async
|
```python async title="models/search.py"
|
||||||
# models/search.py
|
|
||||||
class SearchPage:
|
class SearchPage:
|
||||||
def __init__(self, page):
|
def __init__(self, page):
|
||||||
self.page = page
|
self.page = page
|
||||||
@ -233,8 +225,7 @@ class SearchPage:
|
|||||||
await self.search_term_input.press("Enter")
|
await self.search_term_input.press("Enter")
|
||||||
```
|
```
|
||||||
|
|
||||||
```python sync
|
```python sync title="models/search.py"
|
||||||
# models/search.py
|
|
||||||
class SearchPage:
|
class SearchPage:
|
||||||
def __init__(self, page):
|
def __init__(self, page):
|
||||||
self.page = page
|
self.page = page
|
||||||
@ -292,8 +283,7 @@ searchPage.navigate();
|
|||||||
searchPage.search("search query");
|
searchPage.search("search query");
|
||||||
```
|
```
|
||||||
|
|
||||||
```python async
|
```python async title="test_search.py"
|
||||||
# test_search.py
|
|
||||||
from models.search import SearchPage
|
from models.search import SearchPage
|
||||||
|
|
||||||
# in the test
|
# in the test
|
||||||
@ -303,8 +293,7 @@ await search_page.navigate()
|
|||||||
await search_page.search("search query")
|
await search_page.search("search query")
|
||||||
```
|
```
|
||||||
|
|
||||||
```python sync
|
```python sync title="test_search.py"
|
||||||
# test_search.py
|
|
||||||
from models.search import SearchPage
|
from models.search import SearchPage
|
||||||
|
|
||||||
# in the test
|
# in the test
|
||||||
|
@ -615,8 +615,7 @@ Use these to configure your app for tests.
|
|||||||
|
|
||||||
For example, this could be used to setup App router in Vue.js:
|
For example, this could be used to setup App router in Vue.js:
|
||||||
|
|
||||||
```js
|
```js title="src/component.spec.ts"
|
||||||
// src/component.spec.ts
|
|
||||||
import { test } from '@playwright/experimental-ct-vue';
|
import { test } from '@playwright/experimental-ct-vue';
|
||||||
import { Component } from './mycomponent';
|
import { Component } from './mycomponent';
|
||||||
|
|
||||||
@ -629,8 +628,7 @@ test('should work', async ({ mount }) => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js title="playwright/index.ts"
|
||||||
// playwright/index.ts
|
|
||||||
import { router } from '../router';
|
import { router } from '../router';
|
||||||
import { beforeMount } from '@playwright/experimental-ct-vue/hooks';
|
import { beforeMount } from '@playwright/experimental-ct-vue/hooks';
|
||||||
|
|
||||||
@ -641,8 +639,7 @@ beforeMount(async ({ app, hooksConfig }) => {
|
|||||||
|
|
||||||
A similar configuration in Next.js would look like this:
|
A similar configuration in Next.js would look like this:
|
||||||
|
|
||||||
```js
|
```js title="src/component.spec.jsx"
|
||||||
// src/component.spec.jsx
|
|
||||||
import { test } from '@playwright/experimental-ct-react';
|
import { test } from '@playwright/experimental-ct-react';
|
||||||
import { Component } from './mycomponent';
|
import { Component } from './mycomponent';
|
||||||
|
|
||||||
@ -659,8 +656,7 @@ test('should work', async ({ mount }) => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js title="playwright/index.js"
|
||||||
// playwright/index.js
|
|
||||||
import router from 'next/router';
|
import router from 'next/router';
|
||||||
import { beforeMount } from '@playwright/experimental-ct-react/hooks';
|
import { beforeMount } from '@playwright/experimental-ct-react/hooks';
|
||||||
|
|
||||||
@ -805,8 +801,7 @@ WebServer is now considered "ready" if request to the specified url has any of t
|
|||||||
|
|
||||||
Here is what a typical component test looks like:
|
Here is what a typical component test looks like:
|
||||||
|
|
||||||
```ts
|
```ts title="App.spec.tsx"
|
||||||
// App.spec.tsx
|
|
||||||
import { test, expect } from '@playwright/experimental-ct-react';
|
import { test, expect } from '@playwright/experimental-ct-react';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
|
||||||
|
@ -127,8 +127,7 @@ Additionally, any network request made by the **Page** (including its sub-[Frame
|
|||||||
|
|
||||||
Many Service Worker implementations simply execute the request from the page (possibly with some custom caching/offline logic omitted for simplicity):
|
Many Service Worker implementations simply execute the request from the page (possibly with some custom caching/offline logic omitted for simplicity):
|
||||||
|
|
||||||
```js
|
```js title="transparent-service-worker.js"
|
||||||
// filename: transparent-service-worker.js
|
|
||||||
self.addEventListener("fetch", (event) => {
|
self.addEventListener("fetch", (event) => {
|
||||||
// actually make the request
|
// actually make the request
|
||||||
const responsePromise = fetch(event.request);
|
const responsePromise = fetch(event.request);
|
||||||
@ -180,8 +179,7 @@ When a Service Worker handles a page's request, the Service Worker can make 0 to
|
|||||||
Consider the code snippets below to understand Playwright's view into the Request/Responses and how it impacts routing in some of these cases.
|
Consider the code snippets below to understand Playwright's view into the Request/Responses and how it impacts routing in some of these cases.
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js title="complex-service-worker.js"
|
||||||
// filename: complex-service-worker.js
|
|
||||||
self.addEventListener("install", function (event) {
|
self.addEventListener("install", function (event) {
|
||||||
event.waitUntil(
|
event.waitUntil(
|
||||||
caches.open("v1").then(function (cache) {
|
caches.open("v1").then(function (cache) {
|
||||||
|
@ -103,8 +103,7 @@ npx playwright test --grep "(?=.*@fast)(?=.*@slow)"
|
|||||||
|
|
||||||
For example, you can run a group of tests just in Chromium by passing a callback.
|
For example, you can run a group of tests just in Chromium by passing a callback.
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
|
|
||||||
test.describe('chromium only', () => {
|
test.describe('chromium only', () => {
|
||||||
test.skip(({ browserName }) => browserName !== 'chromium', 'Chromium only!');
|
test.skip(({ browserName }) => browserName !== 'chromium', 'Chromium only!');
|
||||||
@ -127,8 +126,7 @@ test.describe('chromium only', () => {
|
|||||||
|
|
||||||
To avoid running `beforeEach` hooks, you can put annotations in the hook itself.
|
To avoid running `beforeEach` hooks, you can put annotations in the hook itself.
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
|
|
||||||
test.beforeEach(async ({ page, isMobile }) => {
|
test.beforeEach(async ({ page, isMobile }) => {
|
||||||
test.fixme(isMobile, 'Settings page does not work in mobile yet');
|
test.fixme(isMobile, 'Settings page does not work in mobile yet');
|
||||||
@ -147,8 +145,7 @@ test('user profile', async ({ page }) => {
|
|||||||
It's also possible to add custom metadata in the form of annotations to your tests. Annotations are key/value pairs accessible via [`test.info().annotations`](./api/class-testinfo#test-info-annotations). Many reporters show annotations, for example `'html'`.
|
It's also possible to add custom metadata in the form of annotations to your tests. Annotations are key/value pairs accessible via [`test.info().annotations`](./api/class-testinfo#test-info-annotations). Many reporters show annotations, for example `'html'`.
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
|
|
||||||
test('user profile', async ({ page }) => {
|
test('user profile', async ({ page }) => {
|
||||||
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/<some-issue>' });
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/<some-issue>' });
|
||||||
|
@ -85,8 +85,7 @@ You can access all the same [Fixtures] as the test function itself, and also the
|
|||||||
|
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test.afterEach(async ({ page }, testInfo) => {
|
test.afterEach(async ({ page }, testInfo) => {
|
||||||
@ -123,8 +122,7 @@ You can use [`method: Test.afterAll`] to teardown any resources set up in `befor
|
|||||||
|
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test.beforeAll(async () => {
|
test.beforeAll(async () => {
|
||||||
@ -163,8 +161,7 @@ You can use [`method: Test.afterEach`] to teardown any resources set up in `befo
|
|||||||
|
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test.beforeEach(async ({ page }, testInfo) => {
|
test.beforeEach(async ({ page }, testInfo) => {
|
||||||
@ -551,8 +548,7 @@ Extends the `test` object by defining fixtures and/or options that can be used i
|
|||||||
|
|
||||||
First define a fixture and/or an option.
|
First define a fixture and/or an option.
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="my-test.js"
|
||||||
// my-test.js
|
|
||||||
const base = require('@playwright/test');
|
const base = require('@playwright/test');
|
||||||
const { TodoPage } = require('./todo-page');
|
const { TodoPage } = require('./todo-page');
|
||||||
|
|
||||||
@ -600,8 +596,7 @@ export const test = base.extend<Options & { todoPage: TodoPage }>({
|
|||||||
|
|
||||||
Then use the fixture in the test.
|
Then use the fixture in the test.
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test } from './my-test';
|
import { test } from './my-test';
|
||||||
|
|
||||||
test('test 1', async ({ todoPage }) => {
|
test('test 1', async ({ todoPage }) => {
|
||||||
|
@ -607,8 +607,7 @@ export default defineConfig({
|
|||||||
|
|
||||||
Now you can use a relative path when navigating the page:
|
Now you can use a relative path when navigating the page:
|
||||||
|
|
||||||
```js
|
```js title="test.spec.ts"
|
||||||
// test.spec.ts
|
|
||||||
import { test } from '@playwright/test';
|
import { test } from '@playwright/test';
|
||||||
|
|
||||||
test('test', async ({ page }) => {
|
test('test', async ({ page }) => {
|
||||||
|
@ -20,8 +20,7 @@ export default defineConfig({
|
|||||||
|
|
||||||
Alternatively, with [`method: Test.use`] you can override some options for a file.
|
Alternatively, with [`method: Test.use`] you can override some options for a file.
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
// Run tests in this file with portrait-like viewport.
|
// Run tests in this file with portrait-like viewport.
|
||||||
|
@ -216,8 +216,7 @@ This includes any config that needs to be run before or after mounting the compo
|
|||||||
}>
|
}>
|
||||||
<TabItem value="react">
|
<TabItem value="react">
|
||||||
|
|
||||||
```js
|
```js title="playwright/index.tsx"
|
||||||
// playwright/index.tsx
|
|
||||||
import { beforeMount, afterMount } from '@playwright/experimental-ct-react/hooks';
|
import { beforeMount, afterMount } from '@playwright/experimental-ct-react/hooks';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
|
||||||
@ -233,8 +232,7 @@ This includes any config that needs to be run before or after mounting the compo
|
|||||||
|
|
||||||
#### In your test file:
|
#### In your test file:
|
||||||
|
|
||||||
```js
|
```js title="src/pages/ProductsPage.spec.tsx"
|
||||||
// src/pages/ProductsPage.spec.tsx
|
|
||||||
import { test, expect } from '@playwright/experimental-ct-react';
|
import { test, expect } from '@playwright/experimental-ct-react';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '@playwright/test';
|
||||||
import { ProductsPage } from './pages/ProductsPage';
|
import { ProductsPage } from './pages/ProductsPage';
|
||||||
@ -251,8 +249,7 @@ This includes any config that needs to be run before or after mounting the compo
|
|||||||
|
|
||||||
<TabItem value="solid">
|
<TabItem value="solid">
|
||||||
|
|
||||||
```js
|
```js title="playwright/index.tsx"
|
||||||
// playwright/index.tsx
|
|
||||||
import { beforeMount, afterMount } from '@playwright/experimental-ct-solid/hooks';
|
import { beforeMount, afterMount } from '@playwright/experimental-ct-solid/hooks';
|
||||||
import { Router } from '@solidjs/router';
|
import { Router } from '@solidjs/router';
|
||||||
|
|
||||||
@ -268,8 +265,7 @@ This includes any config that needs to be run before or after mounting the compo
|
|||||||
|
|
||||||
#### In your test file:
|
#### In your test file:
|
||||||
|
|
||||||
```js
|
```js title="src/pages/ProductsPage.spec.tsx"
|
||||||
// src/pages/ProductsPage.spec.tsx
|
|
||||||
import { test, expect } from '@playwright/experimental-ct-solid';
|
import { test, expect } from '@playwright/experimental-ct-solid';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '@playwright/test';
|
||||||
import { ProductsPage } from './pages/ProductsPage';
|
import { ProductsPage } from './pages/ProductsPage';
|
||||||
@ -286,8 +282,7 @@ This includes any config that needs to be run before or after mounting the compo
|
|||||||
|
|
||||||
<TabItem value="vue3">
|
<TabItem value="vue3">
|
||||||
|
|
||||||
```js
|
```js title="playwright/index.ts"
|
||||||
// playwright/index.ts
|
|
||||||
import { beforeMount, afterMount } from '@playwright/experimental-ct-vue/hooks';
|
import { beforeMount, afterMount } from '@playwright/experimental-ct-vue/hooks';
|
||||||
import { router } from '../src/router';
|
import { router } from '../src/router';
|
||||||
|
|
||||||
@ -303,8 +298,7 @@ This includes any config that needs to be run before or after mounting the compo
|
|||||||
|
|
||||||
#### In your test file:
|
#### In your test file:
|
||||||
|
|
||||||
```js
|
```js title="src/pages/ProductsPage.spec.ts"
|
||||||
// src/pages/ProductsPage.spec.ts
|
|
||||||
import { test, expect } from '@playwright/experimental-ct-vue';
|
import { test, expect } from '@playwright/experimental-ct-vue';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '@playwright/test';
|
||||||
import ProductsPage from './pages/ProductsPage.vue';
|
import ProductsPage from './pages/ProductsPage.vue';
|
||||||
@ -321,8 +315,7 @@ This includes any config that needs to be run before or after mounting the compo
|
|||||||
|
|
||||||
<TabItem value="vue2">
|
<TabItem value="vue2">
|
||||||
|
|
||||||
```js
|
```js title="playwright/index.ts"
|
||||||
// playwright/index.ts
|
|
||||||
import { beforeMount, afterMount } from '@playwright/experimental-ct-vue2/hooks';
|
import { beforeMount, afterMount } from '@playwright/experimental-ct-vue2/hooks';
|
||||||
import Router from 'vue-router';
|
import Router from 'vue-router';
|
||||||
import { router } from '../src/router';
|
import { router } from '../src/router';
|
||||||
@ -340,8 +333,7 @@ This includes any config that needs to be run before or after mounting the compo
|
|||||||
```
|
```
|
||||||
#### In your test file:
|
#### In your test file:
|
||||||
|
|
||||||
```js
|
```js title="src/pages/ProductsPage.spec.ts"
|
||||||
// src/pages/ProductsPage.spec.ts
|
|
||||||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '@playwright/test';
|
||||||
import ProductsPage from './pages/ProductsPage.vue';
|
import ProductsPage from './pages/ProductsPage.vue';
|
||||||
@ -567,8 +559,7 @@ export default defineConfig({
|
|||||||
|
|
||||||
Pinia needs to be initialized in `playwright/index.{js,ts,jsx,tsx}`. If you do this inside a `beforeMount` hook, the `initialState` can be overwritten on a per-test basis:
|
Pinia needs to be initialized in `playwright/index.{js,ts,jsx,tsx}`. If you do this inside a `beforeMount` hook, the `initialState` can be overwritten on a per-test basis:
|
||||||
|
|
||||||
```js
|
```js title="playwright/index.ts"
|
||||||
// playwright/index.ts
|
|
||||||
import { beforeMount, afterMount } from '@playwright/experimental-ct-vue/hooks';
|
import { beforeMount, afterMount } from '@playwright/experimental-ct-vue/hooks';
|
||||||
import { createTestingPinia } from '@pinia/testing';
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
import type { StoreState } from 'pinia';
|
import type { StoreState } from 'pinia';
|
||||||
@ -596,8 +587,7 @@ Pinia needs to be initialized in `playwright/index.{js,ts,jsx,tsx}`. If you do t
|
|||||||
|
|
||||||
#### In your test file:
|
#### In your test file:
|
||||||
|
|
||||||
```js
|
```js title="src/pinia.spec.ts"
|
||||||
// src/pinia.spec.ts
|
|
||||||
import { test, expect } from '@playwright/experimental-ct-vue';
|
import { test, expect } from '@playwright/experimental-ct-vue';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '@playwright/test';
|
||||||
import Store from './Store.vue';
|
import Store from './Store.vue';
|
||||||
|
@ -202,8 +202,7 @@ export default defineConfig({});
|
|||||||
|
|
||||||
Now we can use `toBeWithinRange` in the test.
|
Now we can use `toBeWithinRange` in the test.
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test('numeric ranges', () => {
|
test('numeric ranges', () => {
|
||||||
@ -220,8 +219,7 @@ For TypeScript, also add the following to your [`global.d.ts`](https://www.types
|
|||||||
|
|
||||||
You don't need it for JavaScript.
|
You don't need it for JavaScript.
|
||||||
|
|
||||||
```js
|
```js title="global.d.ts"
|
||||||
// global.d.ts
|
|
||||||
export {};
|
export {};
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -41,8 +41,7 @@ Here is how typical test environment setup differs between traditional test styl
|
|||||||
<summary>Click to expand the code for the <code>TodoPage</code></summary>
|
<summary>Click to expand the code for the <code>TodoPage</code></summary>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="todo-page.js"
|
||||||
// todo-page.js
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
/**
|
/**
|
||||||
* @param {import('@playwright/test').Page} page
|
* @param {import('@playwright/test').Page} page
|
||||||
@ -83,8 +82,7 @@ export class TodoPage {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="todo-page.ts"
|
||||||
// todo-page.ts
|
|
||||||
import { Page, Locator } from '@playwright/test';
|
import { Page, Locator } from '@playwright/test';
|
||||||
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
@ -123,8 +121,7 @@ export class TodoPage {
|
|||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
```js
|
```js title="todo.spec.ts"
|
||||||
// todo.spec.js
|
|
||||||
const { test } = require('@playwright/test');
|
const { test } = require('@playwright/test');
|
||||||
const { TodoPage } = require('./todo-page');
|
const { TodoPage } = require('./todo-page');
|
||||||
|
|
||||||
@ -168,8 +165,7 @@ Fixtures have a number of advantages over before/after hooks:
|
|||||||
<summary>Click to expand the code for the <code>TodoPage</code></summary>
|
<summary>Click to expand the code for the <code>TodoPage</code></summary>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="todo-page.js"
|
||||||
// todo-page.js
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
/**
|
/**
|
||||||
* @param {import('@playwright/test').Page} page
|
* @param {import('@playwright/test').Page} page
|
||||||
@ -210,8 +206,7 @@ export class TodoPage {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="todo-page.ts"
|
||||||
// todo-page.ts
|
|
||||||
import { Page, Locator } from '@playwright/test';
|
import { Page, Locator } from '@playwright/test';
|
||||||
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
@ -249,8 +244,7 @@ export class TodoPage {
|
|||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="todo.spec.js"
|
||||||
// todo.spec.js
|
|
||||||
const base = require('@playwright/test');
|
const base = require('@playwright/test');
|
||||||
const { TodoPage } = require('./todo-page');
|
const { TodoPage } = require('./todo-page');
|
||||||
|
|
||||||
@ -277,8 +271,7 @@ test('should remove an item', async ({ todoPage }) => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test as base } from '@playwright/test';
|
import { test as base } from '@playwright/test';
|
||||||
import { TodoPage } from './todo-page';
|
import { TodoPage } from './todo-page';
|
||||||
|
|
||||||
@ -314,8 +307,7 @@ Below we create two fixtures `todoPage` and `settingsPage` that follow the [Page
|
|||||||
<details>
|
<details>
|
||||||
<summary>Click to expand the code for the <code>TodoPage</code> and <code>SettingsPage</code></summary>
|
<summary>Click to expand the code for the <code>TodoPage</code> and <code>SettingsPage</code></summary>
|
||||||
<div>
|
<div>
|
||||||
```js tab=js-js
|
```js tab=js-js title="todo-page.js"
|
||||||
// todo-page.js
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
/**
|
/**
|
||||||
* @param {import('@playwright/test').Page} page
|
* @param {import('@playwright/test').Page} page
|
||||||
@ -356,8 +348,7 @@ export class TodoPage {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="todo-page.ts"
|
||||||
// todo-page.ts
|
|
||||||
import { Page, Locator } from '@playwright/test';
|
import { Page, Locator } from '@playwright/test';
|
||||||
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
@ -395,8 +386,7 @@ export class TodoPage {
|
|||||||
|
|
||||||
SettingsPage is similar:
|
SettingsPage is similar:
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="settings-page.js"
|
||||||
// settings-page.js
|
|
||||||
export class SettingsPage {
|
export class SettingsPage {
|
||||||
/**
|
/**
|
||||||
* @param {import('@playwright/test').Page} page
|
* @param {import('@playwright/test').Page} page
|
||||||
@ -411,8 +401,7 @@ export class SettingsPage {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="settings-page.ts"
|
||||||
// settings-page.ts
|
|
||||||
import { Page } from '@playwright/test';
|
import { Page } from '@playwright/test';
|
||||||
|
|
||||||
export class SettingsPage {
|
export class SettingsPage {
|
||||||
@ -428,8 +417,7 @@ export class SettingsPage {
|
|||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="my-test.js"
|
||||||
// my-test.js
|
|
||||||
const base = require('@playwright/test');
|
const base = require('@playwright/test');
|
||||||
const { TodoPage } = require('./todo-page');
|
const { TodoPage } = require('./todo-page');
|
||||||
const { SettingsPage } = require('./settings-page');
|
const { SettingsPage } = require('./settings-page');
|
||||||
@ -458,8 +446,7 @@ exports.test = base.test.extend({
|
|||||||
exports.expect = base.expect;
|
exports.expect = base.expect;
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="my-test.ts"
|
||||||
// my-test.ts
|
|
||||||
import { test as base } from '@playwright/test';
|
import { test as base } from '@playwright/test';
|
||||||
import { TodoPage } from './todo-page';
|
import { TodoPage } from './todo-page';
|
||||||
import { SettingsPage } from './settings-page';
|
import { SettingsPage } from './settings-page';
|
||||||
@ -547,8 +534,7 @@ export const test = base.extend({
|
|||||||
|
|
||||||
Notice that in this example, the `page` fixture is able to depend on other built-in fixtures such as [`property: TestOptions.baseURL`]. We can now configure `baseURL` in the configuration file, or locally in the test file with [`method: Test.use`].
|
Notice that in this example, the `page` fixture is able to depend on other built-in fixtures such as [`property: TestOptions.baseURL`]. We can now configure `baseURL` in the configuration file, or locally in the test file with [`method: Test.use`].
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
|
|
||||||
test.use({ baseURL: 'https://playwright.dev' });
|
test.use({ baseURL: 'https://playwright.dev' });
|
||||||
```
|
```
|
||||||
@ -572,8 +558,7 @@ Playwright Test uses [worker processes](./test-parallel.md) to run test files. S
|
|||||||
|
|
||||||
Below we'll create an `account` fixture that will be shared by all tests in the same worker, and override the `page` fixture to login into this account for each test. To generate unique accounts, we'll use the [`property: WorkerInfo.workerIndex`] that is available to any test or fixture. Note the tuple-like syntax for the worker fixture - we have to pass `{scope: 'worker'}` so that test runner sets up this fixture once per worker.
|
Below we'll create an `account` fixture that will be shared by all tests in the same worker, and override the `page` fixture to login into this account for each test. To generate unique accounts, we'll use the [`property: WorkerInfo.workerIndex`] that is available to any test or fixture. Note the tuple-like syntax for the worker fixture - we have to pass `{scope: 'worker'}` so that test runner sets up this fixture once per worker.
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="my-test.js"
|
||||||
// my-test.js
|
|
||||||
const base = require('@playwright/test');
|
const base = require('@playwright/test');
|
||||||
|
|
||||||
exports.test = base.test.extend({
|
exports.test = base.test.extend({
|
||||||
@ -613,8 +598,7 @@ exports.test = base.test.extend({
|
|||||||
exports.expect = base.expect;
|
exports.expect = base.expect;
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="my-test.ts"
|
||||||
// my-test.ts
|
|
||||||
import { test as base } from '@playwright/test';
|
import { test as base } from '@playwright/test';
|
||||||
|
|
||||||
type Account = {
|
type Account = {
|
||||||
@ -666,8 +650,7 @@ Automatic fixtures are set up for each test/worker, even when the test does not
|
|||||||
|
|
||||||
Here is an example fixture that automatically attaches debug logs when the test fails, so we can later review the logs in the reporter. Note how it uses [TestInfo] object that is available in each test/fixture to retrieve metadata about the test being run.
|
Here is an example fixture that automatically attaches debug logs when the test fails, so we can later review the logs in the reporter. Note how it uses [TestInfo] object that is available in each test/fixture to retrieve metadata about the test being run.
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="my-test.js"
|
||||||
// my-test.js
|
|
||||||
const debug = require('debug');
|
const debug = require('debug');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const base = require('@playwright/test');
|
const base = require('@playwright/test');
|
||||||
@ -692,8 +675,7 @@ exports.test = base.test.extend({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="my-test.ts"
|
||||||
// my-test.ts
|
|
||||||
import * as debug from 'debug';
|
import * as debug from 'debug';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { test as base } from '@playwright/test';
|
import { test as base } from '@playwright/test';
|
||||||
@ -768,8 +750,7 @@ Below we'll create a `defaultItem` option in addition to the `todoPage` fixture
|
|||||||
<summary>Click to expand the code for the <code>TodoPage</code></summary>
|
<summary>Click to expand the code for the <code>TodoPage</code></summary>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="todo-page.js"
|
||||||
// todo-page.js
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
/**
|
/**
|
||||||
* @param {import('@playwright/test').Page} page
|
* @param {import('@playwright/test').Page} page
|
||||||
@ -810,8 +791,7 @@ export class TodoPage {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="todo-page.ts"
|
||||||
// todo-page.ts
|
|
||||||
import { Page, Locator } from '@playwright/test';
|
import { Page, Locator } from '@playwright/test';
|
||||||
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
@ -850,8 +830,7 @@ export class TodoPage {
|
|||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="my-test.js"
|
||||||
// my-test.js
|
|
||||||
const base = require('@playwright/test');
|
const base = require('@playwright/test');
|
||||||
const { TodoPage } = require('./todo-page');
|
const { TodoPage } = require('./todo-page');
|
||||||
|
|
||||||
@ -872,8 +851,7 @@ exports.test = base.test.extend({
|
|||||||
exports.expect = base.expect;
|
exports.expect = base.expect;
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="my-test.ts"
|
||||||
// my-test.ts
|
|
||||||
import { test as base } from '@playwright/test';
|
import { test as base } from '@playwright/test';
|
||||||
import { TodoPage } from './todo-page';
|
import { TodoPage } from './todo-page';
|
||||||
|
|
||||||
|
@ -60,8 +60,7 @@ export default defineConfig({
|
|||||||
|
|
||||||
Here is a global setup example that authenticates once and reuses authentication state in tests. It uses the `baseURL` and `storageState` options from the configuration file.
|
Here is a global setup example that authenticates once and reuses authentication state in tests. It uses the `baseURL` and `storageState` options from the configuration file.
|
||||||
|
|
||||||
```js
|
```js title="global-setup.ts"
|
||||||
// global-setup.ts/js
|
|
||||||
import { chromium, FullConfig } from '@playwright/test';
|
import { chromium, FullConfig } from '@playwright/test';
|
||||||
|
|
||||||
async function globalSetup(config: FullConfig) {
|
async function globalSetup(config: FullConfig) {
|
||||||
@ -105,8 +104,7 @@ test('test', async ({ page }) => {
|
|||||||
|
|
||||||
You can make arbitrary data available in your tests from your global setup file by setting them as environment variables via `process.env`.
|
You can make arbitrary data available in your tests from your global setup file by setting them as environment variables via `process.env`.
|
||||||
|
|
||||||
```js
|
```js title="global-setup.ts"
|
||||||
// global-setup.ts/js
|
|
||||||
import { FullConfig } from '@playwright/test';
|
import { FullConfig } from '@playwright/test';
|
||||||
|
|
||||||
async function globalSetup(config: FullConfig) {
|
async function globalSetup(config: FullConfig) {
|
||||||
@ -139,8 +137,7 @@ test('test', async ({ page }) => {
|
|||||||
|
|
||||||
In some instances, it may be useful to capture a trace of failures encountered during the global setup. In order to do this, you must [start tracing](./api/class-tracing.md#tracing-start) in your setup, and you must ensure that you [stop tracing](./api/class-tracing.md#tracing-stop) if an error occurs before that error is thrown. This can be achieved by wrapping your setup in a `try...catch` block. Here is an example that expands the global setup example to capture a trace.
|
In some instances, it may be useful to capture a trace of failures encountered during the global setup. In order to do this, you must [start tracing](./api/class-tracing.md#tracing-start) in your setup, and you must ensure that you [stop tracing](./api/class-tracing.md#tracing-stop) if an error occurs before that error is thrown. This can be achieved by wrapping your setup in a `try...catch` block. Here is an example that expands the global setup example to capture a trace.
|
||||||
|
|
||||||
```js
|
```js title="global-setup.ts"
|
||||||
// global-setup.ts/js
|
|
||||||
import { chromium, FullConfig } from '@playwright/test';
|
import { chromium, FullConfig } from '@playwright/test';
|
||||||
|
|
||||||
async function globalSetup(config: FullConfig) {
|
async function globalSetup(config: FullConfig) {
|
||||||
|
@ -181,8 +181,7 @@ Tests lists are discouraged and supported as a best-effort only. Some features s
|
|||||||
|
|
||||||
You can put your tests in helper functions in multiple files. Consider the following example where tests are not defined directly in the file, but rather in a wrapper function.
|
You can put your tests in helper functions in multiple files. Consider the following example where tests are not defined directly in the file, but rather in a wrapper function.
|
||||||
|
|
||||||
```js
|
```js title="feature-a.spec.ts"
|
||||||
// feature-a.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
export default function createTests() {
|
export default function createTests() {
|
||||||
@ -191,7 +190,9 @@ export default function createTests() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// feature-b.spec.ts
|
```
|
||||||
|
|
||||||
|
```js title="feature-b.spec.ts"
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
export default function createTests() {
|
export default function createTests() {
|
||||||
@ -206,8 +207,7 @@ export default function createTests() {
|
|||||||
You can create a test list file that will control the order of tests - first run `feature-b` tests, then `feature-a` tests. Note how each test file is wrapped in a `test.describe()` block that calls the function where tests are defined. This way `test.use()` calls only affect tests from a single file.
|
You can create a test list file that will control the order of tests - first run `feature-b` tests, then `feature-a` tests. Note how each test file is wrapped in a `test.describe()` block that calls the function where tests are defined. This way `test.use()` calls only affect tests from a single file.
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js title="test.list.ts"
|
||||||
// test.list.ts
|
|
||||||
import { test } from '@playwright/test';
|
import { test } from '@playwright/test';
|
||||||
import featureBTests from './feature-b.spec.ts';
|
import featureBTests from './feature-b.spec.ts';
|
||||||
import featureATests from './feature-a.spec.ts';
|
import featureATests from './feature-a.spec.ts';
|
||||||
|
@ -7,8 +7,7 @@ You can either parameterize tests on a test level or on a project level.
|
|||||||
|
|
||||||
## Parameterized Tests
|
## Parameterized Tests
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
const people = ['Alice', 'Bob'];
|
const people = ['Alice', 'Bob'];
|
||||||
for (const name of people) {
|
for (const name of people) {
|
||||||
test(`testing with ${name}`, async () => {
|
test(`testing with ${name}`, async () => {
|
||||||
@ -24,8 +23,7 @@ Playwright Test supports running multiple test projects at the same time. In the
|
|||||||
|
|
||||||
We declare the option `person` and set the value in the config. The first project runs with the value `Alice` and the second with the value `Bob`.
|
We declare the option `person` and set the value in the config. The first project runs with the value `Alice` and the second with the value `Bob`.
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="my-test.js"
|
||||||
// my-test.js
|
|
||||||
const base = require('@playwright/test');
|
const base = require('@playwright/test');
|
||||||
|
|
||||||
exports.test = base.test.extend({
|
exports.test = base.test.extend({
|
||||||
@ -35,8 +33,7 @@ exports.test = base.test.extend({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="my-test.ts"
|
||||||
// my-test.ts
|
|
||||||
import { test as base } from '@playwright/test';
|
import { test as base } from '@playwright/test';
|
||||||
|
|
||||||
export type TestOptions = {
|
export type TestOptions = {
|
||||||
@ -52,8 +49,7 @@ export const test = base.extend<TestOptions>({
|
|||||||
|
|
||||||
We can use this option in the test, similarly to [fixtures](./test-fixtures.md).
|
We can use this option in the test, similarly to [fixtures](./test-fixtures.md).
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test } from './my-test';
|
import { test } from './my-test';
|
||||||
|
|
||||||
test('test 1', async ({ page, person }) => {
|
test('test 1', async ({ page, person }) => {
|
||||||
@ -102,8 +98,7 @@ export default defineConfig<TestOptions>({
|
|||||||
|
|
||||||
We can also use the option in a fixture. Learn more about [fixtures](./test-fixtures.md).
|
We can also use the option in a fixture. Learn more about [fixtures](./test-fixtures.md).
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="my-test.js"
|
||||||
// my-test.js
|
|
||||||
const base = require('@playwright/test');
|
const base = require('@playwright/test');
|
||||||
|
|
||||||
exports.test = base.test.extend({
|
exports.test = base.test.extend({
|
||||||
@ -123,8 +118,7 @@ exports.test = base.test.extend({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="my-test.ts"
|
||||||
// my-test.ts
|
|
||||||
import { test as base } from '@playwright/test';
|
import { test as base } from '@playwright/test';
|
||||||
|
|
||||||
export type TestOptions = {
|
export type TestOptions = {
|
||||||
@ -158,8 +152,7 @@ You can use environment variables to configure tests from the command line.
|
|||||||
|
|
||||||
For example, consider the following test file that needs a username and a password. It is usually a good idea not to store your secrets in the source code, so we'll need a way to pass secrets from outside.
|
For example, consider the following test file that needs a username and a password. It is usually a good idea not to store your secrets in the source code, so we'll need a way to pass secrets from outside.
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
test(`example test`, async ({ page }) => {
|
test(`example test`, async ({ page }) => {
|
||||||
// ...
|
// ...
|
||||||
await page.getByLabel('User Name').fill(process.env.USERNAME);
|
await page.getByLabel('User Name').fill(process.env.USERNAME);
|
||||||
@ -266,8 +259,7 @@ See for example this CSV file, in our example `input.csv`:
|
|||||||
|
|
||||||
Based on this we'll generate some tests by using the [csv-parse](https://www.npmjs.com/package/csv-parse) library from NPM:
|
Based on this we'll generate some tests by using the [csv-parse](https://www.npmjs.com/package/csv-parse) library from NPM:
|
||||||
|
|
||||||
```js
|
```js title="test.spec.ts"
|
||||||
// foo.spec.ts
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { test } from '@playwright/test';
|
import { test } from '@playwright/test';
|
||||||
@ -279,7 +271,7 @@ const records = parse(fs.readFileSync(path.join(__dirname, 'input.csv')), {
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (const record of records) {
|
for (const record of records) {
|
||||||
test(`fooo: ${record.test_case}`, async ({ page }) => {
|
test(`foo: ${record.test_case}`, async ({ page }) => {
|
||||||
console.log(record.test_case, record.some_value, record.some_other_value);
|
console.log(record.test_case, record.some_value, record.some_other_value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,7 @@ Test runner notifies the reporter about various events during test execution. Al
|
|||||||
|
|
||||||
You can create a custom reporter by implementing a class with some of the reporter methods. Make sure to export this class as default.
|
You can create a custom reporter by implementing a class with some of the reporter methods. Make sure to export this class as default.
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="my-awesome-reporter.js"
|
||||||
// my-awesome-reporter.js
|
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
/** @implements {import('@playwright/test/reporter').Reporter} */
|
/** @implements {import('@playwright/test/reporter').Reporter} */
|
||||||
@ -36,8 +35,7 @@ class MyReporter {
|
|||||||
module.exports = MyReporter;
|
module.exports = MyReporter;
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="my-awesome-reporter.ts"
|
||||||
// my-awesome-reporter.ts
|
|
||||||
import { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
|
import { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
|
||||||
|
|
||||||
class MyReporter implements Reporter {
|
class MyReporter implements Reporter {
|
||||||
|
@ -288,8 +288,7 @@ export default defineConfig({
|
|||||||
|
|
||||||
You can create a custom reporter by implementing a class with some of the reporter methods. Learn more about the [Reporter] API.
|
You can create a custom reporter by implementing a class with some of the reporter methods. Learn more about the [Reporter] API.
|
||||||
|
|
||||||
```js
|
```js title="my-awesome-reporter.ts"
|
||||||
// my-awesome-reporter.ts
|
|
||||||
import { FullConfig, FullResult, Reporter, Suite, TestCase, TestResult } from '@playwright/test/reporter';
|
import { FullConfig, FullResult, Reporter, Suite, TestCase, TestResult } from '@playwright/test/reporter';
|
||||||
|
|
||||||
class MyReporter implements Reporter {
|
class MyReporter implements Reporter {
|
||||||
|
@ -163,8 +163,7 @@ It is usually better to make your tests isolated, so they can be efficiently run
|
|||||||
|
|
||||||
Playwright Test creates an isolated [Page] object for each test. However, if you'd like to reuse a single [Page] object between multiple tests, you can create your own in [`method: Test.beforeAll`] and close it in [`method: Test.afterAll`].
|
Playwright Test creates an isolated [Page] object for each test. However, if you'd like to reuse a single [Page] object between multiple tests, you can create your own in [`method: Test.beforeAll`] and close it in [`method: Test.afterAll`].
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js title="example.spec.js"
|
||||||
// example.spec.js
|
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const { test } = require('@playwright/test');
|
const { test } = require('@playwright/test');
|
||||||
@ -191,9 +190,7 @@ test('runs second', async () => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts
|
```js tab=js-ts title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
|
|
||||||
import { test, Page } from '@playwright/test';
|
import { test, Page } from '@playwright/test';
|
||||||
|
|
||||||
test.describe.configure({ mode: 'serial' });
|
test.describe.configure({ mode: 'serial' });
|
||||||
|
@ -82,8 +82,7 @@ See [Running Tests](./running-tests.md) for general information on `pytest` opti
|
|||||||
|
|
||||||
### Configure Mypy typings for auto-completion
|
### Configure Mypy typings for auto-completion
|
||||||
|
|
||||||
```py
|
```py title="test_my_application.py"
|
||||||
# test_my_application.py
|
|
||||||
from playwright.sync_api import Page
|
from playwright.sync_api import Page
|
||||||
|
|
||||||
def test_visit_admin_dashboard(page: Page):
|
def test_visit_admin_dashboard(page: Page):
|
||||||
@ -103,8 +102,7 @@ Slows down Playwright operations by 100 milliseconds.
|
|||||||
|
|
||||||
### Skip test by browser
|
### Skip test by browser
|
||||||
|
|
||||||
```py
|
```py title="test_my_application.py"
|
||||||
# test_my_application.py
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.mark.skip_browser("firefox")
|
@pytest.mark.skip_browser("firefox")
|
||||||
@ -115,8 +113,7 @@ def test_visit_example(page):
|
|||||||
|
|
||||||
### Run on a specific browser
|
### Run on a specific browser
|
||||||
|
|
||||||
```py
|
```py title="conftest.py"
|
||||||
# conftest.py
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.mark.only_browser("chromium")
|
@pytest.mark.only_browser("chromium")
|
||||||
@ -131,8 +128,7 @@ def test_visit_example(page):
|
|||||||
pytest --browser-channel chrome
|
pytest --browser-channel chrome
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python title="test_my_application.py"
|
||||||
# test_my_application.py
|
|
||||||
def test_example(page):
|
def test_example(page):
|
||||||
page.goto("https://example.com")
|
page.goto("https://example.com")
|
||||||
```
|
```
|
||||||
@ -146,8 +142,7 @@ for that which allows you to set the base url from the config, CLI arg or as a f
|
|||||||
pytest --base-url http://localhost:8080
|
pytest --base-url http://localhost:8080
|
||||||
```
|
```
|
||||||
|
|
||||||
```py
|
```py title="test_my_application.py"
|
||||||
# test_my_application.py
|
|
||||||
def test_visit_example(page):
|
def test_visit_example(page):
|
||||||
page.goto("/admin")
|
page.goto("/admin")
|
||||||
# -> Will result in http://localhost:8080/admin
|
# -> Will result in http://localhost:8080/admin
|
||||||
@ -155,8 +150,7 @@ def test_visit_example(page):
|
|||||||
|
|
||||||
### Ignore HTTPS errors
|
### Ignore HTTPS errors
|
||||||
|
|
||||||
```py
|
```py title="conftest.py"
|
||||||
# conftest.py
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
@ -169,8 +163,7 @@ def browser_context_args(browser_context_args):
|
|||||||
|
|
||||||
### Use custom viewport size
|
### Use custom viewport size
|
||||||
|
|
||||||
```py
|
```py title="conftest.py"
|
||||||
# conftest.py
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
@ -186,8 +179,7 @@ def browser_context_args(browser_context_args):
|
|||||||
|
|
||||||
### Device emulation
|
### Device emulation
|
||||||
|
|
||||||
```py
|
```py title="conftest.py"
|
||||||
# conftest.py
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
@ -203,8 +195,7 @@ Or via the CLI `--device="iPhone 11 Pro"`
|
|||||||
|
|
||||||
### Persistent context
|
### Persistent context
|
||||||
|
|
||||||
```py
|
```py title="conftest.py"
|
||||||
# conftest.py
|
|
||||||
import pytest
|
import pytest
|
||||||
from playwright.sync_api import BrowserType
|
from playwright.sync_api import BrowserType
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
@ -5,8 +5,7 @@ title: "Visual comparisons"
|
|||||||
|
|
||||||
Playwright Test includes the ability to produce and visually compare screenshots using `await expect(page).toHaveScreenshot()`. On first execution, Playwright test will generate reference screenshots. Subsequent runs will compare against the reference.
|
Playwright Test includes the ability to produce and visually compare screenshots using `await expect(page).toHaveScreenshot()`. On first execution, Playwright test will generate reference screenshots. Subsequent runs will compare against the reference.
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test('example test', async ({ page }) => {
|
test('example test', async ({ page }) => {
|
||||||
@ -59,8 +58,7 @@ npx playwright test --update-snapshots
|
|||||||
|
|
||||||
Playwright Test uses the [pixelmatch](https://github.com/mapbox/pixelmatch) library. You can [pass various options](./test-assertions#page-assertions-to-have-screenshot-2) to modify its behavior:
|
Playwright Test uses the [pixelmatch](https://github.com/mapbox/pixelmatch) library. You can [pass various options](./test-assertions#page-assertions-to-have-screenshot-2) to modify its behavior:
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test('example test', async ({ page }) => {
|
test('example test', async ({ page }) => {
|
||||||
@ -84,8 +82,7 @@ Apart from screenshots, you can use `expect(value).toMatchSnapshot(snapshotName)
|
|||||||
|
|
||||||
Here we compare text content against the reference.
|
Here we compare text content against the reference.
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test('example test', async ({ page }) => {
|
test('example test', async ({ page }) => {
|
||||||
|
@ -43,8 +43,7 @@ Here is an example `tsconfig.json` that works with Playwright Test:
|
|||||||
|
|
||||||
You can now import using the mapped paths:
|
You can now import using the mapped paths:
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
import { username, password } from '@myhelper/credentials';
|
import { username, password } from '@myhelper/credentials';
|
||||||
|
|
||||||
|
@ -76,8 +76,7 @@ export default defineConfig({
|
|||||||
|
|
||||||
Now you can use a relative path when navigating the page:
|
Now you can use a relative path when navigating the page:
|
||||||
|
|
||||||
```js
|
```js title="test.spec.ts"
|
||||||
// test.spec.js
|
|
||||||
import { test } from '@playwright/test';
|
import { test } from '@playwright/test';
|
||||||
|
|
||||||
test('test', async ({ page }) => {
|
test('test', async ({ page }) => {
|
||||||
|
@ -68,8 +68,7 @@ Using the following, Playwright will run your WebView2 application as a sub-proc
|
|||||||
|
|
||||||
<!-- source code is available here to verify that the examples are working https://github.com/mxschmitt/playwright-webview2-demo -->
|
<!-- source code is available here to verify that the examples are working https://github.com/mxschmitt/playwright-webview2-demo -->
|
||||||
|
|
||||||
```js
|
```js title="webView2Test.ts"
|
||||||
// webView2Test.ts
|
|
||||||
import { test as base } from '@playwright/test';
|
import { test as base } from '@playwright/test';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
@ -114,8 +113,7 @@ export const test = base.extend({
|
|||||||
export { expect } from '@playwright/test';
|
export { expect } from '@playwright/test';
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js title="example.spec.ts"
|
||||||
// example.spec.ts
|
|
||||||
import { test, expect } from './webView2Test';
|
import { test, expect } from './webView2Test';
|
||||||
|
|
||||||
test('test WebView2', async ({ page }) => {
|
test('test WebView2', async ({ page }) => {
|
||||||
@ -125,8 +123,7 @@ test('test WebView2', async ({ page }) => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java title="WebView2Process.java"
|
||||||
// WebView2Process.java
|
|
||||||
package com.example;
|
package com.example;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@ -200,8 +197,7 @@ public class WebView2Process {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java title="TestExample.java"
|
||||||
// TestExample.java
|
|
||||||
package com.example;
|
package com.example;
|
||||||
|
|
||||||
import com.microsoft.playwright.Browser;
|
import com.microsoft.playwright.Browser;
|
||||||
@ -248,8 +244,7 @@ public class TestExample {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python title="conftest.py"
|
||||||
# conftest.py
|
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
import tempfile
|
import tempfile
|
||||||
@ -331,8 +326,7 @@ def _find_free_port(port=9000, max_port=65535):
|
|||||||
raise IOError("no free ports")
|
raise IOError("no free ports")
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python title="test_webview2.py"
|
||||||
# test_webview2.py
|
|
||||||
from playwright.sync_api import Page, expect
|
from playwright.sync_api import Page, expect
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user