跳转至

E2E 命令

此命令调用 e2e-runner 代理,使用 Playwright 生成、维护和执行端到端测试。

此命令的功能

  1. 生成测试旅程 - 为用户流程创建 Playwright 测试
  2. 运行 E2E 测试 - 在多个浏览器中执行测试
  3. 捕获工件 - 失败时的截图、视频和跟踪
  4. 上传结果 - HTML 报告和 JUnit XML
  5. 识别不稳定测试 - 将不稳定测试隔离

何时使用

在以下情况下使用 /e2e: - 测试关键用户旅程(登录、交易、支付) - 验证多步骤端到端流程 - 测试 UI 交互和导航 - 验证前端与后端之间的集成 - 为生产部署做准备

工作原理

e2e-runner 代理将:

  1. 分析用户流程 并识别测试场景
  2. 使用 Page Object Model 模式 生成 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)
  })
})

运行测试

# 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:     PASS: ALL TESTS PASSED                              ║
║ Total:      3 tests                                          ║
║ Passed:     3 (100%)                                         ║
║ Failed:     0                                                ║
║ Flaky:      0                                                ║
║ Duration:   9.1s                                             ║
╚══════════════════════════════════════════════════════════════╝



产物:
 截图:2 个文件
 视频:0 个文件(仅在失败时)
 跟踪:0 个文件(仅在失败时)
 HTML 报告:playwright-report/index.html

查看报告:npx playwright show-report

PASS: E2E test suite ready for CI/CD integration!

## 测试产物 {#artefatos-de-teste}

当测试运行时,会捕获以下产物:

**在所有测试中:**
- 带时间线和结果的 HTML 报告
- 用于 CI 集成的 JUnit XML

**仅在失败时:**
- 失败状态的截图
- 测试视频录制
- 用于调试的 trace 文件(逐步回放)
- 网络日志
- 控制台日志

## 查看产物 {#visualizando-artefatos}

```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

不稳定测试检测

如果测试间歇性失败:

WARNING:  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

浏览器配置

测试默认在多个浏览器中运行: - PASS: Chromium(桌面版 Chrome) - PASS: Firefox(桌面版) - PASS: WebKit(桌面版 Safari) - PASS: Mobile Chrome(可选)

在 playwright.config.ts 中配置以调整浏览器。

CI/CD 集成

将其添加到您的 CI 流水线:

# .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. 移动响应式布局

最佳实践

应该: - PASS: 使用 Page Object Model 以便维护 - PASS: 使用 data-testid 属性作为选择器 - PASS: 等待 API 响应,而不是任意超时 - PASS: 端到端测试关键用户旅程 - PASS: 在合并到 main 之前运行测试 - PASS: 测试失败时审查产物

不要: - FAIL: 使用脆弱选择器(CSS 类可能会变化) - FAIL: 测试实现细节 - FAIL: 对生产环境运行测试 - FAIL: 忽略不稳定测试 - FAIL: 在失败时跳过产物审查 - FAIL: 用 E2E 测试所有边缘情况(使用单元测试)

重要说明

对 PMX 关键: - 涉及真实资金的 E2E 测试必须仅在 testnet/staging 上运行 - 切勿在生产环境运行交易测试 - 对财务测试设置 test.skip(process.env.NODE_ENV === 'production') - 仅使用带有少量测试资金的测试钱包

与其他命令集成

  • 使用 /plan 识别需要测试的关键旅程
  • 使用 /tdd 进行单元测试(更快且更细粒度)
  • 使用 /e2e 进行集成和用户旅程
  • 使用 /code-review 检查测试质量

相关代理

此命令调用由 ECC 提供的 e2e-runner 代理。

对于手动安装,源文件位于: agents/e2e-runner.md

快速命令

# 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

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC