【问题标题】:Access a new window - cypress.io访问新窗口 - cypress.io
【发布时间】:2018-05-24 19:13:03
【问题描述】:

问题就这么简单。在 Cypress 中,如何访问在运行测试时打开的新窗口。

重建步骤:

  1. 运行测试。执行一些操作后,会弹出新窗口(网址本质上是动态的)。
  2. 填写新窗口中的字段,然后单击几个按钮。
  3. 在新窗口中完成所需操作后,关闭新窗口并返回主窗口。
  4. 使用主窗口继续执行。

兴趣点:焦点应该是

main window -> new window -> main window

我读过一些与使用iframeconfirmation box 相关的内容,但这里没有。涉及访问一个全新的窗口。类似于 Selenium 中的Window Handlers。遗憾的是找不到任何相关内容。

【问题讨论】:

    标签: javascript ui-automation cypress


    【解决方案1】:

    通过赛普拉斯访问新窗口是intentionally not supported

    不过,现在可以通过多种方式在赛普拉斯中测试此功能。您可以将测试拆分为单独的部分,并且仍然确信您的应用程序已被涵盖。

    1. 编写一个测试以检查在您的应用中执行操作时,是否通过使用cy.spy() 来调用window.open 事件以侦听window.open 事件。
    cy.visit('http://localhost:3000', {
      onBeforeLoad(win) {
        cy.stub(win, 'open')
      }
    })
    
    // Do the action in your app like cy.get('.open-window-btn').click()
    
    cy.window().its('open').should('be.called')
    
    1. 在新测试中,使用cy.visit() 转到将在新窗口中打开的网址,填写字段并单击按钮,就像在赛普拉斯测试中一样。
    cy.visit('http://localhost:3000/new-window')
    
    // Do the actions you want to test in the new window
    

    可以在here找到完整的测试示例。

    【讨论】:

    • 嗯。迂回的方式,但我猜是可行的。一个问题。如何从按钮单击中获取 URL。假设每次点击 url 都会改变。
    • 您可以使用断言be.calledWith 来代替be.called 并断言该url。我在这里创建了一个完整的工作测试示例:github.com/cypress-io/cypress-example-recipes/blob/master/…
    • 嗯,更像是:我不知道新窗口的url,如何动态获取?我想可能会得到href 属性(如果可用)?那么这种场景是否有.getattribute 函数?
    • 是的,您始终可以只使用 JavaScript。 cy.get('a').then(($a) => { var url = $a[0].getAttribute('href') })
    • 一旦我们可以访问打开的窗口,我们如何对其执行操作然后切换回旧窗口?我可以验证直到窗口打开。但我无法在这个打开的窗口上找到按钮。作品- cy.window().then((win) => { cy.spy(win, 'open').as('windowOpen'); }); cy.get('button').contains('登录你的账户').click() cy.get('@windowOpen').should('have.been.callWith', Cypress.sinon.match(' about:blank')) 这不起作用 - cy.get('@windowOpen').get('#buttonid1').click() 也不确定你如何移回旧窗口?
    【解决方案2】:

    我不是cypress专家,几天前才开始使用它,但我想出了这种带有动态链接的有状态应用程序的解决方案:

    // Get window object
    cy.window().then((win) => {
      // Replace window.open(url, target)-function with our own arrow function
      cy.stub(win, 'open', url => 
      {
        // change window location to be same as the popup url
        win.location.href = Cypress.config().baseUrl + url;
      }).as("popup") // alias it with popup, so we can wait refer it with @popup
    })
    
    // Click button which triggers javascript's window.open() call
    cy.get("#buttonWhichOpensPopupWithDynamicUrl").click()
    
    // Make sure that it triggered window.open function call
    cy.get("@popup").should("be.called")
    
    // Now we can continue integration testing for the new "popup tab" inside the same tab
    

    有没有更好的方法来做到这一点?

    【讨论】:

    • 哇,像魅力一样工作!这应该记录在官方文档中。
    • 一旦我们可以访问打开的窗口,我们如何对其执行操作然后切换回旧窗口?我可以验证直到窗口打开。但我无法在这个打开的窗口上找到按钮。作品- cy.window().then((win) => { cy.spy(win, 'open').as('windowOpen'); }); cy.get('button').contains('登录你的账户').click() cy.get('@windowOpen').should('have.been.callWith', Cypress.sinon.match(' about:blank')) 这不起作用 - cy.get('@windowOpen').get('#buttonid1').click() 也不确定你如何移回旧窗口?
    • 这很棒。它按预期工作。
    【解决方案3】:
    // We can remove the offending attribute - target='_blank'
          // that would normally open content in a new tab.
          cy.get('#users').invoke('removeAttr', 'target').click()
    
          // after clicking the <a> we are now navigated to the
          // new page and we can assert that the url is correct
          cy.url().should('include', 'users.html')
    

    Cypress - tab handling anchor links

    【讨论】:

    • 一个不错的简单技巧。非常感谢。
    【解决方案4】:

    这是我在基于"Cypress using child window"的项目中使用的解决方案

    Cypress Window Helpers (aka. Cypress Tab Helpers) 它们实际上是弹出窗口或子窗口,但为了 API 简洁,我称它们为选项卡

    cy.openTab(url, opts)
    cy.tabVisit(url, window_name)
    cy.switchToTab(tab_name)
    cy.closeTab(index_or_name) - pass nothing to close active tab
    cy.closeAllTabs() - except main root window
    

    【讨论】:

      【解决方案5】:

      我能够通过以下方式实现相同的要求:

      let newUrl = '';
      cy.window().then((win) => {
        cy.stub(win, 'open').as('windowOpen').callsFake(url => {
          newUrl = url;
        });
      })
      
      cy.get('.open-window-btn').click()
      cy.get('@windowOpen').should('be.called');
      cy.visit(newUrl)
      

      【讨论】:

        【解决方案6】:

        我最近也遇到了这个问题 - 新标签的网址是动态的,所以我不知道它是什么。经过大量搜索、一些试验和错误以及来自同事的输入,通过执行以下操作解决了:

        // AFTER cy.visit()
        cy.window().then((win) => {
          cy.spy(win, 'open').as('windowOpen'); // 'spy' vs 'stub' lets the new tab still open if you are visually watching it
        });
        // perform action here [for me it was a button being clicked that eventually ended in a window.open]
        // verify the window opened
        // verify the first parameter is a string (this is the dynamic url) and the second is _blank (opens a new window)
        cy.get('@windowOpen').should('be.calledWith', Cypress.sinon.match.string, '_blank');
        

        【讨论】:

        • 一旦我们可以访问打开的窗口,我们如何对其执行操作然后切换回旧窗口?我可以验证直到窗口打开。但我无法在这个打开的窗口上找到按钮。作品- cy.window().then((win) => { cy.spy(win, 'open').as('windowOpen'); }); cy.get('button').contains('登录你的账户').click() cy.get('@windowOpen').should('have.been.callWith', Cypress.sinon.match(' about:blank')) 这不起作用 - cy.get('@windowOpen').get('#buttonid1').click() 也不确定你如何移回旧窗口?
        • @namrata Cypress 不支持多个选项卡。这就是为什么我的代码只验证 window.open 被调用的原因。在他们的examples 中,他们提供了多种方法来处理新标签的情况。
        • @namrata 你必须关闭 cypress.json 中的 chromewebsecurity。默认情况下,它的值为 true,您可以在 cypress 仪表板上检查设置。例如,请从第 27 分钟开始观看此视频youtu.be/C2DjGl5a_-Y
        【解决方案7】:

        这就是您可以在同一窗口中处理选项卡的方式..

        使用这个代码sn-p

        cy.xpath("//a[@href='http://www.selenium.dev']").invoke('removeAttr','target').click();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-11-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多