Rails capybara访问不相关的页面导致测试失败

时间:2014-10-31 03:25:01

标签: javascript jquery ruby-on-rails ajax capybara

我有一个包含一些AJAX代码的页面,我正在尝试构建使用Capybara的规范。此测试有效:

context 'from the JobSpec#index page' do
  scenario 'clicks the Run now link' do
    visit job_specs_path
    within( find('tr', text: @job_spec.name) ) { click_link 'run_now' }
    visit current_path
    expect(find('tr', text: @job_spec.name)).to have_content(/(running|success)/)
  end
end

单击链接'run_now'后,将启动一个作业,并将用户重定向到launched_jobs_path,其中有一个Datatable,它使用一些AJAX来提取当前正在运行的作业。这个测试通过。但是,我想添加测试以检查以确保在单击“run_now”按钮之前作业尚未运行(这会给我一个误报)。我开始玩它,但后来我注意到,即使只是在visit launched_jobs_path之前放visit job_specs_path也会导致测试因错误而失败

Failure/Error: expect(find('tr', text: @job_spec.name)).to have_content(/(running|success)/)
 Capybara::ElementNotFound:
   Unable to find css "tr" with text "job_spec_collection-1"

我很确定这是Javascript没有在正确的时间运行的问题,但我不太清楚如何解决它。有任何想法吗?这是带有Capybara 2.4和Capybara-webkit 1.3的Rails 4.1。

谢谢!

更新

在规范的父上下文中,我确实有:js => true

feature 'User runs a JobSpec now', :js => true do
  before do
    Capybara.current_driver = :webkit
    @job_spec = FactoryGirl.create(:job_spec, :with_client_spaces)
  end

  after { Capybara.use_default_driver }

  context 'from the JobSpec#index page' do
    ...
  end
end

2 个答案:

答案 0 :(得分:0)

我认为它可能像添加一样简单:js =>对于您的方案标题是true,以便它知道启动webkit / selenium来测试js / ajax。

scenario 'clicks the Run now link', :js => true do

希望有所帮助!

<强>更新

这是另一个想法。您可以尝试将其添加到'rails_helper'或'spec_helper'文件中以设置:js驱动程序。

Capybara.javascript_driver = :webkit

你有其他:js测试正常使用:webkit?您是否尝试过使用save_and_open_page来查看您要查找的元素是否实际位于页面上而Capybara是否找不到它?

答案 1 :(得分:0)

好的,我很确定我现在有一些至少可以工作的东西。如果有人有更优雅的解决方案,我很乐意听到它们。

我认为问题在于&#39; run_now&#39;控制器。它为Rufus调度程序进程添加了一个作业,然后必须启动该作业(应该立即启动)。只有在通过Rufus运行启动的作业后,才会创建launch_jobs表中的条目。

在开发过程中,我会在点击“立即运行”后立即启动该作业。但是,我猜测WebKit是如此之快,以至于当它到达launch_jobs #index页面时,该作业还没有被启动。额外的visit current_path一开始似乎有帮助,因为它会刷新页面,但它只是偶尔起作用。在同步块中包含最后两个步骤似乎可靠地工作(我现在已经运行了大约20次而没有任何故障):

context 'from the JobSpec#index page' do
  scenario 'clicks the Run now link' do

    # First make sure that the job isn't already running
    visit launched_jobs_path
    expect(page).to have_no_selector('tr', text: @job_spec.name)

    # Now launch the job
    visit job_specs_path
    within( find('tr', text: @job_spec.name) ) { click_link 'run_now' }
    page.document.synchronize do
      visit current_path
      expect(find('tr', text: @job_spec.name)).to have_content(/(running|success)/)
    end

  end
end