Can't make sense of capybara behaviour

2019-03-03 07:58发布

问题:

I have this integration test for my Rails App:

require 'test_helper'

class StudyCapybaraTest < ActionDispatch::IntegrationTest
  def setup
    @user = users(:archer)
    @vocabs = @user.vocabs
    Capybara.register_driver :selenium_chrome do |app|
      Capybara::Selenium::Driver.new(app, :browser => :chrome)
    end
    Capybara.current_driver = :selenium_chrome
    #Capybara.default_wait_time = 5
    visit login_path
    fill_in "session_email",    with: @user.email
    fill_in "session_password", with: 'password'
    click_button "session_commit"
  end

  test "full study process" do
    assert_title "Home | Word Up"
    visit study_user_path(@user)
    ....
  end
end

Weirdly, when I remove the first line of the first test "full study process"

assert_title "Home | Word Up"

the test fails because the test user doesn't seem to be logged in. The same problem occurs when I move

visit study_user_path(@user)

into the setup function (as it was before).

But that doesn't change anything about the sequence and logic, right? The only thing I can think of, is that the assertion comes to early, and the app doesn't have time to execute the instructions needed to meet the assertions.

Is this a timing issue, and if so, how can I prevent them from happening in the future? Thx!

回答1:

First, your intuition on it being a timing issue is correct. click_button does just that - it clicks the button. It doesn't wait for a form to post, it doesn't wait for any ajax to occur, etc. So without the assert_title your test is clicking the button, and immediately changing the url in the browser. The changing the url in the browser would have the effect of canceling any form submission or behavior that was triggered by the click_button call. You need to wait after the click_button for something that changes on the page as a result of clicking the button, along the lines of

assert_text('You are now logged in')

Secondly, the setup method is run before each test so you really don't want to be registering the driver in there, since it only needs to be done once.