docs(node): consolidate JS/TS snippets for guides (#21710)
https://github.com/microsoft/playwright/issues/21385
This commit is contained in:
parent
2074a51299
commit
771abe15fb
|
|
@ -226,37 +226,11 @@ Playwright comes with a range of tooling to help you write tests.
|
|||
|
||||
Playwright makes it easy to test your site across all [browsers](./test-configuration#multiple-browsers) no matter what platform you are on. Testing across all browsers ensures your app works for all users. In your config file you can set up projects adding the name and which browser or device to use.
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
const { devices } = require('@playwright/test');
|
||||
|
||||
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
||||
const config = {
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { type PlaywrightTestConfig, devices } from '@playwright/test';
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
export default defineConfig({
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
|
|
@ -271,8 +245,7 @@ const config: PlaywrightTestConfig = {
|
|||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
],
|
||||
};
|
||||
export default config;
|
||||
});
|
||||
```
|
||||
|
||||
### Keep your Playwright dependency up to date
|
||||
|
|
|
|||
|
|
@ -23,21 +23,7 @@ There are two different strategies when it comes to Test Isolation: start from s
|
|||
|
||||
Playwright uses browser contexts to achieve Test Isolation. Each test has it's own Browser Context. Running the test creates a new browser context each time. When using Playwright as a Test Runner, browser contexts are created by default. Otherwise, you can create browser contexts manually.
|
||||
|
||||
```js tab=js-ts
|
||||
const { test } = require('@playwright/test');
|
||||
|
||||
test('example test', async ({ page, context }) => {
|
||||
// "context" is an isolated BrowserContext, created for this specific test.
|
||||
// "page" belongs to this context.
|
||||
});
|
||||
|
||||
test('another test', async ({ page, context }) => {
|
||||
// "context" and "page" in this second test are completely
|
||||
// isolated from the first test.
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test('example test', async ({ page, context }) => {
|
||||
|
|
@ -87,7 +73,7 @@ Browser contexts can also be used to emulate multi-page scenarios involving mobi
|
|||
|
||||
Playwright can create multiple browser contexts within a single scenario. This is useful when you want to test for multi-user functionality, like a chat.
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test('admin and user', async ({ browser }) => {
|
||||
|
|
@ -101,20 +87,6 @@ test('admin and user', async ({ browser }) => {
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
const { test } = require('@playwright/test');
|
||||
|
||||
test('admin and user', async ({ browser }) => {
|
||||
// Create two isolated browser contexts
|
||||
const adminContext = await browser.newContext();
|
||||
const userContext = await browser.newContext();
|
||||
|
||||
// Create pages and interact with contexts independently
|
||||
const adminPage = await adminContext.newPage();
|
||||
const userPage = await userContext.newPage();
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-library
|
||||
const { chromium } = require('playwright');
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +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:
|
||||
|
||||
```ts
|
||||
```js
|
||||
// fixtures.ts
|
||||
import { test as base, expect, chromium, type BrowserContext } from '@playwright/test';
|
||||
import path from 'path';
|
||||
|
|
@ -184,7 +184,7 @@ def extension_id(context) -> Generator[str, None, None]:
|
|||
|
||||
Then use these fixtures in a test:
|
||||
|
||||
```ts
|
||||
```js
|
||||
import { test, expect } from './fixtures';
|
||||
|
||||
test('example test', async ({ page }) => {
|
||||
|
|
@ -216,7 +216,7 @@ def test_popup_page(page: Page, extension_id: str) -> None:
|
|||
## 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:
|
||||
```ts
|
||||
```js
|
||||
// fixtures.ts
|
||||
// ...
|
||||
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ jobs:
|
|||
|
||||
```
|
||||
Note: The JUnit reporter needs to be configured accordingly via
|
||||
```ts
|
||||
```js
|
||||
["junit", { outputFile: "test-results/e2e-junit-results.xml" }]
|
||||
```
|
||||
in `playwright.config.ts`.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ With Playwright you can test your app on any browser as well as emulate a real d
|
|||
|
||||
Playwright comes with a [registry of device parameters](https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json) using [`property: Playwright.devices`] for selected desktop, tablet and mobile devices. It can be used to simulate browser behavior for a specific device such as user agent, screen size, viewport and if it has touch enabled. All tests will run with the specified device parameters.
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
// playwright.config.ts/js
|
||||
import { defineConfig, devices } from '@playwright/test'; // import devices
|
||||
|
||||
|
|
@ -98,21 +98,27 @@ class Program
|
|||
|
||||
The viewport is included in the device but you can override it for some tests with [`method: Page.setViewportSize`].
|
||||
|
||||
|
||||
```js
|
||||
```js tab=js-test
|
||||
// playwright.config.ts/js
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
use: {
|
||||
// Viewport used for all pages in the context.
|
||||
viewport: { width: 1280, height: 720 },
|
||||
},
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-library
|
||||
// Create context with given viewport
|
||||
const context = await browser.newContext({
|
||||
viewport: { width: 1280, height: 1024 }
|
||||
});
|
||||
```
|
||||
|
||||
Test file:
|
||||
|
||||
```js tab=js-test
|
||||
// example.spec.ts/js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
@ -140,9 +146,10 @@ const context = await browser.newContext({
|
|||
deviceScaleFactor: 2,
|
||||
});
|
||||
```
|
||||
The same works inside a describe block.
|
||||
|
||||
```js
|
||||
The same works inside a test file.
|
||||
|
||||
```js tab=js-test
|
||||
// example.spec.ts/js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
@ -155,6 +162,14 @@ test.describe('specific viewport block', () => {
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-library
|
||||
// Create context with given viewport
|
||||
const context = await browser.newContext({
|
||||
viewport: { width: 1600, height: 1200 }
|
||||
});
|
||||
const page = await context.newPage();
|
||||
```
|
||||
|
||||
```java
|
||||
// Create context with given viewport
|
||||
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
|
||||
|
|
@ -239,7 +254,7 @@ export default defineConfig({
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
// example.spec.ts/js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
@ -294,7 +309,7 @@ await using var context = await browser.NewContextAsync(new()
|
|||
|
||||
Allow app to show system notifications.
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
// playwright.config.ts/js
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
|
|
@ -331,7 +346,7 @@ context = browser.new_context(
|
|||
|
||||
Allow notifications for a specific domain.
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
// example.spec.ts/js
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
|
|
@ -405,7 +420,7 @@ export default defineConfig({
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
// example.spec.ts/js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
@ -459,7 +474,7 @@ await using var context = await browser.NewContextAsync(new()
|
|||
|
||||
Change the location later:
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
// example.spec.ts/js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
@ -509,7 +524,7 @@ export default defineConfig({
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
// example.spec.ts/js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
@ -623,7 +638,7 @@ await page.EmulateMediaAsync(new()
|
|||
|
||||
The User Agent is included in the device and therefore you will rarely need to change it however if you do need to test a different user agent you can override it with the `userAgent` property.
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
// example.spec.ts/js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
@ -664,7 +679,7 @@ var context = await browser.NewContextAsync(new() { UserAgent = "My User Agent"
|
|||
|
||||
Emulate a user scenario where JavaScript is disabled.
|
||||
|
||||
```js tab=js-js
|
||||
```js tab=js-test
|
||||
// example.spec.ts/js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
|
|||
|
|
@ -553,19 +553,7 @@ By default, [`method: Page.getByTestId`] will locate elements based on the `data
|
|||
|
||||
Set the test id to use a custom data attribute for your tests.
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
module.exports = defineConfig({
|
||||
use: {
|
||||
testIdAttribute: 'data-pw'
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ test('loads page without images', async ({ page }) => {
|
|||
|
||||
Perform HTTP Authentication.
|
||||
|
||||
```js tab=js-ts
|
||||
```js tab=js-test
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
use: {
|
||||
|
|
@ -113,7 +113,7 @@ bypass proxy for.
|
|||
|
||||
Here is an example of a global proxy:
|
||||
|
||||
```js tab=js-ts
|
||||
```js tab=js-test
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
use: {
|
||||
|
|
@ -174,7 +174,7 @@ await using var browser = await BrowserType.LaunchAsync(new()
|
|||
|
||||
When specifying proxy for each context individually, **Chromium on Windows** needs a hint that proxy will be set. This is done via passing a non-empty proxy server to the browser itself. Here is an example of a context-specific proxy:
|
||||
|
||||
```js tab=js-ts
|
||||
```js tab=js-test
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
use: {
|
||||
|
|
|
|||
|
|
@ -27,13 +27,7 @@ If you're using (or are interested in using this this feature), please comment o
|
|||
|
||||
You can use [`method: BrowserContext.serviceWorkers`] to list the Service [Worker]s, or specifically watch for the Service [Worker] if you anticipate a page will trigger its [registration](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register):
|
||||
|
||||
```js tab=js-ts
|
||||
const serviceWorkerPromise = context.waitForEvent('serviceworker');
|
||||
await page.goto('/example-with-a-service-worker.html');
|
||||
const serviceworker = await serviceWorkerPromise;
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
```js
|
||||
const serviceWorkerPromise = context.waitForEvent('serviceworker');
|
||||
await page.goto('/example-with-a-service-worker.html');
|
||||
const serviceworker = await serviceWorkerPromise;
|
||||
|
|
@ -67,16 +61,7 @@ Worker serviceWorker = page.waitForRequest(() -> {
|
|||
|
||||
There are more idiomatic methods of waiting for a Service Worker to be activated, but the following is an implementation agnostic method:
|
||||
|
||||
```js tab=js-ts
|
||||
await page.evaluate(async () => {
|
||||
const registration = await window.navigator.serviceWorker.getRegistration();
|
||||
if (registration.active?.state === 'activated')
|
||||
return;
|
||||
await new Promise(res => window.navigator.serviceWorker.addEventListener('controllerchange', res));
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
```js
|
||||
await page.evaluate(async () => {
|
||||
const registration = await window.navigator.serviceWorker.getRegistration();
|
||||
if (registration.active?.state === 'activated')
|
||||
|
|
@ -257,14 +242,7 @@ It's important to note that [`cache.add`](https://developer.mozilla.org/en-US/do
|
|||
|
||||
Once the Service Worker is activated and handling FetchEvents, if the page makes the following requests:
|
||||
|
||||
```js tab=js-ts
|
||||
await page.evaluate(() => fetch('/addressbook.json'));
|
||||
await page.evaluate(() => fetch('/foo'));
|
||||
await page.evaluate(() => fetch('/tracker.js'));
|
||||
await page.evaluate(() => fetch('/fallthrough.txt'));
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
```js
|
||||
await page.evaluate(() => fetch('/addressbook.json'));
|
||||
await page.evaluate(() => fetch('/foo'));
|
||||
await page.evaluate(() => fetch('/tracker.js'));
|
||||
|
|
@ -321,22 +299,7 @@ It's important to note:
|
|||
|
||||
## Routing Service Worker Requests Only
|
||||
|
||||
```js tab=js-ts
|
||||
await context.route('**', async route => {
|
||||
if (route.request().serviceWorker()) {
|
||||
// NB: calling route.request().frame() here would THROW
|
||||
return route.fulfill({
|
||||
contentType: 'text/plain',
|
||||
status: 200,
|
||||
body: 'from sw',
|
||||
});
|
||||
} else {
|
||||
return route.continue();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
```js
|
||||
await context.route('**', async route => {
|
||||
if (route.request().serviceWorker()) {
|
||||
// NB: calling route.request().frame() here would THROW
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Note that each [test project](#projects) can provide its own [options][TestProje
|
|||
|
||||
Here is an example that defines a common timeout and two projects. The "Smoke" project runs a small subset of tests without retries, and "Default" project runs all other tests with retries.
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
|
|
@ -31,28 +31,6 @@ export default defineConfig({
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
timeout: 60000, // Timeout is shared between all tests.
|
||||
projects: [
|
||||
{
|
||||
name: 'Smoke',
|
||||
testMatch: /.*smoke.spec.ts/,
|
||||
retries: 0,
|
||||
},
|
||||
{
|
||||
name: 'Default',
|
||||
testIgnore: /.*smoke.spec.ts/,
|
||||
retries: 2,
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## TestInfo object
|
||||
|
||||
Test functions, fixtures and hooks receive a [TestInfo] parameter that provides information about the currently running test as well as some useful utilities that include:
|
||||
|
|
@ -147,7 +125,7 @@ The `port` (but not the `url`) gets passed over to Playwright as a [`property: T
|
|||
It is also recommended to specify [`property: TestOptions.baseURL`] in the config, so that tests could use relative urls.
|
||||
:::
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
|
|
@ -163,27 +141,9 @@ export default defineConfig({
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
webServer: {
|
||||
command: 'npm run start',
|
||||
url: 'http://localhost:3000/app/',
|
||||
timeout: 120 * 1000,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
},
|
||||
use: {
|
||||
baseURL: 'http://localhost:3000/app/',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Now you can use a relative path when navigating the page:
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// test.spec.ts
|
||||
import { test } from '@playwright/test';
|
||||
test('test', async ({ page }) => {
|
||||
|
|
@ -193,16 +153,6 @@ test('test', async ({ page }) => {
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
// test.spec.js
|
||||
const { test } = require('@playwright/test');
|
||||
test('test', async ({ page }) => {
|
||||
// baseURL is set in the config to http://localhost:3000/app/
|
||||
// This will navigate to http://localhost:3000/app/login
|
||||
await page.goto('./login');
|
||||
});
|
||||
```
|
||||
|
||||
Multiple web servers (or background processes) can be launched simultaneously by providing an array of `webServer` configurations. See [`property: TestConfig.webServer`] for additional examples and documentation.
|
||||
|
||||
## Global setup and teardown
|
||||
|
|
@ -251,21 +201,7 @@ export default globalSetup;
|
|||
|
||||
Specify `globalSetup`, `baseURL` and `storageState` in the configuration file.
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
globalSetup: require.resolve('./global-setup'),
|
||||
use: {
|
||||
baseURL: 'http://localhost:3000/',
|
||||
storageState: 'state.json',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
|
|
@ -279,7 +215,7 @@ export default defineConfig({
|
|||
|
||||
Tests start already authenticated because we specify `storageState` that was populated by global setup.
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test('test', async ({ page }) => {
|
||||
|
|
@ -288,15 +224,6 @@ test('test', async ({ page }) => {
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
const { test } = require('@playwright/test');
|
||||
|
||||
test('test', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
// You are signed in!
|
||||
});
|
||||
```
|
||||
|
||||
You can make arbitrary data available in your tests from your global setup file by setting them as environment variables via `process.env`.
|
||||
|
||||
```js tab=js-js
|
||||
|
|
@ -323,7 +250,7 @@ export default globalSetup;
|
|||
|
||||
Tests have access to the `process.env` properties set in the global setup.
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test('test', async ({ page }) => {
|
||||
|
|
@ -338,21 +265,6 @@ test('test', async ({ page }) => {
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
const { test } = require('@playwright/test');
|
||||
|
||||
test('test', async ({ page }) => {
|
||||
// environment variables which are set in globalSetup are only available inside test().
|
||||
const { FOO, BAR } = process.env;
|
||||
|
||||
// FOO and BAR properties are populated.
|
||||
expect(FOO).toEqual('some data');
|
||||
|
||||
const complexData = JSON.parse(BAR);
|
||||
expect(BAR).toEqual({ some: 'data' });
|
||||
});
|
||||
```
|
||||
|
||||
### Capturing trace of failures during global setup
|
||||
|
||||
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.
|
||||
|
|
@ -426,32 +338,8 @@ Playwright Test supports running multiple test projects at the same time. This i
|
|||
### Same tests, different configuration
|
||||
|
||||
Here is an example that runs the same tests in different browsers:
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
const { devices } = require('@playwright/test');
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
|
|
@ -488,7 +376,7 @@ Each project can be configured separately, and run different set of tests with d
|
|||
|
||||
Here is an example that runs projects with different tests and configurations. The "Smoke" project runs a small subset of tests without retries, and "Default" project runs all other tests with retries.
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
|
|
@ -508,28 +396,6 @@ export default defineConfig({
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
timeout: 60000, // Timeout is shared between all tests.
|
||||
projects: [
|
||||
{
|
||||
name: 'Smoke',
|
||||
testMatch: /.*smoke.spec.ts/,
|
||||
retries: 0,
|
||||
},
|
||||
{
|
||||
name: 'Default',
|
||||
testIgnore: /.*smoke.spec.ts/,
|
||||
retries: 2,
|
||||
},
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
You can run all projects or just a single one:
|
||||
```bash
|
||||
# Run both projects
|
||||
|
|
@ -605,7 +471,7 @@ In this example we add a custom `toBeWithinRange` function in the configuration
|
|||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
const { expect } = require('@playwright/test');
|
||||
const { expect, defineConfig } = require('@playwright/test');
|
||||
|
||||
expect.extend({
|
||||
toBeWithinRange(received, floor, ceiling) {
|
||||
|
|
@ -624,12 +490,12 @@ expect.extend({
|
|||
},
|
||||
});
|
||||
|
||||
module.exports = {};
|
||||
module.exports = defineConfig({});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
// playwright.config.ts
|
||||
import { expect, PlaywrightTestConfig } from '@playwright/test';
|
||||
import { expect, defineConfig } from '@playwright/test';
|
||||
|
||||
expect.extend({
|
||||
toBeWithinRange(received: number, floor: number, ceiling: number) {
|
||||
|
|
@ -648,22 +514,12 @@ expect.extend({
|
|||
},
|
||||
});
|
||||
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({});
|
||||
```
|
||||
|
||||
Now we can use `toBeWithinRange` in the test.
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('numeric ranges', () => {
|
||||
expect(100).toBeWithinRange(90, 110);
|
||||
expect(101).not.toBeWithinRange(0, 100);
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
|
|||
|
|
@ -15,13 +15,7 @@ Annotations can be used on a single test or a group of tests. Annotations can be
|
|||
|
||||
You can focus some tests. When there are focused tests, only these tests run.
|
||||
|
||||
```js tab=js-js
|
||||
test.only('focus this test', async ({ page }) => {
|
||||
// Run only focused tests in the entire project.
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
test.only('focus this test', async ({ page }) => {
|
||||
// Run only focused tests in the entire project.
|
||||
});
|
||||
|
|
@ -31,13 +25,7 @@ test.only('focus this test', async ({ page }) => {
|
|||
|
||||
Mark a test as skipped.
|
||||
|
||||
```js tab=js-js
|
||||
test.skip('skip this test', async ({ page }) => {
|
||||
// This test is not run
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
test.skip('skip this test', async ({ page }) => {
|
||||
// This test is not run
|
||||
});
|
||||
|
|
@ -47,13 +35,7 @@ test.skip('skip this test', async ({ page }) => {
|
|||
|
||||
You can skip certain test based on the condition.
|
||||
|
||||
```js tab=js-js
|
||||
test('skip this test', async ({ page, browserName }) => {
|
||||
test.skip(browserName === 'firefox', 'Still working on it');
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
test('skip this test', async ({ page, browserName }) => {
|
||||
test.skip(browserName === 'firefox', 'Still working on it');
|
||||
});
|
||||
|
|
@ -63,21 +45,7 @@ test('skip this test', async ({ page, browserName }) => {
|
|||
|
||||
You can group tests to give them a logical name or to scope before/after hooks to the group.
|
||||
|
||||
```js tab=js-js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test.describe('two tests', () => {
|
||||
test('one', async ({ page }) => {
|
||||
// ...
|
||||
});
|
||||
|
||||
test('two', async ({ page }) => {
|
||||
// ...
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('two tests', () => {
|
||||
|
|
@ -95,19 +63,7 @@ test.describe('two tests', () => {
|
|||
|
||||
Sometimes you want to tag your tests as `@fast` or `@slow` and only run the tests that have the certain tag. We recommend that you use the `--grep` and `--grep-invert` command line flags for that:
|
||||
|
||||
```js tab=js-js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('Test login page @fast', async ({ page }) => {
|
||||
// ...
|
||||
});
|
||||
|
||||
test('Test full report @slow', async ({ page }) => {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('Test login page @fast', async ({ page }) => {
|
||||
|
|
@ -135,27 +91,7 @@ npx playwright test --grep-invert @slow
|
|||
|
||||
For example, you can run a group of tests just in Chromium by passing a callback.
|
||||
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
|
||||
test.describe('chromium only', () => {
|
||||
test.skip(({ browserName }) => browserName !== 'chromium', 'Chromium only!');
|
||||
|
||||
test.beforeAll(async () => {
|
||||
// This hook is only run in Chromium.
|
||||
});
|
||||
|
||||
test('test 1', async ({ page }) => {
|
||||
// This test is only run in Chromium.
|
||||
});
|
||||
|
||||
test('test 2', async ({ page }) => {
|
||||
// This test is only run in Chromium.
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
|
||||
test.describe('chromium only', () => {
|
||||
|
|
@ -179,22 +115,7 @@ test.describe('chromium only', () => {
|
|||
|
||||
To avoid running `beforeEach` hooks, you can put annotations in the hook itself.
|
||||
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
|
||||
test.beforeEach(async ({ page, isMobile }) => {
|
||||
test.fixme(isMobile, 'Settings page does not work in mobile yet');
|
||||
|
||||
await page.goto('http://localhost:3000/settings');
|
||||
});
|
||||
|
||||
test('user profile', async ({ page }) => {
|
||||
await page.getByText('My Profile').click();
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
|
||||
test.beforeEach(async ({ page, isMobile }) => {
|
||||
|
|
@ -213,16 +134,8 @@ 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'`.
|
||||
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
|
||||
test('user profile', async ({ page }) => {
|
||||
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/<some-issue>' });
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
|
||||
test('user profile', async ({ page }) => {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ The following example demonstrates how to use Playwright to test issues creation
|
|||
|
||||
GitHub API requires authorization, so we'll configure the token once for all tests. While at it, we'll also set the `baseURL` to simplify the tests. You can either put them in the configuration file, or in the test file with `test.use()`.
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
|
|
@ -47,26 +47,6 @@ export default defineConfig({
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
use: {
|
||||
// All requests we send go to this API endpoint.
|
||||
baseURL: 'https://api.github.com',
|
||||
extraHTTPHeaders: {
|
||||
// We set this header per GitHub guidelines.
|
||||
'Accept': 'application/vnd.github.v3+json',
|
||||
// Add authorization token to all requests.
|
||||
// Assuming personal access token available in the environment.
|
||||
'Authorization': `token ${process.env.API_TOKEN}`,
|
||||
},
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Writing tests
|
||||
|
||||
Playwright Test comes with the built-in `request` fixture that respects configuration options like `baseURL` or `extraHTTPHeaders` we specified and is ready to send some requests.
|
||||
|
|
@ -138,7 +118,7 @@ test.afterAll(async ({ request }) => {
|
|||
Behind the scenes, [`request` fixture](./api/class-fixtures#fixtures-request) will actually call [`method: APIRequest.newContext`]. You can always do that manually if you'd like more control. Below is a standalone script that does the same as `beforeAll` and `afterAll` from above.
|
||||
|
||||
```js
|
||||
const { request } = require('@playwright/test');
|
||||
import { request } from '@playwright/test';
|
||||
const REPO = 'test-repo-1';
|
||||
const USER = 'github-username';
|
||||
|
||||
|
|
@ -180,7 +160,7 @@ While running tests inside browsers you may want to make calls to the HTTP API o
|
|||
The following test creates a new issue via API and then navigates to the list of all issues in the
|
||||
project to check that it appears at the top of the list.
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
const REPO = 'test-repo-1';
|
||||
|
|
@ -222,55 +202,12 @@ test('last created issue should be first in the list', async ({ page }) => {
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
// @ts-check
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
const REPO = 'test-repo-1';
|
||||
const USER = 'github-username';
|
||||
|
||||
// Request context is reused by all tests in the file.
|
||||
let apiContext;
|
||||
|
||||
test.beforeAll(async ({ playwright }) => {
|
||||
apiContext = await playwright.request.newContext({
|
||||
// All requests we send go to this API endpoint.
|
||||
baseURL: 'https://api.github.com',
|
||||
extraHTTPHeaders: {
|
||||
// We set this header per GitHub guidelines.
|
||||
'Accept': 'application/vnd.github.v3+json',
|
||||
// Add authorization token to all requests.
|
||||
// Assuming personal access token available in the environment.
|
||||
'Authorization': `token ${process.env.API_TOKEN}`,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
test.afterAll(async ({ }) => {
|
||||
// Dispose all responses.
|
||||
await apiContext.dispose();
|
||||
});
|
||||
|
||||
test('last created issue should be first in the list', async ({ page }) => {
|
||||
const newIssue = await apiContext.post(`/repos/${USER}/${REPO}/issues`, {
|
||||
data: {
|
||||
title: '[Feature] request 1',
|
||||
}
|
||||
});
|
||||
expect(newIssue.ok()).toBeTruthy();
|
||||
|
||||
await page.goto(`https://github.com/${USER}/${REPO}/issues`);
|
||||
const firstIssue = page.locator(`a[data-hovercard-type='issue']`).first();
|
||||
await expect(firstIssue).toHaveText('[Feature] request 1');
|
||||
});
|
||||
```
|
||||
|
||||
### Validating postconditions
|
||||
|
||||
The following test creates a new issue via user interface in the browser and then uses checks if
|
||||
it was created via API:
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
const REPO = 'test-repo-1';
|
||||
|
|
@ -314,51 +251,6 @@ test('last created issue should be on the server', async ({ page, request }) =>
|
|||
});
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
// @ts-check
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
const REPO = 'test-repo-1';
|
||||
const USER = 'github-username';
|
||||
|
||||
// Request context is reused by all tests in the file.
|
||||
let apiContext;
|
||||
|
||||
test.beforeAll(async ({ playwright }) => {
|
||||
apiContext = await playwright.request.newContext({
|
||||
// All requests we send go to this API endpoint.
|
||||
baseURL: 'https://api.github.com',
|
||||
extraHTTPHeaders: {
|
||||
// We set this header per GitHub guidelines.
|
||||
'Accept': 'application/vnd.github.v3+json',
|
||||
// Add authorization token to all requests.
|
||||
// Assuming personal access token available in the environment.
|
||||
'Authorization': `token ${process.env.API_TOKEN}`,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
test.afterAll(async ({ }) => {
|
||||
// Dispose all responses.
|
||||
await apiContext.dispose();
|
||||
});
|
||||
|
||||
test('last created issue should be on the server', async ({ page, request }) => {
|
||||
await page.goto(`https://github.com/${USER}/${REPO}/issues`);
|
||||
await page.getByText('New Issue').click();
|
||||
await page.getByRole('textbox', { name: 'Title' }).fill('Bug report 1');
|
||||
await page.getByRole('textbox', { name: 'Comment body' }).fill('Bug description');
|
||||
await page.getByText('Submit new issue').click();
|
||||
const issueId = page.url().substr(page.url().lastIndexOf('/'));
|
||||
|
||||
const newIssue = await request.get(`https://api.github.com/repos/${USER}/${REPO}/issues/${issueId}`);
|
||||
expect(newIssue.ok()).toBeTruthy();
|
||||
expect(newIssue.json()).toEqual(expect.objectContaining({
|
||||
title: 'Bug report 1'
|
||||
}));
|
||||
});
|
||||
```
|
||||
|
||||
## Reusing authentication state
|
||||
|
||||
Web apps use cookie-based or token-based authentication, where authenticated
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ test('should work', async ({ mount }) => {
|
|||
|
||||
If using TypeScript and Vue make sure to add a `vue.d.ts` file to your project:
|
||||
|
||||
```ts
|
||||
```js
|
||||
declare module '*.vue';
|
||||
```
|
||||
|
||||
|
|
@ -393,7 +393,7 @@ export default defineConfig({
|
|||
|
||||
### Q) What's the difference between `@playwright/test` and `@playwright/experimental-ct-{react,svelte,vue,solid}`?
|
||||
|
||||
```ts
|
||||
```js
|
||||
test('…', async { mount, page, context } => {
|
||||
// …
|
||||
});
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ In this example we add a custom `toBeWithinRange` function in the configuration
|
|||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
const { expect } = require('@playwright/test');
|
||||
const { expect, defineConfig } = require('@playwright/test');
|
||||
|
||||
expect.extend({
|
||||
toBeWithinRange(received, floor, ceiling) {
|
||||
|
|
@ -175,12 +175,12 @@ expect.extend({
|
|||
},
|
||||
});
|
||||
|
||||
module.exports = {};
|
||||
module.exports = defineConfig({});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
// playwright.config.ts
|
||||
import { expect, PlaywrightTestConfig } from '@playwright/test';
|
||||
import { expect, defineConfig } from '@playwright/test';
|
||||
|
||||
expect.extend({
|
||||
toBeWithinRange(received: number, floor: number, ceiling: number) {
|
||||
|
|
@ -199,22 +199,12 @@ expect.extend({
|
|||
},
|
||||
});
|
||||
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({});
|
||||
```
|
||||
|
||||
Now we can use `toBeWithinRange` in the test.
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('numeric ranges', () => {
|
||||
expect(100).toBeWithinRange(90, 110);
|
||||
expect(101).not.toBeWithinRange(0, 100);
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
|
|||
|
|
@ -9,17 +9,7 @@ Playwright Test is based on the concept of test fixtures. Test fixtures are used
|
|||
|
||||
You have already used test fixtures in your first test.
|
||||
|
||||
```js tab=js-js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('basic test', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev/');
|
||||
|
||||
await expect(page).toHaveTitle(/Playwright/);
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('basic test', async ({ page }) => {
|
||||
|
|
@ -256,18 +246,7 @@ test('basic test', async ({ todoPage, page }) => {
|
|||
|
||||
In addition to creating your own fixtures, you can also override existing fixtures to fit your needs. Consider the following example which overrides the `page` fixture by automatically navigating to some `baseURL`:
|
||||
|
||||
```js tab=js-js
|
||||
const base = require('@playwright/test');
|
||||
|
||||
exports.test = base.test.extend({
|
||||
page: async ({ baseURL, page }, use) => {
|
||||
await page.goto(baseURL);
|
||||
await use(page);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test as base } from '@playwright/test';
|
||||
|
||||
export const test = base.extend({
|
||||
|
|
@ -280,13 +259,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`].
|
||||
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
|
||||
test.use({ baseURL: 'https://playwright.dev' });
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
|
||||
test.use({ baseURL: 'https://playwright.dev' });
|
||||
|
|
@ -294,18 +267,7 @@ test.use({ baseURL: 'https://playwright.dev' });
|
|||
|
||||
Fixtures can also be overridden where the base fixture is completely replaced with something different. For example, we could override the [`property: TestOptions.storageState`] fixture to provide our own data.
|
||||
|
||||
```js tab=js-js
|
||||
const base = require('@playwright/test');
|
||||
|
||||
exports.test = base.test.extend({
|
||||
storageState: async ({}, use) => {
|
||||
const cookie = await getAuthCookie();
|
||||
await use({ cookies: [cookie] });
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test as base } from '@playwright/test';
|
||||
|
||||
export const test = base.extend({
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ export default globalSetup;
|
|||
Tests have access to the `process.env` properties set in the global setup.
|
||||
|
||||
```js
|
||||
const { test } = require('@playwright/test');
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test('test', async ({ page }) => {
|
||||
// environment variables which are set in globalSetup are only available inside test().
|
||||
|
|
|
|||
|
|
@ -53,16 +53,7 @@ By default, tests in a single file are run in order. If you have many independen
|
|||
|
||||
Note that parallel tests are executed in separate worker processes and cannot share any state or global variables. Each test executes all relevant hooks just for itself, including `beforeAll` and `afterAll`.
|
||||
|
||||
```js tab=js-js
|
||||
const { test } = require('@playwright/test');
|
||||
|
||||
test.describe.configure({ mode: 'parallel' });
|
||||
|
||||
test('runs in parallel 1', async ({ page }) => { /* ... */ });
|
||||
test('runs in parallel 2', async ({ page }) => { /* ... */ });
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test.describe.configure({ mode: 'parallel' });
|
||||
|
|
|
|||
|
|
@ -7,18 +7,7 @@ You can either parameterize tests on a test level or on a project level.
|
|||
|
||||
## Parameterized Tests
|
||||
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
const people = ['Alice', 'Bob'];
|
||||
for (const name of people) {
|
||||
test(`testing with ${name}`, async () => {
|
||||
// ...
|
||||
});
|
||||
// You can also do it with test.describe() or with multiple tests as long the test name is unique.
|
||||
}
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
const people = ['Alice', 'Bob'];
|
||||
for (const name of people) {
|
||||
|
|
@ -63,18 +52,7 @@ export const test = base.extend<TestOptions>({
|
|||
|
||||
We can use this option in the test, similarly to [fixtures](./test-fixtures.md).
|
||||
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
const { test } = require('./my-test');
|
||||
|
||||
test('test 1', async ({ page, person }) => {
|
||||
await page.goto(`/index.html`);
|
||||
await expect(page.locator('#node')).toContainText(person);
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
import { test } from './my-test';
|
||||
|
||||
|
|
@ -182,16 +160,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.
|
||||
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
test(`example test`, async ({ page }) => {
|
||||
// ...
|
||||
await page.getByLabel('User Name').fill(process.env.USERNAME);
|
||||
await page.getByLabel('Password').fill(process.env.PASSWORD);
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
test(`example test`, async ({ page }) => {
|
||||
// ...
|
||||
|
|
@ -220,21 +189,7 @@ npx playwright test
|
|||
|
||||
Similarly, configuration file can also read environment variables passed through the command line.
|
||||
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
use: {
|
||||
baseURL: process.env.STAGING === '1' ? 'http://staging.example.test/' : 'http://example.test/',
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
|
|
@ -265,26 +220,7 @@ npx playwright test
|
|||
|
||||
To make environment variables easier to manage, consider something like `.env` files. Here is an example that uses [`dotenv`](https://www.npmjs.com/package/dotenv) package to read environment variables directly in the configuration file.
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
|
||||
// Read from default ".env" file.
|
||||
require('dotenv').config();
|
||||
|
||||
// Alternatively, read from "../my.env" file.
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '..', 'my.env') });
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
use: {
|
||||
baseURL: process.env.STAGING === '1' ? 'http://staging.example.test/' : 'http://example.test/',
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
import dotenv from 'dotenv';
|
||||
|
|
@ -334,7 +270,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:
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// foo.spec.ts
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
|
@ -352,22 +288,3 @@ for (const record of records) {
|
|||
});
|
||||
}
|
||||
```
|
||||
|
||||
```js tab=js-js
|
||||
// foo.spec.js
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { test } = require('@playwright/test');
|
||||
const { parse } = require('csv-parse/sync');
|
||||
|
||||
const records = parse(fs.readFileSync(path.join(__dirname, 'input.csv')), {
|
||||
columns: true,
|
||||
skip_empty_lines: true
|
||||
});
|
||||
|
||||
for (const record of records) {
|
||||
test(`fooo: ${record.test_case}`, async ({ page }) => {
|
||||
console.log(record.test_case, record.some_value, record.some_other_value);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -11,18 +11,7 @@ Playwright Test runs tests in worker processes. These processes are OS processes
|
|||
|
||||
Consider the following snippet:
|
||||
|
||||
```js tab=js-js
|
||||
const { test } = require('@playwright/test');
|
||||
|
||||
test.describe('suite', () => {
|
||||
test.beforeAll(async () => { /* ... */ });
|
||||
test('first good', async ({ page }) => { /* ... */ });
|
||||
test('second flaky', async ({ page }) => { /* ... */ });
|
||||
test('third good', async ({ page }) => { /* ... */ });
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test.describe('suite', () => {
|
||||
|
|
@ -101,17 +90,7 @@ Running 3 tests using 1 worker
|
|||
|
||||
You can detect retries at runtime with [`property: TestInfo.retry`], which is accessible to any test, hook or fixture. Here is an example that clears some server-side state before a retry.
|
||||
|
||||
```js tab=js-js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('my test', async ({ page }, testInfo) => {
|
||||
if (testInfo.retry)
|
||||
await cleanSomeCachesOnTheServer();
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('my test', async ({ page }, testInfo) => {
|
||||
|
|
@ -123,24 +102,7 @@ test('my test', async ({ page }, testInfo) => {
|
|||
|
||||
You can specify retries for a specific group of tests or a single file with [`method: Test.describe.configure`].
|
||||
|
||||
```js tab=js-js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test.describe(() => {
|
||||
// All tests in this describe group will get 2 retry attempts.
|
||||
test.describe.configure({ retries: 2 });
|
||||
|
||||
test('test 1', async ({ page }) => {
|
||||
// ...
|
||||
});
|
||||
|
||||
test('test 2', async ({ page }) => {
|
||||
// ...
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe(() => {
|
||||
|
|
@ -163,18 +125,7 @@ Use [`method: Test.describe.serial`] to group dependent tests to ensure they wil
|
|||
|
||||
Consider the following snippet that uses `test.describe.serial`:
|
||||
|
||||
```js tab=js-js
|
||||
const { test } = require('@playwright/test');
|
||||
|
||||
test.describe.configure({ mode: 'serial' });
|
||||
|
||||
test.beforeAll(async () => { /* ... */ });
|
||||
test('first good', async ({ page }) => { /* ... */ });
|
||||
test('second flaky', async ({ page }) => { /* ... */ });
|
||||
test('third good', async ({ page }) => { /* ... */ });
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test.describe.configure({ mode: 'serial' });
|
||||
|
|
|
|||
|
|
@ -5,17 +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.
|
||||
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('example test', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev');
|
||||
await expect(page).toHaveScreenshot();
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
@ -44,10 +34,7 @@ drwxr-xr-x 3 user group 96 Jun 4 11:46 example.spec.ts-snapshots
|
|||
|
||||
The snapshot name `example-test-1-chromium-darwin.png` consists of a few parts:
|
||||
- `example-test-1.png` - an auto-generated name of the snapshot. Alternatively you can specify snapshot name as the first argument of the `toHaveScreenshot()` method:
|
||||
```js tab=js-js
|
||||
await expect(page).toHaveScreenshot('landing.png');
|
||||
```
|
||||
```js tab=js-ts
|
||||
```js
|
||||
await expect(page).toHaveScreenshot('landing.png');
|
||||
```
|
||||
|
||||
|
|
@ -72,17 +59,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:
|
||||
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('example test', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev');
|
||||
await expect(page).toHaveScreenshot({ maxDiffPixels: 100 });
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
@ -94,15 +71,7 @@ test('example test', async ({ page }) => {
|
|||
|
||||
If you'd like to share the default value among all the tests in the project, you can specify it in the playwright config, either globally or per project:
|
||||
|
||||
```js tab=js-js
|
||||
module.exports = {
|
||||
expect: {
|
||||
toHaveScreenshot: { maxDiffPixels: 100 },
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
expect: {
|
||||
|
|
@ -115,17 +84,7 @@ Apart from screenshots, you can use `expect(value).toMatchSnapshot(snapshotName)
|
|||
|
||||
Here we compare text content against the reference.
|
||||
|
||||
```js tab=js-js
|
||||
// example.spec.js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('example test', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev');
|
||||
expect(await page.textContent('.hero__title')).toMatchSnapshot('hero.txt');
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
|
|
|
|||
|
|
@ -31,18 +31,7 @@ The same timeout value also applies to `beforeAll` and `afterAll` hooks, but the
|
|||
|
||||
### Set test timeout in the config
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
timeout: 5 * 60 * 1000,
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
|
|
@ -55,21 +44,7 @@ API reference: [`property: TestConfig.timeout`].
|
|||
|
||||
### Set timeout for a single test
|
||||
|
||||
```js tab=js-js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('slow test', async ({ page }) => {
|
||||
test.slow(); // Easy way to triple the default timeout
|
||||
// ...
|
||||
});
|
||||
|
||||
test('very slow test', async ({ page }) => {
|
||||
test.setTimeout(120000);
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('slow test', async ({ page }) => {
|
||||
|
|
@ -87,16 +62,7 @@ API reference: [`method: Test.setTimeout`] and [`method: Test.slow#1`].
|
|||
|
||||
### Change timeout from a `beforeEach` hook
|
||||
|
||||
```js tab=js-js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test.beforeEach(async ({ page }, testInfo) => {
|
||||
// Extend timeout for all tests running this hook by 30 seconds.
|
||||
testInfo.setTimeout(testInfo.timeout + 30000);
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.beforeEach(async ({ page }, testInfo) => {
|
||||
|
|
@ -111,16 +77,7 @@ API reference: [`method: TestInfo.setTimeout`].
|
|||
|
||||
`beforeAll` and `afterAll` hooks have a separate timeout, by default equal to test timeout. You can change it separately for each hook by calling [`method: TestInfo.setTimeout`] inside the hook.
|
||||
|
||||
```js tab=js-js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test.beforeAll(async () => {
|
||||
// Set timeout for this hook.
|
||||
test.setTimeout(60000);
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.beforeAll(async () => {
|
||||
|
|
@ -149,20 +106,7 @@ Call log:
|
|||
|
||||
### Set expect timeout in the config
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
expect: {
|
||||
timeout: 10 * 1000,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
|
|
@ -177,15 +121,7 @@ API reference: [`property: TestConfig.expect`].
|
|||
|
||||
### Set timeout for a single assertion
|
||||
|
||||
```js tab=js-js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('basic test', async ({ page }) => {
|
||||
await expect(page.getByRole('button')).toHaveText('Sign in', { timeout: 10000 });
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('basic test', async ({ page }) => {
|
||||
|
|
@ -210,21 +146,7 @@ Playwright also allows to set a separate timeout for navigation actions like `pa
|
|||
|
||||
### Set action and navigation timeouts in the config
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
use: {
|
||||
actionTimeout: 10 * 1000,
|
||||
navigationTimeout: 30 * 1000,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
|
|
@ -240,16 +162,7 @@ API reference: [`property: TestOptions.actionTimeout`] and [`property: TestOptio
|
|||
|
||||
### Set timeout for a single action
|
||||
|
||||
```js tab=js-js
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test('basic test', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev', { timeout: 30000 });
|
||||
await page.getByText('Get Started').click({ timeout: 10000 });
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test('basic test', async ({ page }) => {
|
||||
|
|
@ -272,18 +185,7 @@ Running 1000 tests using 10 workers
|
|||
|
||||
You can set global timeout in the config.
|
||||
|
||||
```js tab=js-js
|
||||
// playwright.config.js
|
||||
// @ts-check
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
globalTimeout: 60 * 60 * 1000,
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
// playwright.config.ts
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ Now you can use a relative path when navigating the page:
|
|||
|
||||
```js
|
||||
// test.spec.js
|
||||
const { test } = require('@playwright/test');
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
test('test', async ({ page }) => {
|
||||
// This will navigate to http://127.0.0.1:3000/login
|
||||
|
|
|
|||
|
|
@ -21,21 +21,7 @@ Playwright Trace Viewer is a GUI tool that lets you explore recorded Playwright
|
|||
|
||||
By default the [playwright.config](/test-configuration.md#record-test-trace) file will contain the configuration needed to create a `trace.zip` file for each test. Traces are setup to run `on-first-retry` meaning they will be run on the first retry of a failed test. Also `retries` are set to 2 when running on CI and 0 locally. This means the traces will be recorded on the first retry of a failed test but not on the first run and not on the second retry.
|
||||
|
||||
```js tab=js-js
|
||||
// @ts-check
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
retries: process.env.CI ? 2 : 0, // set to 2 when running on CI
|
||||
...
|
||||
use: {
|
||||
trace: 'on-first-retry', // record traces on first retry of each test
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
retries: process.env.CI ? 2 : 0, // set to 2 when running on CI
|
||||
|
|
|
|||
|
|
@ -142,20 +142,7 @@ npx playwright show-report
|
|||
Traces should be run on continuous integration on the first retry of a failed test
|
||||
by setting the `trace: 'on-first-retry'` option in the test configuration file. This will produce a `trace.zip` file for each test that was retried.
|
||||
|
||||
```js tab=js-js
|
||||
// @ts-check
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
retries: 1,
|
||||
use: {
|
||||
trace: 'on-first-retry',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js tab=js-test
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
retries: 1,
|
||||
|
|
|
|||
|
|
@ -19,19 +19,7 @@ Video files will appear in the test output directory, typically `test-results`.
|
|||
|
||||
Videos are saved upon [browser context](./browser-contexts.md) closure at the end of a test. If you create a browser context manually, make sure to await [`method: BrowserContext.close`].
|
||||
|
||||
```js tab=js-js
|
||||
// @ts-check
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
use: {
|
||||
video: 'on-first-retry',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js tab=js-test
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
use: {
|
||||
|
|
@ -48,22 +36,7 @@ await context.close();
|
|||
|
||||
You can also specify video size. The video size defaults to the viewport size scaled down to fit 800x800. The video of the viewport is placed in the top-left corner of the output video, scaled down to fit if necessary. You may need to set the viewport size to match your desired video size.
|
||||
|
||||
```js tab=js-js
|
||||
// @ts-check
|
||||
|
||||
const { defineConfig } = require('@playwright/test');
|
||||
|
||||
module.exports = defineConfig({
|
||||
use: {
|
||||
video: {
|
||||
mode: 'on-first-retry',
|
||||
size: { width: 640, height: 480 }
|
||||
}
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
```js tab=js-test
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
use: {
|
||||
|
|
@ -88,15 +61,7 @@ For multi-page scenarios, you can access the video file associated with the page
|
|||
[`method: Page.video`].
|
||||
|
||||
|
||||
```js tab=js-js
|
||||
const path = await page.video().path();
|
||||
```
|
||||
|
||||
```js tab=js-ts
|
||||
const path = await page.video().path();
|
||||
```
|
||||
|
||||
```js tab=js-library
|
||||
```js
|
||||
const path = await page.video().path();
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +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 -->
|
||||
|
||||
```ts
|
||||
```js
|
||||
// webView2Test.ts
|
||||
import { test as base } from '@playwright/test';
|
||||
import fs from 'fs';
|
||||
|
|
@ -114,7 +114,7 @@ export const test = base.extend({
|
|||
export { expect } from '@playwright/test';
|
||||
```
|
||||
|
||||
```ts
|
||||
```js
|
||||
// example.spec.ts
|
||||
import { test, expect } from './webView2Test';
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue