Skip to main content

Playwright

Resilient • No flaky tests

Auto-wait. Playwright waits for elements to be actionable prior to performing actions. It also has a rich set of introspection events. The combination of the two eliminates the need for artificial timeouts - the primary cause of flaky tests.

Web-first assertions. Playwright assertions are created specifically for the dynamic web. Checks are automatically retried until the necessary conditions are met.

Multiple everything. Test scenarios that span multiple tabs, multiple origins and multiple users. Create scenarios with different contexts for different users and run them against your server, all in one test.

Test frames, pierce Shadow DOM. Playwright selectors pierce shadow DOM and allow entering frames seamlessly.

Log in once. Save the authentication state of the context and reuse it in all the tests. This bypasses repetitive log-in operations in each test, yet delivers full isolation of independent tests.

Powerful Tooling

Codegen. Generate tests by recording your actions. Save them into any language.

Playwright inspector. Inspect page, generate selectors, step through the test execution, see click points, explore execution logs.

Trace Viewer. Capture all the information to investigate the test failure. Playwright trace contains test execution screencast, live DOM snapshots, action explorer, test source, and many more.

Important Commands

yarn create playwright // Create Project
yarn playwright test // Run Test
yarn playwright show-report // Run Report Server
yarn playwright test --ui // Debut test in UI mode
yarn playwright test --project webkit --project firefox # Overrride Browser
yarn playwright test tests/todo-page/ tests/landing-page/ # Run Specific tests
yarn playwright test landing login # run test containing landing and login in its name
npx playwright test --debug
npx playwright test example.spec.ts:10 --debug # Debug from a specific line

Basic Test

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

test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
await expect(page).toHaveTitle(/Playwright/);
});

test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
await page.getByRole('link', { name: 'Get started' }).click();
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});

Locator Actions

ActionDescription
locator.check()Check the input checkbox
locator.click()Click the element
locator.uncheck()Uncheck the input checkbox
locator.hover()Hover mouse over the element
locator.fill()Fill the form field, input text
locator.focus()Focus the element
locator.press()Press single key
locator.setInputFiles()Pick files to upload
locator.selectOption()Select option in the drop down

Code

expect(success).toBeTruthy(); # `toEqual`, `toContain`, `toBeTruthy`
await expect(page).toHaveTitle(/Playwright/);
AssertionDescription
expect(locator).toBeChecked()Checkbox is checked
expect(locator).toBeEnabled()Control is enabled
expect(locator).toBeVisible()Element is visible
expect(locator).toContainText()Element contains text
expect(locator).toHaveAttribute()Element has attribute
expect(locator).toHaveCount()List of elements has given length
expect(locator).toHaveText()Element matches text
expect(locator).toHaveValue()Input element has value
expect(page).toHaveTitle()Page has title
expect(page).toHaveURL()Page has URL

Hooks

test.beforeEach and test.afterEach which are executed before/after each test. Other hooks include the test.beforeAll and test.afterAll

Codegen

npx playwright codegen demo.playwright.dev/todomvc

Trace Viewer

npx playwright test --trace on

Test Configuration

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
// Look for test files in the "tests" directory, relative to this configuration file.
testDir: 'tests',

// Run all tests in parallel.
fullyParallel: true,

// Fail the build on CI if you accidentally left test.only in the source code.
forbidOnly: !!process.env.CI,

// Retry on CI only.
retries: process.env.CI ? 2 : 0,

// Opt out of parallel tests on CI.
workers: process.env.CI ? 1 : undefined,

// Reporter to use
reporter: 'html',

use: {
// Base URL to use in actions like `await page.goto('/')`.
baseURL: 'http://127.0.0.1:3000',

// Collect trace when retrying the failed test.
trace: 'on-first-retry',
},
// Configure projects for major browsers.
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
// Run your local dev server before starting the tests.
webServer: {
command: 'npm run start',
url: 'http://127.0.0.1:3000',
reuseExistingServer: !process.env.CI,
},
});
OptionDescription
testConfig.forbidOnlyWhether to exit with an error if any tests are marked as test.only. Useful on CI.
testConfig.fullyParallelhave all tests in all files to run in parallel. See /Parallelism and sharding for more details.
testConfig.projectsRun tests in multiple configurations or on multiple browsers
testConfig.reporterReporter to use. See Test Reporters to learn more about which reporters are available.
testConfig.retriesThe maximum number of retry attempts per test. See Test Retries to learn more about retries.
testConfig.testDirDirectory with the test files.
testConfig.useOptions with use{}
testConfig.webServerTo launch a server during the tests, use the webServer option
testConfig.workersThe maximum number of concurrent worker processes to use for parallelizing tests. Can also be set as percentage of logical CPU cores, e.g. '50%'.. See /Parallelism and sharding for more details.

Save Authentication state

https://playwright.dev/docs/auth

Annotation

test.only('focus this test', async ({ page }) => {  // Run only focused tests in the entire project.});
test.skip('skip this test', async ({ page }) => {  // This test is not run});
test('skip this test', async ({ page, browserName }) => {  test.skip(browserName === 'firefox', 'Still working on it');});
test('skip this test', async ({ page, browserName }) => {  test.skip(browserName === 'firefox', 'Still working on it');});

Groups

import { test, expect } from '@playwright/test';test.describe('two tests', () => {  test('one', async ({ page }) => {    // ...  });  test('two', async ({ page }) => {    // ...  });});

Tags

import { test, expect } from '@playwright/test';test('Test login page @fast', async ({ page }) => {  // ...});test('Test full report @slow', async ({ page }) => {  // ...});
npx playwright test --grep @fast
npx playwright test --grep-invert @slow
npx playwright test --grep "@fast|@slow"

Conditional running tests