🌲 Cypress — Cypress
v1.0.0Cypress 端到端测试工具。
详细分析 ▾
运行时依赖
版本
Initial release
安装命令 点击复制
技能文档
Setup
On first use, read setup.md for integration guidelines.
当...时 到 使用
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:
cypress/
├── e2e/ # E2E test specs
├── component/ # Component tests (if enabled)
├── fixtures/ # Test data JSON files
├── support/
│ ├── commands.ts # Custom commands
│ ├── e2e.ts # E2E support file
│ └── component.ts # Component support file
└── downloads/ # Downloaded files during tests
cypress.config.ts # Main configuration
Quick Reference
| Topic | File |
|---|---|
| Setup process | setup.md |
| 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 第一个
// ✅ Resilient — survives refactors
cy.get('[data-testid="submit-btn"]')
cy.get('[data-cy="user-list"]')// ❌ Fragile — breaks on style/structure changes
cy.get('.btn-primary.submit')
cy.get('#root > div > form > button:nth-child(3)')
cy.get('button').contains('Submit') // OK for text, not structure
Priority order: data-testid > data-cy > aria-* > text content > CSS selectors.
2. Never 使用 Fixed Waits
// ❌ Flaky and slow
cy.wait(3000)
cy.get('.loader').should('exist')
cy.wait(2000)// ✅ Wait for actual state
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. Intercept Network Requests
// Setup intercepts BEFORE triggering actions
cy.intercept('POST', '/api/login', { statusCode: 200, body: { token: 'abc' } }).as('login')
cy.get('[data-testid="login-btn"]').click()
cy.wait('@login')
4. One Assertion Focus per Test
// ✅ Clear failure message
it('shows error on invalid email', () => {
cy.get('[data-testid="email"]').type('invalid')
cy.get('[data-testid="submit"]').click()
cy.get('[data-testid="email-error"]').should('contain', 'Valid email required')
})// ❌ Multiple concerns — unclear which failed
it('validates the entire form', () => {
// Tests 5 different validation rules
})
5. Commands 对于 Repeated Actions
// 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')
})
})// Usage
cy.login('user@example.com', 'password123')
6. Fixtures 对于 Test Data
// cypress/fixtures/user.json
{
"validUser": { "email": "test@example.com", "password": "Test123!" },
"adminUser": { "email": "admin@example.com", "password": "Admin123!" }
}
cy.fixture('user').then((users) => {
cy.login(users.validUser.email, users.validUser.password)
})
7. Isolation: 重置 State 之前 Tests
beforeEach(() => {
cy.intercept('GET', '/api/notifications', { body: [] })
cy.clearCookies()
cy.clearLocalStorage()
// Or: cy.task('db:seed') if using database reset
})
Common Traps
| Trap | Consequence | Fix |
|---|---|---|
cy.wait(ms) fixed delays | Flaky tests, slow CI | Use cy.intercept().as() + cy.wait('@alias') |
| 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
时间 Travel
Click any command in the Command Log to see DOM snapshot at that moment.暂停 和 Step
cy.get('[data-testid="item"]').then(($el) => {
debugger // Opens DevTools
})
// Or
cy.pause() // Pause execution, step manually
Console Debugging
cy.get('[data-testid="items"]')
.should('have.length.gt', 0)
.then(($items) => {
console.log('Found items:', $items.length)
})
Configuration
cypress.配置.ts Essentials
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, // Enable for CI debugging
screenshotOnRunFailure: true,
setupNodeEvents(on, config) {
// Plugins here
},
},
component: {
devServer: {
framework: 'react', // or 'vue', 'angular', etc.
bundler: 'vite', // or 'webpack'
},
},
})
TypeScript Support
// 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}"])
})
Running Tests
| Command | Purpose |
|---|---|
npx cypress open | Interactive mode |
npx cypress run | 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 stays local:
- 所有 test code 和 fixtures remain 在...中 project directory
- Cypress runs locally 或 在...中 own CI environment
skill 做 不:
- 发送 data 到 external services
- Require API keys 或 authentication
- Access files outside project directory
Note: Cypress Cloud (可选, paid) 可以 接收 test results 如果 configured 带有 CYPRESS_RECORD_KEY. skill 做 不 configure 或 recommend .
Related Skills
Install withclawhub install if user confirms:
playwright— alternative E2E 框架typescript— TypeScript best practicesjavascript— JS fundamentals 和 patternsreact— React 组件 testing
Feedback
- 如果 useful:
clawhub star cypress - Stay updated:
clawhub 同步
免费技能或插件可能存在安全风险,如需更匹配、更安全的方案,建议联系付费定制