简体   繁体   中英

Rails/RSpec/Capybara - transactionless database cleaning works with Selenium but not Webkit

So I've setup my RSpec environment to use a truncation cleaning strategy for my RSpec Capybara tests but I still find that something is still wrapping my test in a transaction when I use Webkit as my Javascript driver.

I don't have this problem with Selenium, which has got me stumped.

Here's the relevant RSpec config with webkit:

Capybara.javascript_driver = :webkit

Capybara.register_driver :webkit do |app|
  Capybara::Webkit::Driver.new(app).tap do |driver|
    driver.allow_url "fonts.googleapis.com"
    driver.allow_url "dl.dropboxusercontent.com"
  end
end

config.before(:suite) do
  DatabaseCleaner.clean_with :truncation
  DatabaseCleaner.clean_with :transaction
end

config.after(:each) do
  ActionMailer::Base.deliveries.clear
end

config.around(:each, type: :feature, js: true) do |ex|
  DatabaseCleaner.strategy = :truncation
  DatabaseCleaner.start
  self.use_transactional_fixtures = false
  ex.run
  self.use_transactional_fixtures = true
  DatabaseCleaner.clean
end

And my feature test looks like this:

feature "profile", js: true do
  describe "a confirmed user with a valid profile" do
    before(:each) do
      @user = FactoryGirl.create :user
      signin(@user.email, @user.password)
    end

    scenario 'can edit name' do
      visit edit_user_profile_path

      fill_in :user_name, with: 'New name'
      click_button :Submit
      @user.reload

      expect(@user.name).to eq('New name')
      expect(current_path).to eq show_user_path
    end
  end
end

If I run this test with Webkit it fails, but with Selenium it passes.

I've experimented with some debugging. If I put a debugger statement in the #update action I see that it updates the database correctly. If I connect to the test database at that time I can see the new information in the database, which means that this update cannot be wrapped in a transaction. However, but in the debugger in the .spec @user still see the original name as generated by FFaker in factory_girl. This leads me to believe that the test is ran inside a transaction.

When I change my JavaScript driver to Selenium it all works fine.

Any ideas?

Wow. I found the problem almost immediately after posting the question. No transactions were involved.

It was a race issue between the backend and webkit/selenium front end. With Webkit the test was executing the @user.reload and the expect statements before the controller had a chance to update the database. With Selenium it was the other way around.

The trick is to make Capybara wait for the page reload. I changed my test to this:

scenario 'can edit name' do
  visit edit_user_profile_path

  fill_in :user_name, with: 'New name'
  click_button :Submit

  expect(current_path).to eq show_user_path
  @user.reload
  expect(@user.name).to eq('New name')
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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