Draft page
Access: Prod

Playwright

Playwright is a modern browser automation framework with a built-in test runner, strict locators, web-first assertions, traces, reports, and a strong local development workflow.

This tutorial teaches the Playwright workflow first, then explains the remote Selenium mode that existing webmate documentation uses. That distinction matters: normal Playwright can drive Chromium, Firefox, and WebKit through Playwright’s own browser protocol, while the webmate integration path documented in this repository uses Playwright’s Selenium Grid support and is limited to Chromium-based browsers.

Goal

By the end of this tutorial you will have a small Playwright suite that can run locally, produce useful traces, fit into CI, and be adapted for the documented webmate remote endpoint when Chromium execution through Selenium is the right tradeoff.

Before You Start

You need Node.js, access to the application under test, and a test project where Playwright can install its browser dependencies. For the webmate path, you also need a webmate API key, project ID, Selenium remote URL, and capabilities for the target browser and platform.

Playwright is most productive when test code describes user-visible behavior. Favor role, label, placeholder, and text locators before CSS selectors. That makes tests less sensitive to markup changes and closer to how users and accessibility tools understand the page.

Project Setup

Initialize Playwright in an application repository:

1
npm init playwright@latest

The initializer creates a config file, a tests folder, and examples. A minimal test looks like this:

1
2
3
4
5
6
7
import { test, expect } from '@playwright/test';

test('documentation search opens results', async ({ page }) => {
  await page.goto('https://docs.webmate.io/');
  await page.getByRole('searchbox').fill('Playwright');
  await expect(page).toHaveTitle(/webmate/i);
});

The page fixture is an isolated browser page for the test. Playwright handles browser lifecycle, context isolation, tracing configuration, retries, reporters, and parallelism through the test runner.

Step 1: Use Locators as Contracts

Playwright locators wait automatically before actions and assertions. Use them as named contracts for the UI rather than one-off DOM queries.

1
2
3
4
5
6
const email = page.getByLabel('Email');
const submit = page.getByRole('button', { name: 'Sign in' });

await email.fill('tester@example.com');
await submit.click();
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();

Good locators make failures readable. If getByRole('button', { name: 'Sign in' }) fails, the page either lacks the button or exposes it incorrectly. That is more useful than a generated class selector failing after a harmless style change.

Step 2: Prefer Web-First Assertions

Playwright assertions retry until the condition is met or the timeout expires. This reduces the need for manual sleeps.

1
2
3
await expect(page.getByTestId('toast')).toContainText('Saved');
await expect(page.getByRole('button', { name: 'Delete' })).toBeEnabled();
await expect(page).toHaveURL(/\/projects\/\d+$/);

Use explicit waits only when waiting for a non-UI event that is not already covered by an action or assertion. If a test needs many custom waits, the application may need better observable states or test IDs.

Step 3: Record Traces for Debugging

Traces are one of Playwright’s strongest debugging tools. They capture actions, snapshots, network activity, console messages, and screenshots depending on configuration.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
  },
});

Run tests normally:

1
npx playwright test

Then inspect a trace:

1
npx playwright show-trace test-results/example/trace.zip

For local development, npx playwright test --ui is useful for exploring failures interactively. In CI, keep trace and report artifacts so reviewers can diagnose failures without rerunning the job.

Step 4: Configure Projects and CI

Playwright projects define browser and device variants. Keep the default matrix small for pull requests and expand it for nightly or release checks.

1
2
3
4
5
6
7
export default defineConfig({
  projects: [
    { name: 'chromium', use: { browserName: 'chromium' } },
    { name: 'firefox', use: { browserName: 'firefox' } },
    { name: 'webkit', use: { browserName: 'webkit' } },
  ],
});

A CI job normally installs dependencies, installs Playwright browsers, starts the application, and runs tests:

1
2
3
4
5
npm ci
npx playwright install --with-deps
npm run build
npm run start &
npx playwright test

Use retries sparingly. A retry can absorb transient infrastructure noise, but it should not hide deterministic race conditions.

Step 5: Understand Remote Selenium Mode

Playwright can connect to a Selenium Grid by setting SELENIUM_REMOTE_URL. In the existing webmate docs, this is the path used to run Playwright tests on webmate infrastructure.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
export SELENIUM_REMOTE_URL="https://selenium.webmate.io/wd/hub"
export SELENIUM_REMOTE_CAPABILITIES='{
  "browserName": "chrome",
  "platformName": "WINDOWS_11_64",
  "browserVersion": "latest",
  "wm:apikey": "YOUR_API_KEY",
  "wm:project": "YOUR_PROJECT_ID"
}'

npx playwright test --project=chromium

Treat this mode as a compatibility bridge, not as a replacement for all Playwright-native browser execution. The current repository documentation states that Playwright tests can only use Chromium-based browsers when executed against an external Selenium service such as webmate.

How This Maps to webmate

Use normal Playwright locally when you want the full Playwright browser matrix, fast feedback, UI mode, and native traces. Use the webmate Selenium path when the important requirement is running Chromium-based Playwright tests against webmate-managed desktop browser infrastructure.

Name and tag sessions through capabilities where the webmate Selenium endpoint supports it. Keep API keys and project IDs in environment variables. Link failures back to the corresponding test run so the trace, Playwright report, and webmate session evidence tell the same story.

Troubleshooting

If Playwright cannot find a browser locally, run npx playwright install and verify the project config. If a locator fails, use the trace viewer and accessibility snapshot to see what the page actually exposes. If remote session creation fails, check SELENIUM_REMOTE_URL, JSON escaping in SELENIUM_REMOTE_CAPABILITIES, browser name, platform name, project ID, and API key.

If a test passes locally but fails remotely, compare browser channel, viewport, operating system, base URL, authentication state, and network access. Remote execution changes the environment. Keep the test deterministic by creating its own data and avoiding hidden dependencies on local storage, cookies, or developer-only services.

Verify the Result

A useful Playwright setup can run locally with npx playwright test, produce traces for failures, and run in CI with preserved reports. If you use the webmate route, a successful run should create a remote Chromium session and leave enough metadata in webmate to identify the test and inspect the browser session.

Next Steps

Read the existing Playwright Web Testing page for the current webmate-specific environment variables, and use the Web Testing section when you need deeper Selenium capability and device information.