5月27日 23:18

Cypress 自定义命令怎么用?

Cypress 自定义命令(Custom Commands)是通过 Cypress.Commands.add()cypress/support/commands.js 中注册的可复用测试函数,调用方式与 cy.visit() 等内置命令一致,核心目的是消除跨用例的重复代码。

创建自定义命令

cypress/support/commands.js 中定义:

javascript
Cypress.Commands.add('login', (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.login('user@example.com', 'password'),无需每次重复编写登录步骤。

三种命令类型

Cypress.Commands.add() 第二个参数可选 prevSubject,决定命令的调用方式:

  • 父命令(默认):独立调用,如 cy.login()
  • 子命令:必须链式接在前一个命令后,对获取到的元素操作
javascript
Cypress.Commands.add('drag', { prevSubject: 'element' }, (subject, options) => { cy.wrap(subject) .trigger('mousedown', { button: 0 }) .trigger('mousemove', { clientX: options.x, clientY: options.y }) .trigger('mouseup'); }); // 使用:cy.get('.box').drag({ x: 100, y: 200 })
  • 双重命令{ prevSubject: 'optional' },既可独立调用也可链式调用

覆盖已有命令

Cypress.Commands.overwrite() 改写内置命令行为:

javascript
Cypress.Commands.overwrite('visit', (originalFn, url, options) => { return originalFn(url, { ...options, headers: { Authorization: 'Bearer ...' } }); });

TypeScript 类型支持

cypress/support/index.d.ts 中声明类型,避免 TS 报错:

typescript
declare namespace Cypress { interface Chainable { login(email: string, password: string): Chainable<void>; drag(options: { x: number; y: number }): Chainable<void>; } }

常见追问

自定义命令和普通函数的区别? 自定义命令运行在 Cypress 命令队列中,支持重试和超时机制;普通 JS 函数是同步执行,不具备这些能力。

什么时候不该用自定义命令? 仅在单个 spec 文件中复用的逻辑,写成普通函数更轻量;自定义命令适合跨文件、跨模块共享的场景。

命令命名冲突怎么办? 自定义命令会覆盖同名内置命令,建议用业务前缀(如 cy.authLogin)避免冲突。

标签:Cypress