Your First Playwright Test
A Playwright test is a JavaScript/TypeScript function passed to test() from @playwright/test, given a page fixture that the runner has already navigated-free and ready to use; inside it, you call locator methods to find elements, action methods like .click() or .fill() to interact with them, and expect() assertions to verify outcomes. The test file is discovered automatically if it matches the testMatch pattern in playwright.config.ts (by default, files ending in .spec.ts or .test.ts under the configured testDir).
Cricket analogy: It's like a match umpire (the runner) handing a fresh, correctly pitched ball (the page fixture) to the bowler at the top of every over, so the bowler just focuses on line and length rather than preparing the ball themselves.
Locators, Actions, and Auto-Waiting
Playwright recommends locator-based selection — page.getByRole(), page.getByText(), page.getByLabel(), page.getByTestId() — over raw CSS selectors, because locators are lazy: they describe how to find an element at the moment an action runs, and Playwright automatically retries that lookup and waits for actionability instead of failing immediately if the element isn't ready yet. getByRole is generally preferred because it matches how assistive technology and real users perceive the page (by ARIA role and accessible name), which tends to make tests more resilient to markup changes than brittle CSS class selectors.
Cricket analogy: It's like a fielder being told 'go to short cover' (a role-based description) rather than 'stand exactly at grid coordinate X,Y' (a CSS-style fixed position), so they can still find the right spot even if the field markings shift slightly.
Assertions and Reading the Report
Assertions use expect(locator).toHaveText(...), toBeVisible(), toHaveURL(...) and similar web-first matchers, which — unlike a plain Node assert — automatically retry for a few seconds until the condition is true or a timeout is reached, matching how real pages update asynchronously after a click. When a test fails, npx playwright show-report opens an interactive HTML report with a screenshot, video, and full trace of the failing run, including a DOM snapshot at each step, which is usually enough to diagnose a failure without adding a single console.log or re-running the test locally.
Cricket analogy: It's like the third umpire re-checking a run-out from multiple camera angles for several seconds before confirming out or not out, rather than an on-field umpire making an instant, unreviewed call.
// tests/login.spec.ts
import { test, expect } from '@playwright/test';
test('user can log in and see the dashboard', async ({ page }) => {
await page.goto('https://example.com/login');
await page.getByLabel('Email').fill('alice@example.com');
await page.getByLabel('Password').fill('correct-horse-battery-staple');
await page.getByRole('button', { name: 'Sign in' }).click();
// Web-first assertion: retries until true or timeout
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
await expect(page).toHaveURL(/.*\/dashboard/);
});Avoid selecting elements by brittle CSS classes generated by CSS-in-JS or build tools (e.g. .css-1x2y3z) — those hashes change on every rebuild and will silently break your tests. Prefer getByRole, getByLabel, or a stable data-testid attribute added specifically for testing.
Run npx playwright test --ui to open Playwright's UI Mode, which lets you watch each test step through a timeline, time-travel to any point in the run, and inspect the DOM snapshot at that exact moment — extremely useful while writing your first tests.
- A test is a function passed to test() from @playwright/test, receiving an already-ready
pagefixture. - Prefer locator methods like getByRole, getByLabel, and getByTestId over brittle CSS selectors.
- Locators are lazy and auto-retry lookups, waiting for actionability before acting.
- Web-first assertions like toBeVisible() and toHaveText() automatically retry until the condition is true or times out.
npx playwright testruns the suite;npx playwright show-reportopens the interactive HTML report.- The HTML report includes screenshots, video, and a full step-by-step trace for failed tests.
- UI Mode (
--ui) lets you time-travel through a test run and inspect DOM snapshots at each step.
Practice what you learned
1. What is passed automatically into a Playwright test function by the test runner?
2. Why is `page.getByRole('button', { name: 'Sign in' })` generally preferred over a CSS class selector?
3. What makes a Playwright web-first assertion like `toBeVisible()` different from a plain assert statement?
4. What command opens Playwright's interactive HTML report after a test run?
5. What does Playwright's UI Mode (`--ui`) primarily help with?
Was this page helpful?
You May Also Like
Installing Playwright and Project Setup
A practical walkthrough of installing Playwright, understanding what gets set up, and structuring a new test project.
Browsers, Contexts, and Pages
Understanding Playwright's core object model — Browser, BrowserContext, and Page — and how it enables fast, isolated test execution.
What Is Playwright?
An introduction to Playwright, Microsoft's cross-browser automation and end-to-end testing framework, and why teams choose it over older tools.