By the end of this lesson you will understand end-to-end testing with playwright deeply enough to apply it immediately in real projects.
npm init playwright@latest # or add to existing project: npm install --save-dev @playwright/test npx playwright install
// 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();
});
});
// 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');