home / skills / doanchienthangdev / omgkit / playwright

This skill helps you write reliable end-to-end tests with Playwright, utilizing Page Object Model, API mocking, and cross-browser strategies for robust apps.

npx playbooks add skill doanchienthangdev/omgkit --skill playwright

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
5.1 KB
---
name: Testing with Playwright
description: Claude writes reliable E2E tests using Playwright for browser automation. Use when writing end-to-end tests, implementing Page Object Model, visual regression testing, API mocking, or cross-browser testing.
---

# Testing with Playwright

## Quick Start

```typescript
// playwright.config.ts
import { defineConfig, devices } from "@playwright/test";

export default defineConfig({
  testDir: "./tests/e2e",
  fullyParallel: true,
  retries: process.env.CI ? 2 : 0,
  reporter: [["list"], ["html"]],
  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 12"] } },
  ],
  webServer: { command: "npm run dev", url: "http://localhost:3000" },
});
```

## Features

| Feature | Description | Reference |
|---------|-------------|-----------|
| Page Object Model | Maintainable test architecture pattern | [POM Guide](https://playwright.dev/docs/pom) |
| Auto-Waiting | Built-in waiting for elements and assertions | [Auto-Waiting](https://playwright.dev/docs/actionability) |
| Network Mocking | Intercept and mock API responses | [Network](https://playwright.dev/docs/network) |
| Visual Testing | Screenshot comparison for regression testing | [Visual Comparisons](https://playwright.dev/docs/test-snapshots) |
| Cross-Browser | Chrome, Firefox, Safari, mobile devices | [Browsers](https://playwright.dev/docs/browsers) |
| Trace Viewer | Debug failing tests with timeline | [Trace Viewer](https://playwright.dev/docs/trace-viewer) |

## Common Patterns

### Page Object Model

```typescript
// tests/pages/login.page.ts
import { Page, Locator, expect } from "@playwright/test";

export class LoginPage {
  readonly emailInput: Locator;
  readonly passwordInput: Locator;
  readonly submitButton: Locator;

  constructor(private page: Page) {
    this.emailInput = page.getByLabel("Email");
    this.passwordInput = page.getByLabel("Password");
    this.submitButton = page.getByRole("button", { name: "Sign in" });
  }

  async login(email: string, password: string) {
    await this.emailInput.fill(email);
    await this.passwordInput.fill(password);
    await this.submitButton.click();
  }

  async expectError(message: string) {
    await expect(this.page.getByRole("alert")).toContainText(message);
  }
}
```

### API Mocking

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

test("mock API response", async ({ page }) => {
  await page.route("**/api/users", (route) =>
    route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify({ users: [{ id: 1, name: "John" }] }),
    })
  );

  await page.goto("/users");
  await expect(page.getByText("John")).toBeVisible();
});

test("capture network requests", async ({ page }) => {
  const requestPromise = page.waitForRequest("**/api/analytics");
  await page.goto("/dashboard");
  const request = await requestPromise;
  expect(request.postDataJSON()).toMatchObject({ event: "page_view" });
});
```

### Authentication Fixture

```typescript
// tests/fixtures/auth.fixture.ts
import { test as base } from "@playwright/test";
import { LoginPage } from "../pages/login.page";

export const test = base.extend<{ authenticatedPage: Page }>({
  authenticatedPage: async ({ page }, use) => {
    // Fast auth via API
    const response = await page.request.post("/api/auth/login", {
      data: { email: "[email protected]", password: "password" },
    });
    const { token } = await response.json();

    await page.context().addCookies([
      { name: "auth_token", value: token, domain: "localhost", path: "/" },
    ]);

    await page.goto("/dashboard");
    await use(page);
  },
});
```

### Visual Regression Testing

```typescript
test("visual snapshot", async ({ page }) => {
  await page.goto("/");
  await page.addStyleTag({
    content: "*, *::before, *::after { animation-duration: 0s !important; }",
  });

  await expect(page).toHaveScreenshot("homepage.png", {
    fullPage: true,
    maxDiffPixels: 100,
  });

  // Mask dynamic content
  await expect(page).toHaveScreenshot("dashboard.png", {
    mask: [page.getByTestId("timestamp"), page.getByTestId("avatar")],
  });
});
```

## Best Practices

| Do | Avoid |
|----|-------|
| Use Page Object Model for maintainability | Fragile CSS selectors |
| Prefer user-facing locators (getByRole, getByLabel) | Relying on arbitrary waits |
| Use API auth for faster test setup | Sharing state between tests |
| Enable traces and screenshots for debugging | Testing third-party services directly |
| Run tests in parallel for speed | Skipping flaky tests without fixing |
| Mock external APIs for reliability | Hardcoding test data |

## References

- [Playwright Documentation](https://playwright.dev/docs/intro)
- [Playwright Best Practices](https://playwright.dev/docs/best-practices)
- [Page Object Model](https://playwright.dev/docs/pom)
- [Visual Comparisons](https://playwright.dev/docs/test-snapshots)

Overview

This skill trains Claude to write reliable end-to-end tests using Playwright for browser automation. It focuses on maintainable test architecture, robust locators, API mocking, visual regression, and cross-browser execution. The goal is fast, deterministic tests that are easy to debug and scale.

How this skill works

Claude generates Playwright test code, Page Object Models, fixtures, and configuration tailored to your app. It can implement API mocking and network interception, set up fast authentication via API, and author visual snapshot assertions with masking for dynamic content. The skill also produces configuration for multiple projects (Chromium, Firefox, mobile) and debug helpers like traces and screenshots.

When to use it

  • Writing end-to-end tests for web applications
  • Implementing Page Object Model for maintainability
  • Creating visual regression tests with masked dynamic regions
  • Mocking or asserting network requests and API responses
  • Running cross-browser tests including mobile device emulation

Best practices

  • Use user-facing locators (getByRole, getByLabel) instead of fragile CSS selectors
  • Encapsulate page interactions in Page Object classes to reduce duplication
  • Prefer API-based authentication for fast, isolated test setup
  • Enable traces and screenshots for failing tests to simplify debugging
  • Mock external APIs and stable fixtures to make tests deterministic

Example use cases

  • Create a LoginPage class with login and error assertion helpers for reuse across tests
  • Mock /api/users and assert UI renders mocked data without hitting real backend
  • Add an authenticated fixture that injects auth cookies via the API for dashboard tests
  • Add visual snapshot tests with masks for timestamps and avatars to detect regressions
  • Configure playwright.config.ts for parallel runs, retries on CI, and multiple browser projects

FAQ

How do I reduce flaky tests caused by timing?

Use Playwright's auto-waiting and user-facing locators, avoid arbitrary sleeps, and prefer assertions that wait for expected states before proceeding.

When should I mock APIs vs hit the real backend?

Mock external or unstable services to keep tests deterministic. Use real backends sparingly for end-to-end smoke tests and run them in a dedicated environment.