【问题标题】:With Capybara, how do I switch to the new window for links with "_blank" targets?使用 Capybara,如何切换到带有“_blank”目标的链接的新窗口?
【发布时间】:2011-11-28 13:10:02
【问题描述】:

也许这实际上不是我遇到的问题,但似乎当我“click_link”一个带有 target="_blank" 的链接时,会话将焦点保持在当前窗口上。

所以我要么希望能够切换到新窗口,要么忽略 _blank 属性 - 本质上,我只是希望它实际转到链接指示的页面,以便我可以确保它是正确的页面。

我使用 webkit 和 selenium 驱动程序。


到目前为止,我在下面提交了我的发现。非常感谢您提供更全面的答案。

此外,这仅适用于 selenium - webkit 驱动程序的等效项(或指出我自己可以在哪里发现它)将不胜感激。

【问题讨论】:

    标签: ruby-on-rails testing selenium webkit capybara


    【解决方案1】:

    Capybara >= 2.3 包含新的窗口管理 API。它可以像这样使用:

    new_window = window_opened_by { click_link 'Something' }
    within_window new_window do
      # code
    end
    

    【讨论】:

    • poltergeist 1.6 实现了这个 API,所以在写这篇文章时,这就是 poltergeist 的方式。
    【解决方案2】:

    此解决方案仅适用于 Selenium 驱动程序

    所有打开的窗口都是 Selenium 中的商店

    response.driver.browser.window_handles
    

    这似乎是一个数组。最后一项始终是最近打开的窗口,这意味着您可以执行以下操作来切换到它。

    在一个区块内:

    new_window=page.driver.browser.window_handles.last 
    page.within_window new_window do
      #code
    end
    

    只需重新关注当前会话:

    session.driver.browser.switch_to.window(page.driver.browser.window_handles.last)
    

    在水豚问题页面上引用:https://github.com/jnicklas/capybara/issues/173

    有关 Selenium 窗口切换功能的更多详细信息:http://qastuffs.blogspot.com/2010/10/testing-pop-up-windows-using-selenium.html

    【讨论】:

    • 这很好,但第二个例子有点误导。 sessionpage没有区别,所以session.driver.browserpage.driver.browser实际上指的是同一个东西。这让我在尝试将其适应不同的环境、通过不同的库访问 Capybara 并且不使用 DSL 时搞砸了。我必须阅读 Capybara DSL 代码才能确定要访问“页面”,我只需要访问会话。
    • @glyphgryph 男孩 我喜欢解决方案只需复制和粘贴即可,没有任何额外的浪费。
    • 这不仅适用于 Selenium:within_window(page.driver.window_handles.last) 对我有用 capybara-webkit
    • 如下所述,Capybara 有一个新的处理窗口的语法:github.com/jnicklas/capybara#working-with-windows
    • 此方法在 capybara DEPRECATION WARNING: Passing string argument to #within_window is deprecated.已弃用
    【解决方案3】:

    现在是 working 与 Poltergeist。尽管window_handles 仍未实现(您需要一个窗口名称,即通过 JavaScript 弹出窗口):

    within_window 'other_window' do
      current_url.should match /example.com/
    end
    

    编辑:根据下面的评论,Poltergeist 现在实现了window_handles,因为version 1.4.0

    【讨论】:

    • 我刚刚尝试了page.within_window page.driver.browser.window_handles.last do ... ,它似乎在 Poltergeist 中按预期工作。无需提供窗口名称。所以这个答案可能需要更新。
    • Capybara 2.3 弃用使用字符串调用 within_windowDEPRECATION WARNING: Passing string argument to #within_window is deprecated. Pass window object or lambda. Andrey Botalov 记录的方法修复了此弃用。
    【解决方案4】:

    Capybara 提供了一些方法来轻松查找和切换窗口:

    facebook_window = window_opened_by do
      click_button 'Like'
    end
    within_window facebook_window do
      find('#login_email').set('a@example.com')
      find('#login_password').set('qwerty')
      click_button 'Submit'
    end
    

    更多详情:Capybara documentation

    【讨论】:

      【解决方案5】:

      我知道这是旧帖子,但它在 capybara 2.4.4 中的价值

      within_window(switch_to_window(windows.last)) do 
          # in my case assert redirected url from a prior click action
          expect(current_url).to eq(redirect['url'])
      end
      

      【讨论】:

        【解决方案6】:

        目前似乎无法使用 capybara-webkit:https://github.com/thoughtbot/capybara-webkit/issues/271

        :-(

        同时https://github.com/thoughtbot/capybara-webkit/issues/129声称可以用within_window切换窗口。

        https://github.com/thoughtbot/capybara-webkit/issues/47 也建议 page.driver.browser.switch_to().window(page.driver.browser.window_handles.last) 有效。嗯,继续阅读代码。

        https://github.com/thoughtbot/capybara-webkit/blob/master/lib/capybara/webkit/browser.rb 的代码至少有一些参考表明适用于 webdriver / firefox 的 API 也适用于 webkit。

        【讨论】:

        • 查看我对已接受答案的评论:within_window(page.driver.window_handles.last) 与 capybara-webkit 一起为我工作。
        【解决方案7】:

        现在为 capybara-webkit http://github.com/thoughtbot/capybara-webkit/pull/314 实现了 inside_window,在这里你可以看到如何使用它 http://github.com/mhoran/capybara-webkit-demo

        【讨论】:

          【解决方案8】:

          截至 2014 年 5 月,以下代码适用于 capybara-webkit

           within_window(page.driver.browser.window_handles.last) do
             expect(current_url).to eq('http://www.example.com/')
           end
          

          【讨论】:

          【解决方案9】:

          要显式更改窗口,请使用 switch_to_window

            def terms_of_use
              terms_window = window_opened_by do
                click_link(@terms_link)
              end
              switch_to_window(terms_window)
            end
          

          该方法之后浏览器将在新页面中运行,而不是将所有内容都包装在 within_window 块中

          【讨论】:

            【解决方案10】:

            这在 capybara-webkit 中对我有用:

            within_window(windows.last) do
              # code here
            end
            

            (我正在使用 capybara 2.4.1 和 capybara-webkit 1.3.0)

            【讨论】:

              【解决方案11】:

              您也可以传递窗口的 nameurltitle (但现在它被分割了)

                let(:product) { create :product }
              
                it 'tests' do
                  visit products_path
                  click_link(product.id)
              
                  within_window(product_path(product)) do
                    expect(page).to have_content(product.title)
                  end
                end
              

              您也可以传递 labdaproc

              within_window(->{ page.title == 'Page title' }) do
                click_button 'Submit'
              end
              

              希望它能将方法的使用扩展到更清晰的理解

              【讨论】:

                【解决方案12】:

                我在 gmail 窗口中打开链接时遇到了这个问题:我修复了这个问题:

                Given /^(?:|I )click the "([^"]*)" link in email message$/ do |field|
                
                  # var alllinks = document.getElementsByTagName("a");
                  # for (alllinksi=0; alllinksi<alllinks.length; alllinksi++) {
                  #   alllinks[alllinksi].removeAttribute("target");
                  # }
                
                  page.execute_script('var alllinks = document.getElementsByTagName("a"); for (alllinksi=0; alllinksi<alllinks.length; alllinksi++) { alllinks[alllinksi].removeAttribute("target"); }')
                
                  within(:css, "div.msg") do
                    click_link link_text
                  end
                
                end
                

                【讨论】:

                • 顺便说一句,您可以使用 heredoc 语法代替 cmets:page.execute_script &lt;&lt;-JS var alllinks = document.getElementsByTagName("a"); for (alllinksi=0; alllinksi&lt;alllinks.length; alllinksi++) { alllinks[alllinksi].removeAttribute("target"); } JS 注释只允许内联代码,因此请确保“JS”前后有换行符,但您明白了。这样您就不必在两个地方管理代码,而且大多数编辑器都会突出显示它们。
                【解决方案13】:

                最好的办法是将 capybara 更新到最新版本 (2.4.1) 并使用 windows.last 因为page.driver.browser.window_handles 已被弃用。

                【讨论】:

                  【解决方案14】:

                  主要实现 (window_opened_by) 对我提出了错误:

                  *** Capybara::WindowError Exception: block passed to #window_opened_by opened 0 windows instead of 1
                  

                  所以,我通过这个解决方案解决它:

                  new_window = open_new_window
                  
                  within_window new_window do
                    visit(click_link 'Something')
                  end
                  
                  page.driver.browser.window_handles
                  # => ["CDwindow-F7EF6D3C12B68D6B6A3DFC69C2790718", "CDwindow-9A026DEC65C3C031AF7D2BA12F28ADC7"]
                  

                  【讨论】:

                    【解决方案15】:

                    我个人喜欢以下方法,因为无论是否启用 JS,它都能正常工作。

                    我的规格:

                      it "shows as expected" do
                        visit my_path
                    
                        # ...test my non-JS stuff in the current tab
                    
                        switch_to_new_tab
                    
                        # ...test my non-JS stuff in the new tab
                        
                        # ...keep switching to new tabs as much as necessary
                      end 
                    
                      # OR
                    
                      it "shows as expected", js: true do
                        visit my_path
                    
                        # ...test my non-JS stuff in the current tab
                        # ...also test my JS stuff in the current tab
                    
                        switch_to_new_tab
                    
                        # ...test my non-JS stuff in the new tab
                        # ...also test my JS stuff in the new tab
                    
                        # ...keep switching to new tabs as much as necessary
                      end 
                    
                    

                    测试助手:

                      def switch_to_new_tab
                        current_browser = page.driver.browser
                    
                        if js_enabled?
                          current_browser.switch_to.window(current_browser.window_handles.last)
                        else
                          visit current_browser.last_request.fullpath
                        end
                      end
                    
                      def js_enabled?
                        Capybara.current_driver == Capybara.javascript_driver
                      end
                    

                    【讨论】:

                      猜你喜欢
                      • 2017-11-25
                      • 1970-01-01
                      • 2011-08-24
                      • 2021-05-05
                      • 2017-07-25
                      • 2012-04-11
                      • 2013-06-22
                      • 1970-01-01
                      • 2015-01-16
                      相关资源
                      最近更新 更多