| name | playwright-test |
| description | Run end-to-end browser tests using the Playwright Test CLI. Create test configs, write spec files with expect assertions, execute tests with npx playwright test, and analyze results. Pre-installed with Chromium in the computer image — no setup needed. Use for E2E testing, regression testing, smoke tests, visual comparisons, and automated QA workflows. |
| category | code |
| tags | ["testing","e2e","browser","playwright","qa"] |
| allowed-tools | Bash, Read, Write, Edit |
Playwright Test CLI
Run end-to-end browser tests using the Playwright Test framework. @playwright/test and Chromium are pre-installed globally — no setup required.
Quick Start
1. Create a config file in the project root (or working directory):
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
use: {
baseURL: 'http://localhost:3000',
headless: true,
screenshot: 'only-on-failure',
},
reporter: [['list'], ['html', { open: 'never' }]],
retries: 1,
timeout: 30000,
});
2. Write a test file:
import { test, expect } from '@playwright/test';
test('homepage loads and has title', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveTitle(/My App/);
});
test('navigation works', async ({ page }) => {
await page.goto('/');
await page.click('a[href="/about"]');
await expect(page).toHaveURL(/about/);
});
3. Run tests:
npx playwright test
CLI Reference
Running Tests
npx playwright test
npx playwright test tests/login.spec.ts
npx playwright test -g "login flow"
npx playwright test tests/smoke/
npx playwright test --config=playwright.ci.config.ts
Filtering & Debugging
npx playwright test --grep @smoke
npx playwright test --grep-invert @slow
npx playwright test tests/auth.spec.ts:15
npx playwright test --debug
npx playwright test --reporter=list
Execution Control
npx playwright test --workers=4
npx playwright test --workers=1
npx playwright test --retries=2
npx playwright test --timeout=60000
npx playwright test --max-failures=1
Reporters & Output
npx playwright test --reporter=list
npx playwright test --reporter=line
npx playwright test --reporter=json
npx playwright test --reporter=html
npx playwright test --reporter=list,html
npx playwright test --reporter=junit
Updating Snapshots
npx playwright test --update-snapshots
Test Patterns
Page Object Model
import { Page, Locator } from '@playwright/test';
export class LoginPage {
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
constructor(private page: Page) {
this.emailInput = page.locator('input[name="email"]');
this.passwordInput = page.locator('input[name="password"]');
this.submitButton = page.locator('button[type="submit"]');
}
async login(email: string, password: string) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
}
import { test, expect } from '@playwright/test';
import { LoginPage } from './pages/login.page';
test('successful login redirects to dashboard', async ({ page }) => {
const loginPage = new LoginPage(page);
await page.goto('/login');
await loginPage.login('user@example.com', 'password123');
await expect(page).toHaveURL(/dashboard/);
});
API Testing
import { test, expect } from '@playwright/test';
test('API returns valid response', async ({ request }) => {
const response = await request.get('/api/users');
expect(response.ok()).toBeTruthy();
const data = await response.json();
expect(data.users).toBeInstanceOf(Array);
expect(data.users.length).toBeGreaterThan(0);
});
Visual Regression
test('homepage matches screenshot', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('homepage.png', {
maxDiffPixelRatio: 0.01,
});
});
Test Tags
test('login works @smoke', async ({ page }) => { });
test('complex workflow @slow', async ({ page }) => { });
Fixtures
import { test as base, expect } from '@playwright/test';
const test = base.extend<{ authenticatedPage: Page }>({
authenticatedPage: async ({ page }, use) => {
await page.goto('/login');
await page.fill('input[name="email"]', 'test@example.com');
await page.fill('input[name="password"]', 'password');
await page.click('button[type="submit"]');
await page.waitForURL(/dashboard/);
await use(page);
},
});
test('dashboard shows user name', async ({ authenticatedPage }) => {
await expect(authenticatedPage.locator('.username')).toContainText('Test User');
});
Config Options
Common playwright.config.ts settings:
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'list',
use: {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
headless: true,
screenshot: 'only-on-failure',
trace: 'on-first-retry',
video: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'mobile', use: { ...devices['Pixel 5'] } },
],
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
reuseExistingServer: true,
timeout: 30000,
},
});
Workflow
When asked to write or run Playwright tests:
- Check for existing config — look for
playwright.config.ts in the working directory
- Create config if missing — use the Quick Start template, adjust
baseURL to match the user's app
- Create test directory —
mkdir -p tests
- Write test files — use
.spec.ts extension, import from @playwright/test
- Run tests —
npx playwright test with appropriate flags
- Report results — parse output, highlight failures, suggest fixes
Tips
- Always use headless mode — the computer image has no display;
headless: true is the default
- Use
baseURL — set it in config so tests use relative paths (page.goto('/') instead of full URLs)
- Prefer locators over selectors —
page.getByRole(), page.getByText(), page.getByTestId() are more resilient
- Use
expect auto-waiting — Playwright assertions auto-retry, so await expect(locator).toBeVisible() waits automatically
- Capture traces on failure — set
trace: 'on-first-retry' in config for debugging failed tests
- Only Chromium is available — don't configure Firefox or WebKit projects; only
chromium is installed