简体   繁体   English

Capybara/Selenium/Chrome:仅在调用 save_screenshot 时测试通过

[英]Capybara/Selenium/Chrome: test passes only when calling save_screenshot

I'm in the process of migrating from Poltergeist to headless Chrome.我正在从 Poltergeist 迁移到无头 Chrome。

Gemfile:宝石文件:

group :test do
  # Capybara - Headless, JavaScript-executing browser for Selenium
  gem 'selenium-webdriver'  # Selenium webdriver (needed to use Chrome driver)
  gem 'webdrivers', '~> 4.0', require: false # Run Selenium tests more easily with automatic installation and updates for all supported webdrivers.
  gem 'capybara-screenshot' # Automatically save screen shots when a scenario fails
  ...
end

spec/support/capybara.rb:规格/支持/capybara.rb:

Capybara.javascript_driver = :selenium_chrome_headless

I have spec which tests whether focusing an element applies a CSS class to an element.我有测试聚焦元素是否将 CSS class 应用于元素的规范。

it 'shows the fullscreen toggler on focus', js: true do
  visit new_user_path
  page.execute_script("$('#user_about').focus()")
  expect(page).to have_css '.textarea-fullscreenizer-toggler'
end

With Poltergeist it passed.有了 Poltergeist,它就过去了。 With :selenium_chrome_headless it does not:使用:selenium_chrome_headless它不会:

expected to find visible css ".textarea-fullscreenizer-toggler" within #<Capybara::Node::Element tag="div" path="/HTML/BODY[1]/MAIN[1]/DIV[1]/DIV[1]/FORM[1]/FIELDSET[1]/DIV[1]/DIV[1]/DIV[5]"> but there were no matches. Also found "", which matched the selector but not all filters. 

With :selenium_chrome though, it passes.但是,使用:selenium_chrome ,它通过了。 So it seems that the headless and non-headless driver do different things!所以看起来headless和non-headless driver做不同的事情! This is pretty uncomfortable.这很不舒服。

Interestingly, when putting a save_screenshot after focusing the element, the spec passes with headless chrome, too!有趣的是,在聚焦元素后放置save_screenshot时,规范也会通过 headless chrome!

What can I do here?我可以在这里做什么? I'm on the right track?我在正确的轨道上? Should I try https://github.com/twalpole/apparition driver instead?我应该尝试https://github.com/twalpole/apparition驱动程序吗?

You can also try something like this for headless chrome in the helper capybara.rb file.您也可以在帮助程序 capybara.rb 文件中为无头 chrome 尝试类似的操作。

require "selenium/webdriver"

Capybara.register_driver :chrome do |app|
  Capybara::Selenium::Driver.new(app, browser: :chrome)
end

Capybara.register_driver :headless_chrome do |app|
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
    chromeOptions: { args: %w(headless disable-gpu) }
  )

  Capybara::Selenium::Driver.new app,
    browser: :chrome,
    desired_capabilities: capabilities
end

Capybara.javascript_driver = :headless_chrome

This worked for me.这对我有用。 Might work for you as well.也可能对你有用。

Seems like a timing issue to me.对我来说似乎是一个时间问题。 My guess would be that the jQuery call you use to trigger focus takes some time while the matcher is already executed.我的猜测是,当匹配器已经执行时,您用来触发焦点的 jQuery 调用需要一些时间。 However, since it finds an element, which is not yet visible though, it raises the error.但是,由于它找到了一个尚不可见的元素,因此会引发错误。 Inserting the screenshot may consume just enough time to have JavaScript evaluated your command.插入屏幕截图可能会花费足够的时间让 JavaScript 评估您的命令。

Have you tried to explicitly match for a visible element like expect(page).to have_selector('.textarea-fullscreenizer-toggler', visible: true) ?您是否尝试过明确匹配诸如expect(page).to have_selector('.textarea-fullscreenizer-toggler', visible: true)这样的可见元素? Also, the focus trigger could also be done like that: find('#user_about').trigger('focus') .此外,焦点触发器也可以这样完成: find('#user_about').trigger('focus') This may also resolve the issue since it returns after it triggered the event.这也可以解决问题,因为它在触发事件后返回。

The error you provided is obviously not being returned for the code as shown, since the code you've provided isn't scoping anything or checking for text.您提供的错误显然不会返回所示代码,因为您提供的代码没有确定任何范围或检查文本。 In the future it would be much better if the error matched the code.将来如果错误与代码匹配会更好。 That being said the answer below is a guess based on the info available.话虽如此,下面的答案是基于可用信息的猜测。

The issue is most likely that your JS execution is happening before the page has fully loaded and therefore the page is resetting focus.问题很可能是您的 JS 执行发生在页面完全加载之前,因此页面正在重置焦点。 This can happen because visit does not guarantee the page is fully loaded/stable when it returns.发生这种情况是因为visit不能保证页面在返回时完全加载/稳定。 To synchronize that you need an expectation before the execute_script call that checks for something on the page that would indicate the page is loaded/stable.要同步您需要在execute_script调用之前检查页面上表明页面已加载/稳定的内容的期望。

visit new_user_path expect(page).to have_css('input#first_input:focus') # wait until the initially focused element is loaded/displayed/focused page.execute_script("$('#user_about').focus()") visit new_user_path expect(page).to have_css('input#first_input:focus') # 等到最初聚焦的元素被加载/显示/聚焦 page.execute_script("$('#user_about').focus()")

Note that using execute_script is generally a bad idea in tests though since it's not doing what a user would - you'd be much better off having Capybara do whatever actions a user would perform to make the element you care about focused.请注意,在测试中使用execute_script通常是一个坏主意,因为它没有做用户会做的事情 - 你最好让 Capybara 做用户会执行的任何操作以使你关心的元素集中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM