Day 4 of 5

End-to-End Testing with Playwright

E2E tests automate a real browser. Playwright tests your whole stack — frontend, backend, and database — as a real user would. Today you will write page object model tests and integrate them with CI.

bash
npm init playwright@latest
# or add to existing project:
npm install --save-dev @playwright/test
npx playwright install
typescript
// tests/login.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Login flow', () => {
  test('successful login redirects to dashboard', async ({ page }) => {
    await page.goto('/login');

    await page.getByLabel('Email').fill('[email protected]');
    await page.getByLabel('Password').fill('secret123');
    await page.getByRole('button', { name: 'Log in' }).click();

    await expect(page).toHaveURL('/dashboard');
    await expect(page.getByText('Welcome back')).toBeVisible();
  });

  test('shows error for wrong password', async ({ page }) => {
    await page.goto('/login');
    await page.getByLabel('Email').fill('[email protected]');
    await page.getByLabel('Password').fill('wrong');
    await page.getByRole('button', { name: 'Log in' }).click();

    await expect(page.getByText('Invalid credentials')).toBeVisible();
  });
});
typescript
// tests/pages/LoginPage.ts — Page Object Model
export class LoginPage {
  constructor(private page: Page) {}

  async goto() { await this.page.goto('/login'); }

  async login(email: string, password: string) {
    await this.page.getByLabel('Email').fill(email);
    await this.page.getByLabel('Password').fill(password);
    await this.page.getByRole('button', { name: 'Log in' }).click();
  }
}

// Use in tests:
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('[email protected]', 'secret123');

Exercise: Write E2E Tests for a CRUD App

  1. Install Playwright and run npx playwright test
  2. Write a test that creates, reads, and deletes a record
  3. Use getByRole and getByLabel for accessible queries
  4. Record a test with: npx playwright codegen localhost:3000
  5. Run with --reporter=html and inspect the HTML report

Day 4 Summary

Finished this lesson?