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

Cypress打开新标签页无法切换 spy监听window.open失效报错

问题描述

在Cypress自动化测试过程中遇到如下场景:点击指定链接元素会触发新标签页/新窗口打开逻辑,因Cypress原生不支持多标签页测试能力,尝试使用监听window.open的变通方案实现测试逻辑,但方案未生效:点击元素后浏览器确实打开了新标签页,但测试逻辑无法切换到新标签页上下文,用例执行失败抛出错误:

expected redirect to have been called at least once, but it was never called.

原有测试代码如下:

cy.visit('https://qa.abc.com/xyz/documents?action_id=1');

cy.window().then((win) => {
  cy.spy(win, 'open').as('redirect');
});

cy.get(':nth-child(1) > [style="width: 228px;"] > .text-ellipsis')
  .click();

cy.get('@redirect')
  .should('be.called');

补充说明:该场景下跳转的目标URL为动态生成,与JavaScript逻辑绑定,既无法直接从控制台获取到目标URL,也无法通过移除链接属性的方式修改跳转逻辑。
问题报错截图

可复现问题的最小示例代码

以下HTML代码可完整复现该问题:

<html>
   <head>
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <title>Change Content - Javascript</title>
      <meta name="robots" content="noindex, nofollow">
      <meta name="googlebot" content="noindex, nofollow">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
   </head>
   <body>
      <a id="myelement" href="javascript:void(0);" onclick="openNewTab()" "">Open New Tab </a>
      <script type="text/javascript">//<![CDATA[
         function openNewTab() {
            
           window.openNew({
               target:'test_blank', 
               url: 'https://www.google.co.in/'
            });
         }
         
         function openNew(option) {
             const form = document.createElement("form");
             form.target = option.target || "_blank";
             form.action = option.url;
             form.method = "GET";
         
             document.body.appendChild(form);
             form.submit();
             $(form).remove();
         }
         
         
           //]]>
      </script>
   </body>
</html>
问题根因

原有window.open监听方案失效的原因非常直接:当前页面的新标签页跳转逻辑,根本没有调用原生window.openAPI。
从可复现代码可以看到,跳转逻辑是自定义实现的:点击元素后触发自定义的openNewTab方法,内部调用window.openNew函数,动态创建一个带target属性的form表单,将目标地址设为表单的action属性后调用form.submit()触发提交,完全靠form的target属性打开新标签页,全程没有调用window.open,给window.open挂载的spy自然捕获不到任何调用,最终抛出上述错误。

解决方案

Cypress原生不支持多标签页上下文切换,针对这种动态form提交触发新标签的场景,不需要切换标签上下文,直接拦截表单提交行为即可完成校验,以下是两种可直接落地的方案:

方案1:拦截form提交原型方法,捕获跳转参数做断言

通过stub掉表单原生submit方法的方式埋点,不管页面什么时候动态创建form,只要触发submit就会被拦截,不需要提前绑定DOM事件,代码如下:

cy.visit('https://qa.abc.com/xyz/documents?action_id=1');

cy.window().then((win) => {
  // 拦截所有form的submit原生方法
  cy.stub(win.HTMLFormElement.prototype, 'submit').callsFake(function() {
    // this指向当前触发提交的form实例,直接读取跳转参数
    const jumpData = {
      target: this.target,
      url: this.action
    }
    // 将参数挂到window对象上方便后续断言
    win.__test_jump_data = jumpData;
  }).as('formSubmitSpy');
});

// 点击触发跳转的元素
cy.get(':nth-child(1) > [style="width: 228px;"] > .text-ellipsis')
  .click();

// 断言跳转逻辑触发
cy.get('@formSubmitSpy').should('be.called');
// 校验跳转参数符合预期,动态URL可通过包含关键字的方式校验
cy.window().its('__test_jump_data').should((data) => {
  expect(data.target).to.equal('test_blank');
  expect(data.url).to.include('目标地址的关键路径/参数片段');
});

方案2:修改跳转目标为当前窗口,直接校验跳转后页面内容

如果需要校验跳转后页面的内容,可以在拦截submit的时候将form的target改为_self,让表单提交在当前Cypress控制的窗口内完成,不需要处理多标签上下文,代码如下:

cy.visit('https://qa.abc.com/xyz/documents?action_id=1');

cy.window().then((win) => {
  const originSubmit = win.HTMLFormElement.prototype.submit;
  cy.stub(win.HTMLFormElement.prototype, 'submit').callsFake(function() {
    // 将跳转目标改成本窗口,避免打开新标签
    this.target = '_self';
    // 调用原生submit逻辑完成跳转
    originSubmit.call(this);
  });
});

// 点击元素,等待当前页面跳转到目标地址
cy.get(':nth-child(1) > [style="width: 228px;"] > .text-ellipsis')
  .click();

// 后续直接按照单页面跳转的逻辑,校验URL、页面元素即可
cy.url().should('include', '目标地址的关键路径');
避坑提示
  • 不要盲目套用window.open监听的多标签测试方案:该方案仅对业务代码显式调用window.open()打开新页的场景有效,带target属性的a标签跳转、动态form提交触发的新标签都不会调用window.open,监听必然失效。
  • 动态生成的DOM元素不要等渲染后再绑定事件:本场景下的form是点击后临时创建、提交后立刻删除的,必须通过拦截原型方法、document层事件委托的方式提前埋点,否则会错过事件触发时机。
  • 动态跳转地址不需要提前从控制台抓取:拦截到form提交事件后,直接读取form实例的action属性就能拿到完整的最终跳转地址,支持做路径匹配、参数校验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:57:20