Skip to main content
ClaudeWave
ES, Spanish
Slash Command2k estrellas del repoactualizado 7mo ago

e2e

This slash command invokes the e2e-runner agent to generate, maintain, and execute end-to-end tests using Playwright across multiple browsers. Use it to create and run automated test journeys for critical user flows, capture failure artifacts like screenshots and video traces, and generate HTML reports to verify application functionality before production deployment.

Instalar en Claude Code
Copiar
mkdir -p ~/.claude/commands && curl -fsSL https://raw.githubusercontent.com/xu-xiang/everything-claude-code-zh/HEAD/commands/e2e.md -o ~/.claude/commands/e2e.md
Después abre una sesión nueva de Claude Code; el slash command carga automáticamente.

e2e.md

# E2E 命令

此命令调用 **e2e-runner** 智能体(Agent)来使用 Playwright 生成、维护和执行端到端测试(End-to-End Tests/E2E)。

## 此命令的作用

1. **生成测试旅程(Test Journeys)** - 为用户流创建 Playwright 测试
2. **运行 E2E 测试** - 在不同浏览器上执行测试
3. **捕获产物(Artifacts)** - 在失败时捕获截图、视频和追踪(Traces)
4. **上传结果** - 生成 HTML 报告和 JUnit XML
5. **识别不稳定测试(Flaky Tests)** - 隔离不稳定的测试

## 何时使用

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

## 工作原理

e2e-runner 智能体将执行以下操作:

1. **分析用户流**并识别测试场景
2. 使用页面对象模型(Page Object Model/POM)模式**生成 Playwright 测试**
3. 在多个浏览器(Chrome、Firefox、Safari)上**运行测试**
4. 通过截图、视频和追踪**捕获失败信息**
5. **生成报告**,包含结果和产物
6. **识别不稳定测试**并推荐修复方案

## 使用示例

```
用户:/e2e 测试市场搜索和查看流程

智能体 (e2e-runner):
# E2E 测试生成:市场搜索和查看流程

## 识别出的测试场景

**用户旅程:** 市场搜索 → 查看结果 → 点击市场 → 查看详情

**测试覆盖范围:**
1. 导航到市场页面
2. 执行语义搜索
3. 验证搜索结果
4. 点击第一个结果
5. 验证市场详情页面加载
6. 验证图表渲染

## 生成的测试代码

```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. 导航到市场页面
    const marketsPage = new MarketsPage(page)
    await marketsPage.goto()

    // 验证页面加载
    await expect(page).toHaveTitle(/Markets/)
    await expect(page.locator('h1')).toContainText('Markets')

    // 2. 执行语义搜索
    await marketsPage.searchMarkets('election')

    // 等待 API 响应
    await page.waitForResponse(resp =>
      resp.url().includes('/api/markets/search') && resp.status() === 200
    )

    // 3. 验证搜索结果
    const marketCards = marketsPage.marketCards
    await expect(marketCards.first()).toBeVisible()
    const resultCount = await marketCards.count()
    expect(resultCount).toBeGreaterThan(0)

    // 截取搜索结果截图
    await page.screenshot({ path: 'artifacts/search-results.png' })

    // 4. 点击第一个结果
    const firstMarketTitle = await marketCards.first().textContent()
    await marketCards.first().click()

    // 5. 验证市场详情页面加载
    await expect(page).toHaveURL(/\/markets\/[a-z0-9-]+/)

    const detailsPage = new MarketDetailsPage(page)
    await expect(detailsPage.marketName).toBeVisible()
    await expect(detailsPage.marketDescription).toBeVisible()

    // 6. 验证图表渲染
    await expect(detailsPage.priceChart).toBeVisible()

    // 验证市场名称匹配
    const detailsTitle = await detailsPage.marketName.textContent()
    expect(detailsTitle?.toLowerCase()).toContain(
      firstMarketTitle?.toLowerCase().substring(0, 20) || ''
    )

    // 截取市场详情截图
    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()

    // 搜索不存在的市场
    await marketsPage.searchMarkets('xyznonexistentmarket123456')

    // 验证空状态
    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()

    // 初始市场数量
    const initialCount = await marketsPage.marketCards.count()

    // 执行搜索
    await marketsPage.searchMarkets('trump')
    await page.waitForLoadState('networkidle')

    // 验证过滤后的结果
    const filteredCount = await marketsPage.marketCards.count()
    expect(filteredCount).toBeLessThan(initialCount)

    // 清除搜索
    await marketsPage.searchInput.clear()
    await page.waitForLoadState('networkidle')

    // 验证再次显示所有市场
    const finalCount = await marketsPage.marketCards.count()
    expect(finalCount).toBe(initialCount)
  })
})
```

## 运行测试

```bash
# 运行生成的测试
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/search-results.png
- artifacts/market-details.png
- playwright-report/index.html
```

## 测试报告

```
╔══════════════════════════════════════════════════════════════╗
║                    E2E 测试结果                              ║
╠══════════════════════════════════════════════════════════════╣
║ 状态:       ✅ 所有测试通过                                   ║
║ 总计:       3 个测试                                          ║
║ 通过:       3 (100%)                                         ║
║ 失败:       0                                                ║
║ 不稳定:     0                                                ║
║ 耗时:       9.1s                                             ║
╚══════════════════════════════════════════════════════════════╝

