关于 e2e-playwright-testing
面向 Web 开发者和编码 Agent 的 Playwright 端到端测试技能,按项目技术栈提供浏览器测试规范,涵盖定位器、认证复用及 CI 配置。
主要功能
- 01检测项目技术栈与认证方式
- 02提供无障碍定位器建议
- 03复用认证状态
- 04指导表单与断言模式
- 05规范测试组织和可靠性
- 06提供 CI 配置指南
适用场景
- 01编写或审查 Playwright 端到端测试
- 02排查不稳定的浏览器测试
- 03测试表单与认证流程
- 04配置 Playwright CI
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ asyrafhussin/ agent-skills --skill e2e-playwright-testing安装后在 Claude Code 中输入/e2e-playwright-testing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
AGENTS.mdmetadata.jsonREADME.mdrules/_sections.md_template.mdassert-web-first.mdauth-storage-state.mdform-custom-checkboxes.mdform-react-date-inputs.mdloc-prefer-role-locators.mdloc-strict-mode.mdorg-mirror-routes.mdrel-no-wait-for-timeout.md详细介绍
E2E Playwright 测试
使用 Playwright 进行可靠的端到端浏览器测试的模式与约定。
Web 应用的综合 E2E 测试指南。包含 8 条规则,分为 6 个类别,涵盖定位器策略、身份验证复用、表单测试(包括 React/SPA 特有的问题)、断言、测试组织、可靠性以及 CI/CD 配置。
技术栈检测
编写或审查 E2E 测试之前,请先检测项目的技术栈:
步骤 1 — 检查是否使用 Playwright
# Look in package.json devDependencies:
# "@playwright/test" → Playwright is installed
# Check for playwright.config.js or playwright.config.ts
- 如果存在
@playwright/test→ 使用此技能中的 Playwright 模式 - 如果存在
cypress→ 此技能不适用
步骤 2 — 检测前端框架
# Check package.json dependencies:
# "react" + "@inertiajs/react" → React + Inertia.js (SPA with server routing)
# "react" + "react-router" → React SPA
# "vue" → Vue.js
# "next" → Next.js
这很重要的原因:
- React + Inertia.js:使用
waitForURL,而不是waitForLoadState('networkidle')——Inertia 使用history.pushState - React 受控输入框:文本输入可使用
fill();日期/时间输入需要使用keyboard.type() - SPA 导航:页面不会完整重新加载——断言应等待内容,而不是等待网络空闲
步骤 3 — 检测身份验证模式
# Check for session-based (Laravel Sanctum) or token-based (JWT) auth
# Session: storageState saves cookies
# Token: may need to save tokens to localStorage
步骤 4 — 检测速率限制
# Check routes for throttle middleware
# If present in dev, tests will hit 429 after ~5 login attempts
# Solution: production-only throttle or increase limits in test env
元数据
- 版本: 1.0.0
- 规则数量: 6 个类别中的 8 条规则
- 许可证: MIT
适用场景
- 编写或审查 Playwright E2E 测试
- 为新项目设置 E2E 测试
- 调试不稳定的浏览器测试
- 测试表单提交、身份验证流程或用户交互
- 为元素选择定位器策略
- 配置 Playwright 以用于 CI/CD
按优先级划分的规则类别
| 优先级 | 类别 | 影响 | 前缀 |
|---|---|---|---|
| 1 | 定位器 | 严重 | loc |
| 2 | 身份验证 | 严重 | auth |
| 3 | 断言 | 高 | assert |
| 4 | 表单与输入框 | 高 | form |
| 5 | 测试组织 | 中 | org |
| 6 | 可靠性 | 中 | rel |
快速参考
1. 定位器(严重)
loc-prefer-role-locators- 优先使用 getByRole/getByLabel,而不是 CSS 选择器loc-strict-mode- 使用 exact/first/限定范围的定位器处理严格模式违规
2. 身份验证(严重)
auth-storage-state- 使用设置项目模式复用登录状态
3. 断言(高)
assert-web-first- 使用会自动重试的 expect(locator) 断言
4. 表单与输入框(高)
form-react-date-inputs- 在 React 应用中输入日期/时间时使用 keyboard.type()form-custom-checkboxes- 处理 sr-only 复选框组件
5. 测试组织(中)
org-mirror-routes- 目录结构与路由组保持一致
6. 可靠性(中)
rel-no-wait-for-timeout- 切勿使用任意的 waitForTimeout
核心模式
定位器优先级
// 1st: Role (best — mirrors accessibility)
page.getByRole('button', { name: 'Submit' })
page.getByRole('tab', { name: 'Network' })
page.getByRole('heading', { name: 'Dashboard' })
// 2nd: Label (for form fields)
page.getByLabel('Email')
// 3rd: Text (for static content, use exact when ambiguous)
page.getByText('Welcome', { exact: true })
// 4th: ID (for inputs without proper labels)
page.locator('#password')
// Last resort: CSS selector
page.locator('button.submit-btn')
身份验证设置模式
// Setup project logs in once per role, all tests reuse the state
// 3 logins for 90+ tests (not 90 logins)
// In test files:
test.use({ role: 'customer' });
test('shows dashboard', async ({ authedPage: page }) => {
await page.goto('/dashboard');
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
});
React 日期输入问题
// fill() doesn't trigger React onChange for date/time inputs
// Use keyboard.type() instead:
await dateInput.click();
await page.keyboard.type('16042026'); // DDMMYYYY
await timeInput.click();
await page.keyboard.type('1000AM'); // 10:00 AM
严格模式修复
// Bad: matches "Verified" AND "Unverified"
page.getByRole('button', { name: 'Verified' })
// Good: exact match
page.getByRole('button', { name: 'Verified', exact: true })
// Bad: matches heading AND breadcrumb
page.getByText('POS Demo')
// Good: use role to disambiguate
page.getByRole('heading', { name: 'POS Demo' })
并行运行决策
// Default Playwright: fullyParallel: true
// Use this when: tests are independent, each test creates its own data
// Override to sequential: workers: 1
// Use this when: tests share a seeded database with mutable state
// Without this, one test's buy transaction changes the balance another test expects
配置模板
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './specs',
fullyParallel: false, // true if tests are independent
workers: 1, // increase if no shared mutable state
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
reporter: [['html', { open: 'never' }], ['list']],
use: {
baseURL: process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:8000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{ name: 'auth-setup', testMatch: /auth\.setup\.js$/, testDir: './auth' },
{ name: 'chrome', use: { ...devices['Desktop Chrome'] }, dependencies: ['auth-setup'] },
{ name: 'mobile', use: { ...devices['iPhone 14'] }, dependencies: ['auth-setup'], testMatch: /responsive/ },
],
});
参考资料
完整编译文档
如需查看包含所有展开规则的完整指南:AGENTS.md
评论
支持 Markdown