| name | e2e-testing |
| description | Run Playwright end-to-end browser tests for web applications with screenshots and traces. Trigger: when running Playwright tests, E2E browser testing, UI testing, Playwright setup, recording browser tests, Cypress |
| version | 1 |
| argument-hint | [--grep <pattern>] [--project <browser>] |
| allowed-tools | ["bash","read","write","grep","glob"] |
E2E Testing (Playwright)
You are now operating in Playwright end-to-end testing mode.
Installation and Setup
npm init playwright@latest
npm install -D @playwright/test
npx playwright install
npx playwright install chromium
npx playwright install chromium firefox
Running Tests
npx playwright test
npx playwright test --headed
npx playwright test tests/login.spec.ts
npx playwright test --grep "user can login"
npx playwright test --grep "@smoke"
npx playwright test --project=chromium
npx playwright test --project=firefox
npx playwright test --project=webkit
npx playwright test --project=chromium --project=firefox --project=webkit
npx playwright test --debug
Reporters and Output
npx playwright test --reporter=html
npx playwright show-report
npx playwright test --reporter=line
npx playwright test --reporter=json > results.json
npx playwright test --reporter=html,line
Trace and Screenshots
npx playwright test --trace on
npx playwright test --trace retain-on-failure
npx playwright test --trace off
npx playwright show-trace trace.zip
Code Generation (Record Tests)
npx playwright codegen http://localhost:3000
npx playwright codegen --save-storage=auth.json http://localhost:3000
npx playwright codegen --load-storage=auth.json http://localhost:3000
Test File Structure
import { test, expect } from '@playwright/test';
test.describe('Authentication', () => {
test('user can log in with valid credentials', async ({ page }) => {
await page.goto('/login');
await page.fill('[name=email]', 'test@example.com');
await page.fill('[name=password]', 'password');
await page.click('button[type=submit]');
await expect(page).toHaveURL('/dashboard');
await expect(page.getByRole('heading')).toContainText('Dashboard');
});
test('shows error for invalid credentials', async ({ page }) => {
await page.goto('/login');
await page.fill('[name=email]', 'wrong@example.com');
await page.fill('[name=password]', 'wrongpassword');
await page.click('button[type=submit]');
await expect(page.getByRole('alert')).toBeVisible();
await expect(page.getByRole('alert')).toContainText('Invalid credentials');
});
});
Page Object Model
import { Page, Locator } from '@playwright/test';
export class LoginPage {
readonly page: Page;
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
readonly errorMessage: Locator;
constructor(page: Page) {
this.page = page;
this.emailInput = page.locator('[name=email]');
this.passwordInput = page.locator('[name=password]');
this.submitButton = page.locator('button[type=submit]');
this.errorMessage = page.getByRole('alert');
}
async login(email: string, password: string) {
await this.page.goto('/login');
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
}
Configuration (playwright.config.ts)
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30_000,
retries: process.env.CI ? 2 : 0,
reporter: process.env.CI ? 'github' : 'html',
use: {
baseURL: process.env.BASE_URL ?? 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
],
});
CI Integration
- name: Run Playwright tests
run: npx playwright test
env:
BASE_URL: http://localhost:3000
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
Common Selectors
page.getByRole('button', { name: 'Submit' })
page.getByRole('heading', { name: 'Dashboard' })
page.getByRole('link', { name: 'Sign in' })
page.getByLabel('Email address')
page.getByLabel('Password')
page.getByPlaceholder('Enter your email')
page.getByTestId('submit-button')
page.locator('[name=email]')
page.locator('.error-message')
Debugging Tips
PWDEBUG=1 npx playwright test tests/login.spec.ts
npx playwright test --headed --slowMo=1000
npx playwright test --grep "@only"