产物:
📸 截图: 2 个文件
📹 视频: 0 个文件 (仅在失败时生成)
🔍 追踪: 0 个文件 (仅在失败时生成)
📊 HTML 报告: playwright-report/index.html

查看报告: npx playwright show-report
```

✅ E2E 测试套件已就绪,可进行 CI/CD 集成!
```

## 测试产物(Artifacts)

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

**所有测试均会捕获:**
- 包含时间线和结果的 HTML 报告
- 用于 CI 集成的 JUnit XML

**仅在失败时捕获:**
- 失败状态的截图
- 测试过程的录屏视频
- 用于调试的追踪文件(单步回放)
- 网络日志
- 控制台日志

## 查看产物

```bash
# 在浏览器中查看 HTML 报告
npx playwright show-report

# 查看特定的追踪文件
npx playwright show-trace artifacts/trace-abc123.zip

# 截图保存在 artifacts/ 目录下
open artifacts/search-results.png
```

## 不稳定测试检测

如果测试间歇性失败:

```
⚠️  检测到不稳定测试 (FLAKY TEST): tests/e2e/markets/trade.spec.ts

测试在 10 次运行中通过了 7 次 (70% 通过率)

常见失败原因:
"Timeout waiting for element '[data-testid="confirm-btn"]'"

推荐修复建议:
1. 添加显式等待: await page.waitForSelector('[data-testid="confirm-btn"]')
2. 增加超时时间: { timeout: 10000 }
3. 检查组件中的竞态条件
4. 验证元素未被动画隐藏

隔离建议: 在修复前标记为 test.fixme()
```

## 浏览器配置

测试默认在多个浏览器上运行:
- ✅ Ch
api-designSkill

生产级 API 的 REST API 设计模式,包括资源命名、状态码、分页、过滤、错误响应、版本控制和速率限制。

architectSubagent

用于系统设计、可扩展性及技术决策的软件架构专家。在规划新功能、重构大型系统或做出架构决策时请主动(PROACTIVELY)使用。

article-writingSkill

编写文章、指南、博客、教程、时事通讯(Newsletter)等长内容,支持从示例或品牌指南中提取独特的语感语调。适用于需要撰写超过一个段落的精炼文本,尤其是对语气一致性、结构和可信度有较高要求时。

backend-patternsSkill

后端架构模式、API 设计、数据库优化以及 Node.js、Express 和 Next.js API 路由的服务端最佳实践。

build-error-resolverSubagent

构建与 TypeScript 错误修复专家。当构建失败或出现类型错误时,请主动(PROACTIVELY)使用。仅修复构建/类型错误,保持最小差异(diff),不进行架构性修改。重点是快速使构建通过(get the build green)。

chief-of-staffSubagent

个人通讯幕僚 (Chief of Staff),负责分拣电子邮件、Slack、LINE 和 Messenger。将消息分类为 4 个级别 (skip/info_only/meeting_info/action_required),生成草稿回复,并通过钩子 (Hooks) 强制执行发送后的后续跟进。适用于管理多渠道通讯工作流。

clawSlash Command

启动 NanoClaw 智能体 (Agent) REPL — 一个由 claude CLI 驱动的持久化、会话感知 (session-aware) 的 AI 助手。

clickhouse-ioSkill

ClickHouse 数据库模式、查询优化、分析以及高性能分析工作负载的数据工程最佳实践。