52

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?

4
  • It could be because different type of selectors are used when JS is on. I ran into similar weird problems like this one before. Can you modify your test and make the option your are selecting simpler (without " - ") for example select(@project.name, :from => "assignment_project_id") just to test it and see what happens? Commented Nov 18, 2011 at 5:40
  • Thanks for the idea. Tried that, but unfortunately it didn't work. Now just get "no option with text 'Test project'" Commented Nov 19, 2011 at 2:19
  • For now, it seems that the workaround I'll use to is populate the test database with data and isolate each test to only require data from the database. Perhaps this is how it's supposed to be done from the start, but my impression was that you could insert a record using Capybara then act on data from that insertion as long as it was within the same "it" block. Commented Nov 19, 2011 at 15:01
  • 1
    I'm having this issue too. I'm using rspec and factory_girl and it's like that when using :js => true no records are being populated in db... Commented Jan 2, 2012 at 8:19

3 Answers 3

108

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 
Sign up to request clarification or add additional context in comments.

4 Comments

nailed it - thanks! also - I now understands why it works thanks to the mailing list explanation by jnicklas - thanks for pointer.
Perfect — thanks a ton! Confirmed that this works with capybara-webkit as well
You only have to set the strategy to truncation for feature specs, just like @Aidan's answer.
It should be noted that recent versions of Rails (5+) and even earlier versions with the help of EvilMartians' shared connection backport support transactional features and you should definitely look into it for major time savings. See test-prof.evilmartians.io/#/active_record_shared_connection
9

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 

Comments

7

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.