javascript Capybara 无法识别动态添加的 DOM 元素?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3876412/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 02:31:41  来源:igfitidea点击:

Capybara doesn't recognize dynamically added DOM elements?

javascriptruby-on-railsdomintegration-testingcapybara

提问by kelly.dunn

I seem to be having trouble testing the slick javascript things I do with jQuery when using Capybara and Selenium. The expected behavior is for a form to be dynamically generated when a user clicks on the link "add resource". Capybara will be able to click the link, but fails to recognize the new form elements (i.e. "resource[name]").

在使用 Capybara 和 Selenium 时,我似乎在测试我用 jQuery 做的流畅的 javascript 事情时遇到了麻烦。预期行为是当用户单击“添加资源”链接时动态生成表单。Capybara 将能够单击该链接,但无法识别新的表单元素(即“资源[名称]”)。

Is there a way to reload the DOM for Capybara, or is there some element of this gem that I just haven't learned of yet?

有没有办法为 Capybara 重新加载 DOM,或者这个 gem 中是否有一些我还没有了解的元素?

Thanks in advance!

提前致谢!

==Edit==

==编辑==

Currently trying my luck with selenium's:

目前正在尝试使用硒的运气:

wait_for_element 

method.

方法。

==Edit==

==编辑==

I keep getting an "undefined method 'wait_for_element` for nill class" when attempting to do the following:

尝试执行以下操作时,我不断收到“nill 类的未定义方法 'wait_for_element`”:

@selenium.wait_for_element

It appears that that specific method, or perhaps wait_forwith a huge selector accessing the DOM element I expect is the correct course of action, but now trying to get the selenium session is starting to be a huge headache.

看起来那个特定的方法,或者可能是wait_for一个巨大的选择器访问我期望的 DOM 元素是正确的行动方案,但现在尝试获取 selenium 会话开始变得非常头疼。

采纳答案by ebeland

I use the Webdriver based driver for Capybara in RSpec, which I configure and use like this and it will definitely handle JS and doesn't need a reload of the dom. The key is using a wait_until and a condition that will be true when your AJAX response has finished.

我在 RSpec 中使用基于 Webdriver 的 Capybara 驱动程序,我像这样配置和使用它,它肯定会处理 JS 并且不需要重新加载 dom。关键是使用 wait_until 和在 AJAX 响应完成时为真的条件。

before(:each) do
  select_driver(example)  
  logout
  login('databanks') 
end

 def select_driver(example)
   if example.metadata[:js]
    Capybara.current_driver = :selenium
  else
    Capybara.use_default_driver
  end
end

it "should let me delete a scenario", :js=>true do
    select("Mysite Search", :from=>'scenario_id')  
    wait_until{ page.has_content?('mysite_searchterms')}    
    click_on "delete"     
    wait_until{ !page.has_content?('mysite_searchterms')}   
    visit '/databanks'
    page.should_not have_content('Mysite Search')
  end

I also figured out a hack to slow down webdriver last night, like this, if you want to watch things in slo-mo:

昨晚我还想出了一个 hack 来减慢 webdriver 的速度,就像这样,如果你想在慢动作中看东西:

   #set a command delay
   require 'selenium-webdriver'

   module ::Selenium::WebDriver::Remote
     class Bridge
       def execute(*args)
         res = raw_execute(*args)['value']
         sleep 0.5
         res
       end
     end
   end  

As someone else mentioned, if you are getting a timeout waiting for the element, you could look at upping this:

正如其他人所提到的,如果您在等待元素时遇到超时,您可以查看以下内容:

Capybara.default_wait_time = 10

回答by thomasfedb

From the Capybara docs:

来自 Capybara 文档:

When working with asynchronous JavaScript, you might come across situations where you are attempting to interact with an element which is not yet present on the page. Capybara automatically deals with this by waiting for elements to appear on the page.

使用异步 JavaScript 时,您可能会遇到尝试与页面上尚不存在的元素进行交互的情况。Capybara 通过等待元素出现在页面上来自动处理这个问题。

You might have some luck increasing the wait time:

您可能会幸运地增加等待时间:

Capybara.default_wait_time = 10

If that doesn't help then I would encorage you to contact somebody from the project on GitHub, write to the mailing list or submit an issue report.

如果这没有帮助,那么我会鼓励您联系 GitHub 上项目的某个人,写信给邮件列表或提交问题报告。

回答by ASM

Even wait_until deleted from Capybara 2.0. Still that's useful and grab code from below:

甚至 wait_until 从 Capybara 2.0 中删除。这仍然很有用,并从下面获取代码:

 def wait_until(delay = 1)   
 seconds_waited = 0   
 while ! yield && seconds_waited < Capybara.default_wait_time     
    sleep delay     
    seconds_waited += 1   
  end   
  raise "Waited for #{Capybara.default_wait_time} seconds but condition did not become true" unless yield 
end