Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capybara with :js => true causes test to fail

I'm new to Capybara and testing on Rails in general, so please forgive me if this is a simple answer.

I've got this test

it "should be able to edit an assignment" do
    visit dashboard_path
    select(@project.client + " - " + @project.name, :from => "assignment_project_id")
    select(@team_member.first_name + " " + @team_member.last_name, :from => "assignment_person_id")
    click_button "Create assignment"
    page.should have_content(@team_member.first_name)
end

it passes as is, but if I add :js => true it fails with

cannot select option, no option with text 'Test client - Test project' in select box 'assignment_project_id'

I'm using FactoryGirl to create the data, and as the test passes without JS, I know that part is working.

I've tried with the default JS driver, and with the :webkit driver (with capybara-webkit installed)

I guess I don't understand enough what turning on JS for Capybara is doing.

Why would the test fail with JS on?

like image 802
evanmcd Avatar asked Nov 18 '11 05:11

evanmcd


People also ask

What are capybara tests?

Capybara is an acceptance test framework for web applications. It's a common choice for end-to-end, acceptance, or integration testing in Rails applications. It allows developers to simulate a user on a web page and make assertions based on the content and environment of the page.

Does Capybara use Selenium?

Capybara supports Selenium 3.5+ (Webdriver). In order to use Selenium, you'll need to install the selenium-webdriver gem, and add it to your Gemfile if you're using bundler.

What is Rspec capybara?

Capybara is a web-based test automation software that simulates scenarios for user stories and automates web application testing for behavior-driven software development. It is written in the Ruby programming language.


3 Answers

I've read the Capybara readme at https://github.com/jnicklas/capybara and it solved my issue.

Transactional fixtures only work in the default Rack::Test driver, but not for other drivers like Selenium. Cucumber takes care of this automatically, but with Test::Unit or RSpec, you may have to use the database_cleaner gem. See this explanation (and code for solution 2 and solution 3) for details.

But basically its a threading issue that involves Capybara having its own thread when running the non-Rack driver, that makes the transactional fixtures feature to use a second connection in another context. So the driver thread is never in the same context of the running rspec.

Luckily this can be easily solve (at least it solved for me) doing a dynamic switching in th DatabaseCleaner strategy to use:

RSpec.configure do |config|
  config.use_transactional_fixtures = false

  config.before :each do
    if Capybara.current_driver == :rack_test
      DatabaseCleaner.strategy = :transaction
    else
      DatabaseCleaner.strategy = :truncation
    end
    DatabaseCleaner.start
  end

  config.after do
    DatabaseCleaner.clean
  end
end
like image 183
brutuscat Avatar answered Nov 07 '22 09:11

brutuscat


A variation of brutuscat's answer that fixed our feature specs (which all use Capybara):

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

config.before(:each) do
  # set the default
  DatabaseCleaner.strategy = :transaction
end

config.before(:each, type: :feature) do
  DatabaseCleaner.strategy = :truncation
end

config.before(:each) do
  DatabaseCleaner.start
end

config.append_after(:each) do
  DatabaseCleaner.clean
end
like image 39
Aidan Feldman Avatar answered Nov 07 '22 09:11

Aidan Feldman


There is another way to deal with this problem now described and discussed here: Why not use shared ActiveRecord connections for Rspec + Selenium?

like image 30
Lars Schirrmeister Avatar answered Nov 07 '22 11:11

Lars Schirrmeister