Files
everything-claude-code/docs/zh-CN/commands/e2e.md
zdoc 88054de673 docs: Add Chinese (zh-CN) translations for all documentation
* docs: add Chinese versions docs

* update

---------

Co-authored-by: neo <neo.dowithless@gmail.com>
2026-02-05 05:57:54 -08:00

371 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: 使用 Playwright 生成并运行端到端测试。创建测试旅程、运行测试、捕获截图/视频/跟踪,并上传工件。
---
# E2E 命令
此命令调用 **e2e-runner** 代理来使用 Playwright 生成、维护和执行端到端测试。
## 此命令的作用
1. **生成测试旅程** - 为用户流程创建 Playwright 测试
2. **运行 E2E 测试** - 跨浏览器执行测试
3. **捕获工件** - 失败时的截图、视频、跟踪
4. **上传结果** - HTML 报告和 JUnit XML
5. **识别不稳定测试** - 隔离不稳定的测试
## 何时使用
在以下情况使用 `/e2e`
* 测试关键用户旅程(登录、交易、支付)
* 验证多步骤流程端到端工作
* 测试 UI 交互和导航
* 验证前端和后端之间的集成
* 为生产部署做准备
## 工作原理
e2e-runner 代理将:
1. **分析用户流程**并识别测试场景
2. **使用页面对象模型模式生成 Playwright 测试**
3. **跨多个浏览器Chrome、Firefox、Safari运行测试**
4. **捕获失败**,包括截图、视频和跟踪
5. **生成包含结果和工件的报告**
6. **识别不稳定测试**并推荐修复方法
## 使用示例
````
User: /e2e Test the market search and view flow
Agent (e2e-runner):
# E2E Test Generation: Market Search and View Flow
## Test Scenario Identified
**User Journey:** Market Search → View Results → Click Market → View Details
**Test Coverage:**
1. Navigate to markets page
2. Perform semantic search
3. Verify search results
4. Click on first result
5. Verify market details page loads
6. Verify chart renders
## Generated Test Code
```typescript
// tests/e2e/markets/search-and-view.spec.ts
import { test, expect } from '@playwright/test'
import { MarketsPage } from '../../pages/MarketsPage'
import { MarketDetailsPage } from '../../pages/MarketDetailsPage'
test.describe('Market Search and View Flow', () => {
test('user can search markets and view details', async ({ page }) => {
// 1. Navigate to markets page
const marketsPage = new MarketsPage(page)
await marketsPage.goto()
// Verify page loaded
await expect(page).toHaveTitle(/Markets/)
await expect(page.locator('h1')).toContainText('Markets')
// 2. Perform semantic search
await marketsPage.searchMarkets('election')
// Wait for API response
await page.waitForResponse(resp =>
resp.url().includes('/api/markets/search') && resp.status() === 200
)
// 3. Verify search results
const marketCards = marketsPage.marketCards
await expect(marketCards.first()).toBeVisible()
const resultCount = await marketCards.count()
expect(resultCount).toBeGreaterThan(0)
// Take screenshot of search results
await page.screenshot({ path: 'artifacts/search-results.png' })
// 4. Click on first result
const firstMarketTitle = await marketCards.first().textContent()
await marketCards.first().click()
// 5. Verify market details page loads
await expect(page).toHaveURL(/\/markets\/[a-z0-9-]+/)
const detailsPage = new MarketDetailsPage(page)
await expect(detailsPage.marketName).toBeVisible()
await expect(detailsPage.marketDescription).toBeVisible()
// 6. Verify chart renders
await expect(detailsPage.priceChart).toBeVisible()
// Verify market name matches
const detailsTitle = await detailsPage.marketName.textContent()
expect(detailsTitle?.toLowerCase()).toContain(
firstMarketTitle?.toLowerCase().substring(0, 20) || ''
)
// Take screenshot of market details
await page.screenshot({ path: 'artifacts/market-details.png' })
})
test('search with no results shows empty state', async ({ page }) => {
const marketsPage = new MarketsPage(page)
await marketsPage.goto()
// Search for non-existent market
await marketsPage.searchMarkets('xyznonexistentmarket123456')
// Verify empty state
await expect(page.locator('[data-testid="no-results"]')).toBeVisible()
await expect(page.locator('[data-testid="no-results"]')).toContainText(
/no.*results|no.*markets/i
)
const marketCount = await marketsPage.marketCards.count()
expect(marketCount).toBe(0)
})
test('can clear search and see all markets again', async ({ page }) => {
const marketsPage = new MarketsPage(page)
await marketsPage.goto()
// Initial market count
const initialCount = await marketsPage.marketCards.count()
// Perform search
await marketsPage.searchMarkets('trump')
await page.waitForLoadState('networkidle')
// Verify filtered results
const filteredCount = await marketsPage.marketCards.count()
expect(filteredCount).toBeLessThan(initialCount)
// Clear search
await marketsPage.searchInput.clear()
await page.waitForLoadState('networkidle')
// Verify all markets shown again
const finalCount = await marketsPage.marketCards.count()
expect(finalCount).toBe(initialCount)
})
})
````
## 运行测试
```bash
# Run the generated test
npx playwright test tests/e2e/markets/search-and-view.spec.ts
Running 3 tests using 3 workers
✓ [chromium] search-and-view.spec.ts:5:3 user can search markets and view details (4.2s)
✓ [chromium] search-and-view.spec.ts:52:3 search with no results shows empty state (1.8s)
✓ [chromium] search-and-view.spec.ts:67:3 can clear search and see all markets again (2.9s)
3 passed (9.1s)
Artifacts generated:
- artifacts/search-results.png
- artifacts/market-details.png
- playwright-report/index.html
```
## 测试报告
```
╔══════════════════════════════════════════════════════════════╗
║ E2E Test Results ║
╠══════════════════════════════════════════════════════════════╣
║ Status: ✅ ALL TESTS PASSED ║
║ Total: 3 tests ║
║ Passed: 3 (100%) ║
║ Failed: 0 ║
║ Flaky: 0 ║
║ Duration: 9.1s ║
╚══════════════════════════════════════════════════════════════╝
Artifacts:
📸 Screenshots: 2 files
📹 Videos: 0 files (only on failure)
🔍 Traces: 0 files (only on failure)
📊 HTML Report: playwright-report/index.html
View report: npx playwright show-report
```
✅ E2E 测试套件已准备好进行 CI/CD 集成!
````
## Test Artifacts
When tests run, the following artifacts are captured:
**On All Tests:**
- HTML Report with timeline and results
- JUnit XML for CI integration
**On Failure Only:**
- Screenshot of the failing state
- Video recording of the test
- Trace file for debugging (step-by-step replay)
- Network logs
- Console logs
## Viewing Artifacts
```bash
# View HTML report in browser
npx playwright show-report
# View specific trace file
npx playwright show-trace artifacts/trace-abc123.zip
# Screenshots are saved in artifacts/ directory
open artifacts/search-results.png
````
## 不稳定测试检测
如果测试间歇性失败:
```
⚠️ FLAKY TEST DETECTED: tests/e2e/markets/trade.spec.ts
Test passed 7/10 runs (70% pass rate)
Common failure:
"Timeout waiting for element '[data-testid="confirm-btn"]'"
Recommended fixes:
1. Add explicit wait: await page.waitForSelector('[data-testid="confirm-btn"]')
2. Increase timeout: { timeout: 10000 }
3. Check for race conditions in component
4. Verify element is not hidden by animation
Quarantine recommendation: Mark as test.fixme() until fixed
```
## 浏览器配置
默认情况下,测试在多个浏览器上运行:
* ✅ Chromium桌面版 Chrome
* ✅ Firefox桌面版
* ✅ WebKit桌面版 Safari
* ✅ 移动版 Chrome可选
在 `playwright.config.ts` 中配置以调整浏览器。
## CI/CD 集成
添加到您的 CI 流水线:
```yaml
# .github/workflows/e2e.yml
- name: Install Playwright
run: npx playwright install --with-deps
- name: Run E2E tests
run: npx playwright test
- name: Upload artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: playwright-report
path: playwright-report/
```
## PMX 特定的关键流程
对于 PMX请优先考虑以下 E2E 测试:
**🔴 关键(必须始终通过):**
1. 用户可以连接钱包
2. 用户可以浏览市场
3. 用户可以搜索市场(语义搜索)
4. 用户可以查看市场详情
5. 用户可以下交易单(使用测试资金)
6. 市场正确结算
7. 用户可以提取资金
**🟡 重要:**
1. 市场创建流程
2. 用户资料更新
3. 实时价格更新
4. 图表渲染
5. 过滤和排序市场
6. 移动端响应式布局
## 最佳实践
**应该:**
* ✅ 使用页面对象模型以提高可维护性
* ✅ 使用 data-testid 属性作为选择器
* ✅ 等待 API 响应,而不是使用任意超时
* ✅ 测试关键用户旅程的端到端
* ✅ 在合并到主分支前运行测试
* ✅ 在测试失败时审查工件
**不应该:**
* ❌ 使用不稳定的选择器CSS 类可能会改变)
* ❌ 测试实现细节
* ❌ 针对生产环境运行测试
* ❌ 忽略不稳定测试
* ❌ 在失败时跳过工件审查
* ❌ 使用 E2E 测试每个边缘情况(使用单元测试)
## 重要注意事项
**对 PMX 至关重要:**
* 涉及真实资金的 E2E 测试**必须**仅在测试网/暂存环境中运行
* 切勿针对生产环境运行交易测试
* 为金融测试设置 `test.skip(process.env.NODE_ENV === 'production')`
* 仅使用带有少量测试资金的测试钱包
## 与其他命令的集成
* 使用 `/plan` 来识别要测试的关键旅程
* 使用 `/tdd` 进行单元测试(更快、更细粒度)
* 使用 `/e2e` 进行集成和用户旅程测试
* 使用 `/code-review` 来验证测试质量
## 相关代理
此命令调用位于 `~/.claude/agents/e2e-runner.md` 的 `e2e-runner` 代理。
## 快速命令
```bash
# Run all E2E tests
npx playwright test
# Run specific test file
npx playwright test tests/e2e/markets/search.spec.ts
# Run in headed mode (see browser)
npx playwright test --headed
# Debug test
npx playwright test --debug
# Generate test code
npx playwright codegen http://localhost:3000
# View report
npx playwright show-report
```