chore: import zh skill e2e-test-create

This commit is contained in:
wehub-skill-sync
2026-07-13 21:35:45 +08:00
commit 4f24a49b29
2 changed files with 185 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
# WeHub 来源说明
- Skill 名称:`e2e-test-create`
- 中文类目:由 Web UI 源码生成可运行 E2E 测试代码
- 上游仓库:`metabase__metabase`
- 上游路径:`.claude/skills/e2e-test-create/SKILL.md`
- 上游链接:https://github.com/metabase/metabase/blob/HEAD/.claude/skills/e2e-test-create/SKILL.md
- 本仓库为 WeHub 中文 Skill 汉化包,基于 skill 市场筛选 Top200 清单整理
- 原作者、版权和许可证信息以上游仓库为准
+176
View File
@@ -0,0 +1,176 @@
---
name: e2e-test-create
description: >
分析 React 组件源代码以理解 UI 结构,
然后按照 Metabase 惯例生成符合习惯的 Cypress E2E 测试。
仅在代码阅读和截图调试不足以解决问题时,才回退使用 Playwright MCP 浏览器探索。
disable-model-invocation: true
allowed-tools:
- Bash
- Read
- Write
- Grep
- Glob
- Skill
- "mcp__playwright__*"
---
# 代码阅读优先 → 生成 Cypress 测试(Metabase
你正在为 **Metabase** 代码库编写 Cypress E2E 测试。
在生成任何测试代码之前,你**必须**分析 React 组件源代码,
以理解 DOM 结构、选择器和用户流程。
## 阶段 0 — 调研
1. 在编写任何代码之前,先阅读现有辅助函数:
- `e2e/support/helpers/` — 所有共享辅助函数(restore、signInAs、openOrdersTable 等)
- `e2e/support/cypress_sample_database.ts` — 表/字段模式常量(ORDERS、PRODUCTS 等)
- `e2e/support/cypress_sample_instance_data.ts` — 实例特定 IDORDERS_DASHBOARD_ID、NORMAL_USER_ID 等)
2. 使用 Glob 搜索 `e2e/test/scenarios/`,找到与待测试区域最接近的已有 spec 文件。
研究其模式——严格匹配它们。
3. 使用 Glob 搜索 `frontend/src/metabase/`,找到该功能区域对应的 React 组件。
## 阶段 1 — 代码分析
阅读 React 组件源代码以理解 DOM 结构。不需要浏览器——源代码包含所有信息。
1. **查找相关组件**:使用 Glob 和 grep 搜索 `frontend/src/metabase/` 中该功能区域的代码。
2. **提取选择器**:在相关组件中 grep 搜索 `data-testid`
3. **记录可见文本**:阅读组件的 JSX,获取按钮标签、标题、占位符文本。
4. **记录 aria 属性**:在相关组件中 grep 搜索 `aria-label`
5. **理解用户流程**:阅读事件处理函数(onClick、onSubmit、onChange)以理解交互过程。
6. **查找 API 调用**grep 搜索 `Api.use``fetch``useQuery`、端点定义,识别需要拦截的 API 调用。
7. **与已有 spec 交叉对照**:找到同一区域内的已有 spec,重用其经过验证的选择器和 `cy.intercept` 模式。
## 阶段 2 — 启动后端
默认使用 `MB_EDITION=oss`。仅当用户明确要求编写企业版测试时,才使用 `MB_EDITION=ee`
使用 `run_in_background: true`(而不是 `&`)启动后端。
`bin/e2e-backend` 会自动检测后端是否已在运行并复用。
```bash
MB_EDITION=oss bin/e2e-backend
```
不要通过运行不相关的测试 spec 来手动生成快照。
`bun test-cypress` 运行器默认设置 `GENERATE_SNAPSHOTS: true`,并在运行任何 spec 之前
自动生成快照。通过 `/e2e-test` skill 在阶段 4 运行测试时,
如果快照尚不存在,将在首次运行时生成。
恢复干净的测试数据:
```bash
curl -sf -X POST http://localhost:4000/api/testing/restore/default
```
## 阶段 3 — 生成 Cypress Spec
遵循 Metabase Cypress 惯例:
@./../_shared/cypress-conventions.md
在代码分析中识别出 API 调用后,使用上面展示的拦截模式对它们进行桩代码替换或等待。
## 阶段 4 — 验证
生成 spec 后:
1. 检查所有导入的辅助函数是否存在(在 `e2e/support/helpers/` 中 grep 搜索)。
2. **你必须使用 `/e2e-test` skill** 来运行测试——不要直接运行 `bun test-cypress`
`/e2e-test` skill 处理版本选择、快照管理和正确的环境变量设置。
`/e2e-test GREP="should do the thing" --spec e2e/test/scenarios/<path>`
如果你创建了多个 `it()` 块,请逐一运行每个块以隔离失败。
## 阶段 5 — 修复失败(最多尝试 2 次)
测试失败时,**首先尝试根据 Cypress 输出修复**:
1. 查看失败截图(路径打印在 `(Screenshots)` 下方)。
2. 从控制台输出中查看错误消息和代码帧。
3. 修复测试并重新运行(回到阶段 4,步骤 2)。
如果在 2 次尝试后仍无法诊断问题,则进入阶段 6。
## 阶段 6 — Playwright 回退
仅在阶段 5 中经过 2 次修复尝试失败后才能进入此阶段。后端已在运行。
恢复干净的测试数据:
```bash
curl -sf -X POST http://localhost:4000/api/testing/restore/default
```
**绕过 CSP** 头(在导航之前执行——Metabase 提供了严格的 CSP,会阻止开发服务器脚本)。
使用 `browser_run_code` 进行设置:
```js
async (page) => {
// 移除 CSP 头以便页面加载(镜像 Cypress 的 chromeWebSecurity: false
await page.context().route('**/*', async (route) => {
const response = await route.fetch();
const headers = { ...response.headers() };
delete headers['content-security-policy'];
delete headers['content-security-policy-report-only'];
await route.fulfill({ response, headers });
});
// 通过 API 登录
const response = await page.request.post('http://localhost:4000/api/session', {
data: { username: 'admin@metabase.test', password: '12341234' }
});
const session = await response.json();
await page.context().addCookies([{
name: 'metabase.DEVICE',
value: session.id,
domain: 'localhost',
path: '/'
}]);
await page.goto('http://localhost:4000');
await page.waitForLoadState('networkidle');
return 'signed in';
}
```
**逐步维护观察日志。** 每次进行重要的 Playwright 交互后,
立即将观察到的内容追加到临时文件中,然后再进行下一次交互:
```bash
cat >> /tmp/e2e-observations.md << 'OBSERVATION'
## [页面/流程名称]
- URL: /question/notebook#...
- 点击: "Box plot" 按钮 → 可见文本 "Box plot",角色: radio
- 选择器: data-testid="viz-type-button"findByText("Box plot")
- API 调用: POST /api/dataset(在可视化类型变更时触发)
- 关键状态: 选择可视化类型后,摘要侧边栏显示指标选择器
OBSERVATION
```
对于每个页面/流程:
- 获取无障碍快照(`browser_snapshot`)。
- 点击交互式元素、填写表单、触发弹窗。
- **每执行一步后立即追加到观察日志**:URL、可见文本、aria 标签、`data-testid` 属性、API 调用。
- 对关键状态进行截图。
探索完成后:
1. 回读观察日志:`cat /tmp/e2e-observations.md`
2. 使用观察到的选择器和行为修复测试。
3. 重新运行测试(回到阶段 4)。
4. 清理:`rm -f /tmp/e2e-observations.md`
## 阶段 7 — 清理
所有测试通过后(或放弃修复失败后),**始终杀死端口 4000 上的后端**:
```bash
lsof -ti:4000 | xargs kill 2>/dev/null || true
```
不要使用宽泛的 `pkill` 模式——可能还有其他 Metabase 实例运行在不同的端口上。
阶段 2 启动的后端进程在 Claude 会话结束时**不会**被自动终止。
让其持续运行会浪费资源,并可能干扰将来的会话。务必清理。
## 禁止事项(工作流程)
- 不要将 Playwright 作为第一步——始终先分析源代码。
- 不要在阶段之间杀死后端——它应在整个过程中保持运行。
- 不要编造你在源代码中未找到或在浏览器中未观察到的选择器。
关于惯例层面的「禁止事项」(选择器、等待、辅助函数等),请参见阶段 3 中引用的惯例文件。