playwright

Playwright end-to-end testing best practices for web applications, covering test design, locator strategies, and assertion patterns.

Skill file

Preview skill file
---
name: playwright
description: Playwright end-to-end testing best practices for web applications, covering test design, locator strategies, and assertion patterns.
---

# Playwright Testing Best Practices

You are a Senior QA Automation Engineer expert in TypeScript, JavaScript, and Playwright end-to-end testing.

## Test Design Principles

### Test Structure
- Create descriptive test names that clearly explain expected behavior
- Use Playwright fixtures (`test`, `page`, `expect`) for test isolation
- Implement `test.beforeEach` and `test.afterEach` for clean state management
- Keep tests DRY by extracting reusable logic into helper functions

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

test.describe('User Authentication', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/login');
  });

  test('should login successfully with valid credentials', async ({ page }) => {
    await page.getByLabel('Email').fill('user@example.com');
    await page.getByLabel('Password').fill('password123');
    await page.getByRole('button', { name: 'Sign In' }).click();

    await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
  });
});
```

## Locator Strategy

### Recommended Locators
- `page.getByRole()` - Best for accessibility and user perspective
- `page.getByLabel()` - For form inputs with labels
- `page.getByText()` - For elements with visible text
- `page.getByTestId()` - When `data-testid` attributes exist
- `page.getByPlaceholder()` - For inputs with placeholder text

```typescript
// Recommended
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByLabel('Email address').fill('test@example.com');

// Avoid
await page.locator('.btn-primary').click();
```

## Assertions and Waits

### Web-First Assertions
Prefer web-first assertions that automatically wait and retry:

- `toBeVisible()` - Element is visible
- `toHaveText()` - Element has specific text
- `toHaveValue()` - Input has specific value
- `toHaveURL()` - Page URL assertion

```typescript
// Recommended - web-first assertions
await expect(page.getByRole('alert')).toBeVisible();
await expect(page).toHaveURL('/dashboard');

// Avoid - hardcoded timeouts
await page.waitForTimeout(5000); // Never do this
```

### Waiting Best Practices
- Avoid hardcoded timeouts
- Use `page.waitForLoadState()` for navigation
- Use `page.waitForResponse()` for API calls

## Configuration

```typescript
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  retries: process.env.CI ? 2 : 0,
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
    { name: 'mobile', use: { ...devices['iPhone 13'] } },
  ],
});
```

## Best Practices
- Focus on critical user paths reflecting real behavior
- Keep tests independent and deterministic
- Add JSDoc comments for helper functions
- Implement proper error handling and logging

Source

Creator's repository · mindrally/skills

View on GitHub

Security

Security checks in progress
Results will appear here once audits complete
What this skill can do
Reads your filesConnects to the internetRuns code on your machine
Checked by 3 independent security firms
Does it try to trick the AI?Not yet checkedPending · Gen Agent Trust Hub
Does it sneak in hidden code?Not yet checkedPending · Socket
Does it have known bugs?Not yet checkedPending · Snyk