home / skills / shipshitdev / library / playwright-e2e-init

playwright-e2e-init skill

/bundles/testing/skills/playwright-e2e-init

This skill initializes Playwright end-to-end tests for Next.js and React projects, creating config, tests, scripts, and CI/CD integration.

npx playbooks add skill shipshitdev/library --skill playwright-e2e-init

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

Files (4)
SKILL.md
6.7 KB
---
name: playwright-e2e-init
description: Initialize Playwright end-to-end testing for Next.js and React projects. Sets up configuration, creates example tests, and integrates with existing CI/CD. Use when adding E2E tests to a frontend project.
---

# Playwright E2E Testing Initialization

Sets up Playwright for end-to-end testing in Next.js and React applications.

## When to Use

This skill should be used when:

- Adding E2E tests to a Next.js project
- Setting up browser automation testing
- Creating user flow tests for critical paths
- Integrating E2E tests with CI/CD pipeline

## What It Does

1. **Installs Playwright** and browsers
2. **Creates configuration** (playwright.config.ts)
3. **Sets up test directory** (e2e/)
4. **Creates example tests** for common flows
5. **Adds npm scripts** for running tests
6. **Updates CI/CD** to run E2E tests

## Quick Start

Ask Claude to:

```
Add Playwright E2E tests to this project
```

Or be specific:

```
Set up E2E tests for the authentication flow
```

## Installation

```bash
bun add -D @playwright/test
bunx playwright install chromium
```

## Configuration

### playwright.config.ts

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

export default defineConfig({
  testDir: "./e2e",
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: [["html", { open: "never" }], ["list"]],
  use: {
    baseURL: "http://localhost:3000",
    trace: "on-first-retry",
    screenshot: "only-on-failure",
  },
  projects: [
    { name: "chromium", use: { ...devices["Desktop Chrome"] } },
  ],
  webServer: {
    command: "bun run dev",
    url: "http://localhost:3000",
    reuseExistingServer: !process.env.CI,
    timeout: 120 * 1000,
  },
});
```

## Test Structure

```
e2e/
├── home.spec.ts          # Homepage tests
├── auth.spec.ts          # Authentication flow
├── navigation.spec.ts    # Navigation tests
└── fixtures/
    └── test-data.ts      # Shared test data
```

## Example Tests

### Basic Navigation Test

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

test.describe("Homepage", () => {
  test("should load successfully", async ({ page }) => {
    await page.goto("/");
    await expect(page).toHaveTitle(/My App/);
  });

  test("should navigate to about page", async ({ page }) => {
    await page.goto("/");
    await page.click('a[href="/about"]');
    await expect(page).toHaveURL("/about");
  });
});
```

### Authentication Flow Test

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

test.describe("Authentication", () => {
  test("should login successfully", async ({ page }) => {
    await page.goto("/login");

    await page.fill('input[name="email"]', "[email protected]");
    await page.fill('input[name="password"]', "password123");
    await page.click('button[type="submit"]');

    await expect(page).toHaveURL("/dashboard");
    await expect(page.locator("text=Welcome")).toBeVisible();
  });

  test("should show error for invalid credentials", async ({ page }) => {
    await page.goto("/login");

    await page.fill('input[name="email"]', "[email protected]");
    await page.fill('input[name="password"]', "wrongpassword");
    await page.click('button[type="submit"]');

    await expect(page.locator("text=Invalid credentials")).toBeVisible();
  });
});
```

### Form Submission Test

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

test.describe("Contact Form", () => {
  test("should submit form successfully", async ({ page }) => {
    await page.goto("/contact");

    await page.fill('input[name="name"]', "John Doe");
    await page.fill('input[name="email"]', "[email protected]");
    await page.fill('textarea[name="message"]', "Hello, this is a test message");
    await page.click('button[type="submit"]');

    await expect(page.locator("text=Thank you")).toBeVisible();
  });
});
```

## NPM Scripts

Add to package.json:

```json
{
  "scripts": {
    "e2e": "playwright test",
    "e2e:ui": "playwright test --ui",
    "e2e:headed": "playwright test --headed",
    "e2e:debug": "playwright test --debug",
    "e2e:report": "playwright show-report"
  }
}
```

## CI/CD Integration

### GitHub Actions

Add to your CI workflow:

