phi*_*kry 5 capybara rspec-rails poltergeist ruby-on-rails-4
我使用带有恶作剧驱动程序的Capybara进行一些功能测试时遇到了奇怪的问题.测试应该在我的网上商店进行简单的结账.它们都在我当地的MacBook以及Ubuntu流浪盒上都很好.但是对于像Codeship,Wercker或Semaphore这样的CI服务,它们会出现同样的错误.
我的规格:
require 'rails_helper'
describe 'Checkout' do
let!(:product) { FactoryGirl.create(:product) }
it 'checks out via CreditCard', js: true do
visit products_path
expect(page.body).to have_link('Test Product 1')
click_link('Test Product 1')
#rest of spec ommitted
end
end
Run Code Online (Sandbox Code Playgroud)
我在CI上遇到的错误是:
2) Checkout checks out via CreditCard
Failure/Error: click_link('Test Product 1')
Capybara::ElementNotFound:
Unable to find link "Test Product 1"
Run Code Online (Sandbox Code Playgroud)
对我来说,这是非常奇怪的,因为第一个期望' 期望(page.body).to has_link('测试产品1')似乎通过但是它在下一步失败,它应该实际上点击它确保的链接出现在页面上?
然后我按如下方式重新配置了poltergeist驱动程序以收集更多调试信息.
rails_helper.rb的片段:
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, {js_errors: false,
#inspector: true,
phantomjs_logger: Rails.logger,
logger: nil,
phantomjs_options: ['--debug=no', '--load-images=no', '--ignore-ssl-errors=yes', '--ssl-protocol=TLSv1'],
debug: true
})
end
Capybara.server_port = 3003
Capybara.app_host = 'http://application-test.lvh.me:3003' # lvh.me always resolves to 127.0.0.1
Capybara.javascript_driver = :poltergeist
Capybara.current_driver = :poltergeist
Capybara.default_wait_time = 5
Run Code Online (Sandbox Code Playgroud)
现在我可以在CI控制台上看到测试成功访问了我的products_path,并且返回了预期的html页面(包括我应该点击的链接).我删除了其余的HTML响应,使其更具可读性:
{"name"=>"visit", "args"=>["http://application-test.lvh.me:3003/products"]}
{"response"=>{"status"=>"success"}}
{"name"=>"body", "args"=>[]}
{"response"=>"--- snip --- <div class=\"info\">\n<a class=\"name color-pomegranate\" href=\"/en/products/6\">\nTest Product 1\n</a>\n850,00 \n</div> --- snap ---"}
{"name"=>"find", "args"=>[:xpath, ".//a[./@href][(((./@id = 'Test Product 1' or normalize-space(string(.)) = 'Test Product 1') or ./@title = 'Test Product 1') or .//img[./@alt = 'Test Product 1'])]"]}
{"response"=>{"page_id"=>4, "ids"=>[0]}}
{"name"=>"visible", "args"=>[4, 0]}
{"response"=>false}
{"name"=>"find", "args"=>[:xpath, ".//a[./@href][(((./@id = 'Test Product 1' or contains(normalize-space(string(.)), 'Test Product 1')) or contains(./@title, 'Test Product 1')) or .//img[contains(./@alt, 'Test Product 1')])]"]}
{"response"=>{"page_id"=>4, "ids"=>[1]}}
{"name"=>"visible", "args"=>[4, 1]}
{"response"=>false}
Run Code Online (Sandbox Code Playgroud)
最后两个发现动作重复,直到Capybara达到超时,然后测试失败.我通过一些在线xpath验证器仔细检查了Capybara使用的xpath,但正如预期的那样,它与HTML链接相匹配.我还使用capybara-screenshot gem在失败时转储HTML正文,并且还存在相关链接.
那么为什么测试仍然失败?有没有我不知道的种族情况?为什么它在本地传递但没有CI服务?
这是我的宝石版本:
虽然我无法重现这个问题,但我记得以前遇到过这个问题。我相信你的台词:
expect(page.body).to have_link('Test Product 1')
Run Code Online (Sandbox Code Playgroud)
正在通过,因为链接实际上位于 html 页面的主体上,即使它可能由于 CSS 或 JS 行为而被隐藏。然而,该行:
click_link('Test Product 1')
Run Code Online (Sandbox Code Playgroud)
在点击链接之前一定要检查可见性。您应该检查您的spec_helper.rb配置以确保:
Capybara.ignore_hidden_elements = true
Run Code Online (Sandbox Code Playgroud)
存在,因此第一行不会通过。我想我还必须将我提到的第一行更改为:
# Change page.body to page, to look at the rendered page, not the literal one
expect(page).to have_link('Test Product 1')
Run Code Online (Sandbox Code Playgroud)
一旦执行此操作,第一行就会阻塞线程并等待,直到链接变得可见。然后其余的测试就会通过。
希望这能解决它。