Setup
On first use, read setup.md for integration guidelines.
When to Use
User needs E2E tests, component tests, or API tests with Cypress. Agent writes tests, debugs flaky specs, configures CI/CD, and creates custom commands.
Architecture
Project tests live in the standard Cypress structure:
CODEBLOCK0
Quick Reference
| Topic | File |
|---|
| Setup process | INLINECODE1 |
| Memory template |
memory-template.md |
| Selectors & queries |
selectors.md |
| Custom commands |
commands.md |
| Network & API |
network.md |
| CI/CD configuration |
ci.md |
Core Rules
1. Selectors: data-testid First
CODEBLOCK1
Priority order: data-testid > data-cy > aria-* > text content > CSS selectors.
2. Never Use Fixed Waits
CODEBLOCK2
3. Intercept Network Requests
CODEBLOCK3
4. One Assertion Focus per Test
CODEBLOCK4
5. Commands for Repeated Actions
CODEBLOCK5
6. Fixtures for Test Data
CODEBLOCK6
CODEBLOCK7
7. Isolation: Reset State Before Tests
CODEBLOCK8
Common Traps
| Trap | Consequence | Fix |
|---|
| INLINECODE10 fixed delays | Flaky tests, slow CI | Use cy.intercept().as() + INLINECODE12 |
| CSS selectors for actions |
Break on redesign | Use
data-testid attributes |
| Test interdependence | One failure cascades | Each test must setup its own state |
| Asserting too early | False positives | Chain
.should() to auto-retry |
| Forgetting
baseUrl | Hardcoded URLs everywhere | Set
baseUrl in config |
| Skipping viewport tests | Mobile bugs in prod | Add
cy.viewport() tests |
| Ignoring retry-ability | Flaky assertions | Use Cypress queries, not jQuery |
Debugging
Time Travel
Click any command in the Command Log to see DOM snapshot at that moment.
Pause and Step
CODEBLOCK9
Console Debugging
CODEBLOCK10
Configuration
cypress.config.ts Essentials
CODEBLOCK11
TypeScript Support
CODEBLOCK12
Running Tests
| Command | Purpose |
|---|
| INLINECODE18 | Interactive mode |
| INLINECODE19 |
Headless (CI) |
|
npx cypress run --spec "cypress/e2e/login.cy.ts" | Single spec |
|
npx cypress run --headed | Headless but visible |
|
npx cypress run --browser chrome | Specific browser |
External Endpoints
This skill does not call external APIs. Cypress runs entirely locally or in your own CI environment.
Security & Privacy
Data that stays local:
- - All test code and fixtures remain in project directory
- Cypress runs locally or in your own CI environment
This skill does NOT:
- - Send data to external services
- Require API keys or authentication
- Access files outside project directory
Note: Cypress Cloud (optional, paid) can receive test results if configured with CYPRESS_RECORD_KEY. This skill does not configure or recommend it.
Related Skills
Install with
clawhub install <slug> if user confirms:
- -
playwright — alternative E2E framework - INLINECODE26 — TypeScript best practices
- INLINECODE27 — JS fundamentals and patterns
- INLINECODE28 — React component testing
Feedback
- - If useful: INLINECODE29
- Stay updated: INLINECODE30
设置
首次使用时,请阅读 setup.md 了解集成指南。
使用时机
用户需要使用 Cypress 进行端到端测试、组件测试或 API 测试。代理负责编写测试、调试不稳定测试用例、配置 CI/CD 以及创建自定义命令。
架构
项目测试文件遵循标准 Cypress 结构:
cypress/
├── e2e/ # 端到端测试用例
├── component/ # 组件测试(如启用)
├── fixtures/ # 测试数据 JSON 文件
├── support/
│ ├── commands.ts # 自定义命令
│ ├── e2e.ts # 端到端支持文件
│ └── component.ts # 组件支持文件
└── downloads/ # 测试期间下载的文件
cypress.config.ts # 主配置文件
快速参考
memory-template.md |
| 选择器与查询 | selectors.md |
| 自定义命令 | commands.md |
| 网络与 API | network.md |
| CI/CD 配置 | ci.md |
核心规则
1. 选择器:优先使用 data-testid
typescript
// ✅ 稳健——重构后仍有效
cy.get([data-testid=submit-btn])
cy.get([data-cy=user-list])
// ❌ 脆弱——样式/结构变化即失效
cy.get(.btn-primary.submit)
cy.get(#root > div > form > button:nth-child(3))
cy.get(button).contains(Submit) // 文本可接受,结构不可
优先级顺序: data-testid > data-cy > aria-* > 文本内容 > CSS 选择器。
2. 绝不使用固定等待
typescript
// ❌ 不稳定且缓慢
cy.wait(3000)
cy.get(.loader).should(exist)
cy.wait(2000)
// ✅ 等待实际状态
cy.get(.loader).should(not.exist)
cy.get([data-testid=results]).should(be.visible)
cy.intercept(GET, /api/users).as(getUsers)
cy.wait(@getUsers)
3. 拦截网络请求
typescript
// 在触发操作前设置拦截
cy.intercept(POST, /api/login, { statusCode: 200, body: { token: abc } }).as(login)
cy.get([data-testid=login-btn]).click()
cy.wait(@login)
4. 每个测试聚焦一个断言
typescript
// ✅ 清晰的失败信息
it(显示无效邮箱错误, () => {
cy.get([data-testid=email]).type(invalid)
cy.get([data-testid=submit]).click()
cy.get([data-testid=email-error]).should(contain, 需要有效邮箱)
})
// ❌ 多个关注点——不清楚哪个失败
it(验证整个表单, () => {
// 测试 5 个不同的验证规则
})
5. 重复操作使用命令
typescript
// cypress/support/commands.ts
Cypress.Commands.add(login, (email: string, password: string) => {
cy.session([email, password], () => {
cy.visit(/login)
cy.get([data-testid=email]).type(email)
cy.get([data-testid=password]).type(password)
cy.get([data-testid=submit]).click()
cy.url().should(include, /dashboard)
})
})
// 使用
cy.login(user@example.com, password123)
6. 测试数据使用 Fixtures
json
// cypress/fixtures/user.json
{
validUser: { email: test@example.com, password: Test123! },
adminUser: { email: admin@example.com, password: Admin123! }
}
typescript
cy.fixture(user).then((users) => {
cy.login(users.validUser.email, users.validUser.password)
})
7. 隔离:测试前重置状态
typescript
beforeEach(() => {
cy.intercept(GET, /api/notifications, { body: [] })
cy.clearCookies()
cy.clearLocalStorage()
// 或:cy.task(db:seed)(如使用数据库重置)
})
常见陷阱
| 陷阱 | 后果 | 修复 |
|---|
| cy.wait(ms) 固定延迟 | 测试不稳定,CI 缓慢 | 使用 cy.intercept().as() + cy.wait(@alias) |
| 使用 CSS 选择器操作 |
重新设计时失效 | 使用 data-testid 属性 |
| 测试相互依赖 | 一个失败导致连锁反应 | 每个测试必须设置自己的状态 |
| 过早断言 | 误报 | 链式调用 .should() 自动重试 |
| 忘记 baseUrl | 到处硬编码 URL | 在配置中设置 baseUrl |
| 跳过视口测试 | 生产环境出现移动端 bug | 添加 cy.viewport() 测试 |
| 忽略可重试性 | 断言不稳定 | 使用 Cypress 查询,而非 jQuery |
调试
时间旅行
点击命令日志中的任意命令,查看该时刻的 DOM 快照。
暂停与单步执行
typescript
cy.get([data-testid=item]).then(($el) => {
debugger // 打开开发者工具
})
// 或
cy.pause() // 暂停执行,手动单步执行
控制台调试
typescript
cy.get([data-testid=items])
.should(have.length.gt, 0)
.then(($items) => {
console.log(找到项目数:, $items.length)
})
配置
cypress.config.ts 要点
typescript
import { defineConfig } from cypress
export default defineConfig({
e2e: {
baseUrl: http://localhost:3000,
viewportWidth: 1280,
viewportHeight: 720,
defaultCommandTimeout: 10000,
requestTimeout: 10000,
retries: { runMode: 2, openMode: 0 },
video: false, // CI 调试时启用
screenshotOnRunFailure: true,
setupNodeEvents(on, config) {
// 插件在此处
},
},
component: {
devServer: {
framework: react, // 或 vue、angular 等
bundler: vite, // 或 webpack
},
},
})
TypeScript 支持
typescript
// cypress/support/commands.ts
declare global {
namespace Cypress {
interface Chainable {
login(email: string, password: string): Chainable
getByTestId(testId: string): Chainable>
}
}
}
Cypress.Commands.add(getByTestId, (testId: string) => {
return cy.get([data-testid=${testId}])
})
运行测试
| 命令 | 用途 |
|---|
| npx cypress open | 交互模式 |
| npx cypress run |
无头模式(CI) |
| npx cypress run --spec cypress/e2e/login.cy.ts | 单个测试用例 |
| npx cypress run --headed | 无头但可见 |
| npx cypress run --browser chrome | 指定浏览器 |
外部端点
本技能不调用外部 API。Cypress 完全在本地或您自己的 CI 环境中运行。
安全与隐私
本地保留的数据:
- - 所有测试代码和 fixtures 保留在项目目录中
- Cypress 在本地或您自己的 CI 环境中运行
本技能不会:
- - 向外部服务发送数据
- 需要 API 密钥或身份验证
- 访问项目目录外的文件
注意: Cypress Cloud(可选,付费)可在配置 CYPRESSRECORDKEY 后接收测试结果。本技能不配置也不推荐使用。
相关技能
如果用户确认,使用 clawhub install 安装:
- - playwright — 替代端到端框架
- typescript — TypeScript 最佳实践
- javascript — JS 基础与模式
- react — React 组件测试
反馈
- - 如有帮助:clawhub star cypress
- 保持更新