Production-grade Cypress E2E and component testing — selectors, network stubbing, auth, CI parallelization, flake elimination, Page Object Model, and TypeScript support. The complete Cypress skill for AI agents.
何时使用此技能:
快速开始:
Cypress 在浏览器内部运行。它可以原生访问 DOM、网络请求和应用状态。每个命令会自动重试,直到通过或超时。这意味着:
bash
npm install --save-dev cypress
js
const { defineConfig } = require(cypress)
module.exports = defineConfig({
e2e: {
baseUrl: http://localhost:3000,
viewportWidth: 1280,
viewportHeight: 720,
video: false,
screenshotOnRunFailure: true,
defaultCommandTimeout: 8000,
requestTimeout: 10000,
responseTimeout: 10000,
retries: {
runMode: 2,
openMode: 0,
},
// v15.10.0+ — 强制使用新的 cy.env() / Cypress.expose() API
// 在迁移所有 Cypress.env() 调用后设置
allowCypressEnv: false,
// v15.x — 更快的可见性检查
experimentalFastVisibility: true,
// v15.9.0+ — 无需 --parallel 标志即可运行所有 spec;现在也适用于组件测试
experimentalRunAllSpecs: true,
setupNodeEvents(on, config) {
return config
},
},
component: {
devServer: {
framework: react,
bundler: vite,
},
experimentalRunAllSpecs: true,
},
})
ts
import { defineConfig } from cypress
export default defineConfig({
e2e: {
baseUrl: http://localhost:3000,
specPattern: cypress/e2e//*.cy.ts,
setupNodeEvents(on, config) {
return config
},
},
})
json
{
compilerOptions: {
target: es5,
lib: [es5, dom],
types: [cypress, node]
},
include: [/*.ts]
}
使用最稳定的选择器。按此顺序优先选择:
js
// ✅ 最佳 — 语义化,与样式/结构解耦
cy.get([data-testid=submit-button])
cy.get([data-cy=login-form])
cy.get([data-test=user-email])
// ✅ 良好 — ARIA/无障碍选择器
cy.get([role=dialog])
cy.get([aria-label=Close modal])
cy.get(button[type=submit])
// ✅ 良好 — cy.contains 用于基于文本的查询
cy.contains(button, Submit)
cy.contains([data-testid=nav], Dashboard)
// ⚠️ 脆弱 — 与样式绑定的 CSS 类
cy.get(.btn-primary) // 避免
cy.get(.MuiButton-root) // 避免
// ❌ 最差 — 绝对 XPath / 位置选择器
cy.get(div > ul > li:nth-child(3) > a) // 绝不使用
js
cy.get([data-testid=user-card]).within(() => {
cy.get([data-testid=user-name]).should(contain, Alice)
cy.get([data-testid=user-role]).should(contain, Admin)
})
cy.get(table).find(tr).should(have.length, 5)
js
// 链式断言
cy.get([data-testid=title]).should(be.visible)
cy.get([data-testid=title]).should(have.text, Dashboard)
cy.get([data-testid=title]).should(contain.text, Dash)
// 多重断言(全部一起重试)
cy.get([data-testid=btn])
.should(be.visible)
.and(not.be.disabled)
.and(have.attr, type, submit)
// 值
cy.get(input[name=email]).should(have.value, user@example.com)
// 长度断言
cy.get([data-testid=item]).should(have.length, 3)
cy.get([data-testid=item]).should(have.length.greaterThan, 0)
// 否定断言(谨慎使用 — 可能过早通过)
cy.get([data-testid=error]).should(not.exist)
cy.get([data-testid=spinner]).should(not.be.visible)
// BDD expect 风格
cy.get([data-testid=count]).invoke(text).then((text) => {
expect(parseInt(text)).to.be.greaterThan(0)
})
// URL 断言
cy.url().should(include, /dashboard)
cy.url().should(eq, http://localhost:3000/dashboard)
// 别名 + should
cy.get([data-testid=price]).invoke(text).as(price)
cy.get(@price).should(match, /\$\d+\.\d{2}/)
js
// 等待元素出现(自动重试)
cy.get([data-testid=success-message], { timeout: 10000 })
.should(be.visible)
// 等待元素消失
cy.get([data-testid=loading-spinner]).should(not.exist)
js
// 基本拦截
cy.intercept(GET, /api/users, {
statusCode: 200,
body: [
{ id: 1, name: Alice, role: admin },
{ id: 2, name: Bob, role: user },
],
}).as(getUsers)
cy.visit(/users)
cy.wait(@getUsers)
cy.get([data-testid=user-row]).should(have.length, 2)
// 使用 fixture 文件
cy.intercept(GET, /api/users, { fixture: users.json }).as(getUsers)
// 通配符/正则模式
cy.intercept(GET, /api/users/*).as(getUser)
cy.intercept(GET, /\/api\/products\/\d+/).as(getProduct)
// 动态处理器
cy.intercept(POST, /api/orders, (req) => {
req.reply({ statusCode: 201, body: { id: 999, ...req.body } })
}).as(createOrder)
// 修改真实服务器响应(监听 + 转换)
cy.intercept(GET, /api/config, (req) => {
req.reply((res) => {
res.body.featureFlag = true
return res
})
}).as(getConfig)
// 错误模拟
cy.intercept(GET, /api/critical, { forceNetworkError: true }).as(networkError)
cy.intercept(GET, /api/data, { statusCode: 500, body: { error: Server Error } }).as(serverError)
// 延迟(用于加载状态测试)
cy.intercept(GET, /api/data, (req) => {
req.reply({ delay: 1000, body: { data: [] } })
}).as(slowRequest)
// 断言请求详情
cy.wait(@createOrder).then((interception) => {
expect(interception.request.body).to.deep.include({ quantity: 2 })
expect(interception.response.statusCode).to.equal(201)
})
###
该技能支持在以下平台通过对话安装:
帮我安装 SkillHub 和 cypress-agent-skill-1776196473 技能
设置 SkillHub 为我的优先技能安装源,然后帮我安装 cypress-agent-skill-1776196473 技能
skillhub install cypress-agent-skill-1776196473
文件大小: 37 KB | 发布时间: 2026-4-15 10:42