playwright-e2e-init
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePlaywright E2E Testing Initialization
Playwright端到端测试初始化
Sets up Playwright for end-to-end testing in Next.js and React applications.
为Next.js和React应用设置Playwright端到端测试。
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
在以下场景中使用此技能:
- 为Next.js项目添加E2E测试
- 设置浏览器自动化测试
- 为关键路径创建用户流程测试
- 将E2E测试与CI/CD流水线集成
What It Does
功能说明
- Installs Playwright and browsers
- Creates configuration (playwright.config.ts)
- Sets up test directory (e2e/)
- Creates example tests for common flows
- Adds npm scripts for running tests
- Updates CI/CD to run E2E tests
- 安装Playwright及浏览器
- 创建配置文件(playwright.config.ts)
- 设置测试目录(e2e/)
- 创建常见流程的示例测试
- 添加npm脚本用于运行测试
- 更新CI/CD配置以运行E2E测试
Quick Start
快速开始
Ask Claude to:
Add Playwright E2E tests to this projectOr be specific:
Set up E2E tests for the authentication flow可以让Claude执行:
Add Playwright E2E tests to this project或者更具体的指令:
Set up E2E tests for the authentication flowInstallation
安装步骤
bash
bun add -D @playwright/test
bunx playwright install chromiumbash
bun add -D @playwright/test
bunx playwright install chromiumConfiguration
配置说明
playwright.config.ts
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,
},
});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 datae2e/
├── home.spec.ts # 首页测试
├── auth.spec.ts # 认证流程测试
├── navigation.spec.ts # 导航测试
└── fixtures/
└── test-data.ts # 共享测试数据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");
});
});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"]', "test@example.com");
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"]', "wrong@example.com");
await page.fill('input[name="password"]', "wrongpassword");
await page.click('button[type="submit"]');
await expect(page.locator("text=Invalid credentials")).toBeVisible();
});
});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"]', "test@example.com");
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"]', "wrong@example.com");
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"]', "john@example.com");
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();
});
});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"]', "john@example.com");
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
NPM脚本
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"
}
}添加到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
CI/CD集成
GitHub Actions
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添加到你的CI工作流:
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: 7Best Practices
最佳实践
1. Test Critical User Flows
1. 测试关键用户流程
Focus on:
- Authentication (login, logout, signup)
- Core features (main value proposition)
- Payment/checkout flows
- Error handling
重点关注:
- 认证(登录、登出、注册)
- 核心功能(主要价值主张)
- 支付/结账流程
- 错误处理
2. Use Page Object Model
2. 使用页面对象模型
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"]');
}
}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
3. 使用数据属性作为选择器
html
<button data-testid="submit-button">Submit</button>typescript
await page.click('[data-testid="submit-button"]');html
<button data-testid="submit-button">Submit</button>typescript
await page.click('[data-testid="submit-button"]');4. Keep Tests Independent
4. 保持测试独立性
Each test should:
- Set up its own state
- Not depend on other tests
- Clean up after itself
每个测试应:
- 自行设置状态
- 不依赖其他测试
- 执行后清理环境
5. Use Fixtures for Common Setup
5. 使用Fixture进行通用设置
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"]', "test@example.com");
await page.fill('input[name="password"]', "password");
await page.click('button[type="submit"]');
await use(page);
},
});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"]', "test@example.com");
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| 技能 | 集成方式 |
|---|---|
| 先设置单元测试 |
| 提供测试模式 |
| 可选的自动化测试技能 |
当此技能激活时,Claude将:
- 安装Playwright及浏览器
- 创建配置文件
- 设置e2e/目录
- 为现有页面创建示例测试
- 添加npm脚本
- 更新CI/CD工作流
Elements not found
—
Use :
waitFortypescript
await page.waitForSelector('[data-testid="element"]');—
Flaky tests
—
Add retries and use :
toPasstypescript
await expect(async () => {
await expect(page.locator("text=Success")).toBeVisible();
}).toPass({ timeout: 10000 });—
Integration with Other Skills
—
| Skill | Integration |
|---|---|
| Sets up unit tests first |
| Provides testing patterns |
| Alternative automation skill |
When this skill is active, Claude will:
- Install Playwright and browsers
- Create configuration file
- Set up e2e/ directory
- Create example tests for existing pages
- Add npm scripts
- Update CI/CD workflow
—