Skip to content

Your First Playwright Test

This lesson walks through a complete, realistic Playwright test: visiting a login page, filling a form, submitting it, and asserting on the outcome.

Planning the Test

A good first test targets a small, well-understood user flow. Login exercises navigation, form input, clicking, and URL or visibility assertions.

Write the steps in plain English first, then translate each step into one or two Playwright calls using role-based locators.

// Plan:
// 1. Visit /login
// 2. Fill email and password
// 3. Click Sign in
// 4. Assert URL is /dashboard

Planning in plain English makes the Playwright code almost write itself.

The Complete First Test

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

test('logs in with valid credentials', async ({ page }) => {
  await page.goto('/login');
  await page.getByLabel('Email').fill('user@example.com');
  await page.getByLabel('Password').fill('correct-password');
  await page.getByRole('button', { name: 'Sign in' }).click();
  await expect(page).toHaveURL(/\/dashboard/);
});
  • page.goto() navigates and waits for the load event.
  • getByLabel() targets inputs by their associated label text.
  • getByRole('button') finds the submit button by accessible name.
  • expect(page).toHaveURL() auto-retries until the URL matches or times out.

First Test Quick Reference

The commands in a typical login-style first test.

Step Command
Navigate await page.goto('/login')
Fill input await page.getByLabel('Email').fill('...')
Click button await page.getByRole('button', { name: 'Sign in' }).click()
Assert URL await expect(page).toHaveURL(/dashboard/)
Assert visible await expect(page.getByRole('heading')).toBeVisible()
Assert text await expect(locator).toContainText('Welcome')
Run test npx playwright test first-login.spec.ts

Running and Debugging Your First Test

Run a single file with npx playwright test tests/login.spec.ts. If it fails, add --headed to watch the browser, or --debug to step through with the Playwright Inspector.

npx playwright test tests/login.spec.ts --headed
npx playwright test tests/login.spec.ts --debug

What Playwright Waits For Automatically

  • goto waits for the load event (configurable via waitUntil).
  • Clicks wait for the element to be visible, stable, and enabled.
  • Assertions like toBeVisible() retry until pass or timeout.

Common Mistakes

  • Using brittle CSS selectors instead of getByRole or getByLabel on the first test.
  • Not awaiting click() before asserting on the result page.
  • Asserting immediately with a plain string compare instead of expect().toHaveURL().
  • Testing against production instead of a local or staging environment.

Key Takeaways

  • Plan user steps in English, then map each to a Playwright API call.
  • Role and label locators make first tests readable and resilient.
  • Web-first assertions auto-retry, avoiding manual waits.
  • Use --headed and --debug while learning, headless in CI.

Pro Tip

After your first test passes, run npx playwright codegen http://localhost:3000/login and compare its locators to yours — adjust toward the generated patterns when they are clearer.