```yaml
- name: Install Playwright Browsers
  run: bunx playwright install --with-deps chromium

- name: Run E2E tests
  run: bun run e2e
  env:
    CI: true

- name: Upload Playwright Report
  uses: actions/upload-artifact@v4
  if: always()
  with:
    name: playwright-report
    path: playwright-report/
    retention-days: 7
```

## Best Practices

### 1. Test Critical User Flows

Focus on:

- Authentication (login, logout, signup)
- Core features (main value proposition)
- Payment/checkout flows
- Error handling

### 2. Use Page Object Model

```typescript
// e2e/pages/login.page.ts
import { Page } from "@playwright/test";

export class LoginPage {
  constructor(private page: Page) {}

  async goto() {
    await this.page.goto("/login");
  }

  async login(email: string, password: string) {
    await this.page.fill('input[name="email"]', email);
    await this.page.fill('input[name="password"]', password);
    await this.page.click('button[type="submit"]');
  }
}
```

### 3. Use Data Attributes for Selectors

```html
<button data-testid="submit-button">Submit</button>
```

```typescript
await page.click('[data-testid="submit-button"]');
```

### 4. Keep Tests Independent

Each test should:

- Set up its own state
- Not depend on other tests
- Clean up after itself

### 5. Use Fixtures for Common Setup

```typescript
import { test as base } from "@playwright/test";

const test = base.extend({
  authenticatedPage: async ({ page }, use) => {
    await page.goto("/login");
    await page.fill('input[name="email"]', "[email protected]");
    await page.fill('input[name="password"]', "password");
    await page.click('button[type="submit"]');
    await use(page);
  },
});
```

## Troubleshooting

### Tests timing out

Increase timeout in config:

```typescript
timeout: 60000, // 60 seconds
```

### Elements not found

Use `waitFor`:

```typescript
await page.waitForSelector('[data-testid="element"]');
```

### Flaky tests

Add retries and use `toPass`:

```typescript
await expect(async () => {
  await expect(page.locator("text=Success")).toBeVisible();
}).toPass({ timeout: 10000 });
```

## Integration with Other Skills

| Skill | Integration |
|-------|-------------|
| `testing-cicd-init` | Sets up unit tests first |
| `testing-expert` | Provides testing patterns |
| `webapp-testing` | Alternative automation skill |

---

**When this skill is active**, Claude will:

1. Install Playwright and browsers
2. Create configuration file
3. Set up e2e/ directory
4. Create example tests for existing pages
5. Add npm scripts
6. Update CI/CD workflow

Overview

This skill initializes Playwright end-to-end testing for Next.js and React projects. It installs Playwright and browsers, creates a sensible playwright.config.ts, scaffolds an e2e/ test directory with example specs, and wires tests into your CI/CD pipeline. Use it to get reliable browser tests running quickly with recommended defaults.

How this skill works

The skill installs @playwright/test and necessary browser binaries, writes a configuration file that includes baseURL, retries, reporters, and a local webServer command. It creates example test files (homepage, auth, navigation, fixtures) and optional page objects, adds npm scripts for common test commands, and updates CI workflows to install browsers and run tests, plus upload reports. All artifacts are tailored for Next.js/React development and CI environments.

When to use it

  • Adding E2E coverage to a Next.js or React frontend project
  • Creating automated user-flow tests for critical paths (auth, checkout, navigation)
  • Bootstrapping Playwright with sensible defaults and CI integration
  • Migrating manual browser checks to repeatable tests
  • Enabling team members to run E2E tests locally or in CI

Best practices

  • Focus tests on critical user flows: auth, core features, payments, error paths
  • Use data-testid or data attributes for stable selectors instead of brittle CSS
  • Keep tests independent: set up and tear down state within each test
  • Adopt Page Object Model for reusable page interactions and clearer tests
  • Configure retries and traces for flaky tests; limit parallel workers in CI

Example use cases

  • Add Playwright to a Next.js app and verify homepage and about navigation
  • Create authentication flow tests covering login success and invalid credentials
  • Add form submission tests for contact or checkout pages
  • Integrate Playwright test run and browser install into a GitHub Actions workflow
  • Provide teammates with npm scripts to run headed, debug, and report modes

FAQ

Which browsers are installed by default?

The setup installs Chromium by default; you can enable WebKit and Firefox in the config or installer command.

How do tests run in CI?

CI steps install Playwright browsers, run the e2e script with CI=true, and optionally upload the Playwright report artifact.