You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将cy.on移至Cypress自定义命令后失效的原因是什么?

Cypress自定义命令中window.open Stub失效问题解析

问题场景

原本在测试代码中定义的本地函数可以正常检测window.open调用并断言:

// 本地stub函数
const stubWindowOpen = () => {
  const stub = cy.stub().as(`window-open`)
  cy.on(`window:before:load`, (window) => {
    cy.stub(window, `open`).callsFake(stub)
  })
}

// 断言函数
const assertWindowOpened = (url) => {
  cy.get(`@window-open`).should(`have.been.calledOnce`)
  cy.get(`@window-open`).should(`be.calledWith`, url, `_blank`)
}

将stubWindowOpen转为/support/commands.js中的自定义命令后,断言失败,提示:

expected window-open to have been called exactly once, but it was never called

失效原因

核心问题在于**cy.stub()命令的异步特性**与window:before:load事件的同步触发时机不匹配:

  • 在window:before:load的回调中使用cy.stub()时,该命令会被加入Cypress的异步命令队列,而非立即执行
  • window:before:load事件是同步触发的,回调执行完成后,页面代码可能随即调用window.open,此时队列中的cy.stub操作还未执行,原生window.open方法并未被替换,导致stub从未被调用
  • 本地函数能正常工作是因为测试代码的执行调度刚好让cy.stub在window.open调用前完成,但转为自定义命令后,命令队列的调度顺序打破了这个时机

修复方案

在window:before:load回调中同步替换window.open,直接使用stub赋值而非cy.stub()命令:

// /support/commands.js
Cypress.Commands.add(`stubWindowOpen`, () => {
  const stub = cy.stub().as(`window-open`)
  cy.on(`window:before:load`, (window) => {
    // 同步替换window.open,确保立即生效
    window.open = stub
  })
})

验证方式

测试代码中按正常顺序调用即可:

cy.stubWindowOpen()
cy.visit('/your-page')
// 触发打开新窗口的操作
cy.get('#open-window-btn').click()
assertWindowOpened('https://target-url.com')

内容的提问来源于stack exchange,提问作者PBrown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 01:52:28