Capybara can't find database records during feature specs
Asked Answered
M

6

23

I have a JS feature spec I'm trying to run with Capybara Webkit. It doesn't seem to be able to find my database records however.

The spec in question looks like this

it "should allow pledging to a Hardback level", js: true do
  book = FactoryGirl.create :book
  visit book_path(book)
  click_link "pledge-btn"
end

Unfortunately, the request to book_path(book) 404s because the book cannot be found.

If I take the :js flag off, the test passes.

I have DatabaseCleaner set up to use :truncation for JS specs as is the recommended method.

# spec/support/database_cleaner.rb
RSpec.configure do |config|
  config.use_transactional_fixtures = false

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

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
    DatabaseMetadata.create!(:sanitized_at => DateTime.now) 
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end
end

I can puts the book in the test and it will be found.

it "should allow pledging to a Hardback level", js: true do
  book = FactoryGirl.create :book
  visit book_path(book)
  p Book.first
  # => .. the book instance
  click_link "pledge-btn"
end

I've also tried this shared connection method which doesn't seem to fix the problem either.

What else could be wrong?

Maugham answered 7/11, 2013 at 12:48 Comment(10)
Just wondering what would happen if the book = FactoryGirl.create :book was in a before(:each) do...end block?Matrix
Did you set config.use_transactional_fixtures = false?Behavior
if you want to know how i handle it, you can read my two cents here: gist.github.com/phoet/6683280#file-readme-mdSqueal
@NeilBillingham It actually is in a before(:each) block (I simplified a little to keep the question concise). I've tried it within and without and it makes no difference.Maugham
@Behavior Yep. Sorry, should have mentioned that in the question.Maugham
Very strange I just tried a very similar thing on my setup and it worked ok. I'm using capybara 2.0.2 and capybara-webkit 1.0.0 - how does that compare to you?Matrix
@NeilBillingham Capybara 2.1.0 and Capybara Webkit 1.0.0Maugham
Here's a simplified version of my spec_helper.rb (i.e. the basic RSpec.configure bit) it you wish to compare: gist.github.com/neilbilly/7356139Matrix
Have you checked if the correct before(:each) is called?Merlynmermaid
I assume that you've checked it, but anyway, are you sure that book does present in the db? You running puts Book.first not puts book, it can be or can be not equal. Can you attach test log? with insert sql, finder sql, transaction marks (like begin, comit). And what is the order of before blocks? If before(:each) runs later then before(:each, :js => true) it can be the reason, try outputting something in them.Typhus
F
9

You may have config.use_transactional_fixtures = true set in your spec_helper.rb. This would override what you have above.

You want to either remove this line from your spec_helper.rb or change it there to be false.

Friedcake answered 14/5, 2014 at 3:50 Comment(6)
doing this would would be one of the causes of the problem seen here, not the solution.Masseter
I'm saying that he may have it set to true in the spec helper as it is the rails default, and despite setting it to false in the above support file, the spec helper will trump it.Friedcake
oh my apologies, I misinterpreted what you said. It read to me like you were telling him thats what he needed to set.Masseter
Sorry for the ambiguity. Hopefully this helps clarify. I had this same issue, and doing this solved it for me.Friedcake
I have config.use_transactional_fixtures = true, still same problemElliotelliott
That is the cause of your problem. We are saying you want to either set that to false or remove that line from your spec helper.Friedcake
C
6

I ran into this same issue and had a very similar config. After looking through the DatabaseCleaner README, I found this small note:

It's also recommended to use append_after to ensure DatabaseCleaner.clean runs after the after-test cleanup capybara/rspec installs.

Source

That means changing your

config.after(:each) do
  DatabaseCleaner.clean
end

to

config.append_after(:each) do
  DatabaseCleaner.clean
end

Note the append_after instead of after. This fixed my problem.

Clarey answered 21/10, 2016 at 21:43 Comment(2)
This solved a very similar problem for me where I was missing database records in my AJAX calls from a feature spec.Lombardi
This solved the following issue when running feature specs ActiveRecord::ConnectionNotEstablished: No connection pool with 'primary' found.Educationist
R
5

Working on legacy project I have had such issue, it was caused by switching DatabaseCleaner strategy to :truncation like the following:

config.before(:suite) do
  DatabaseCleaner.strategy = :truncation
  DatabaseCleaner.clean

  Test::Seeder.seed!

  DatabaseCleaner.strategy = :transaction
end

so, removing DatabaseCleaner.strategy = :transaction helped in my case

Rabbit answered 9/9, 2014 at 14:15 Comment(0)
F
4

If you create records in a before(:all) block then they will be available.

before :all do
  @book = FactoryGirl.create :book
end

it "should allow pledging to a Hardback level", js: true do
  visit book_path(@book)
  click_link "pledge-btn"
end

Capybara runs the rails server in a separate process from the tests, so they each get their own connection to the database. Therefore, the server does not access to the records created in the transaction for the test.

Because they are not inside a transaction, make sure that you clean them up with DatabaseCleaner in your spec_helper.rb:

config.after(:all, :type => :feature) do
  DatabaseCleaner.clean
end
Figuration answered 11/7, 2017 at 22:34 Comment(0)
T
2

For anyone that lands here in 2019 and beyond, I was caught out by the following code which I copied verbatim from the DatabaseCleaner readme:

config.before(:each, type: :feature) do
  # :rack_test driver's Rack app under test shares database connection
  # with the specs, so continue to use transaction strategy for speed.
  driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test

  unless driver_shares_db_connection_with_specs
    # Driver is probably for an external browser with an app
    # under test that does *not* share a database connection with the
    # specs, so use truncation strategy.
    DatabaseCleaner.strategy = :truncation
  end
end

This is all well and good, but I am using Rails system specs, not RSpec features and therefore this code block was never being run.

Change config.before(:each, type: :feature) to config.before(:each, type: :system) if you're using system specs!

Temblor answered 3/8, 2019 at 9:1 Comment(0)
C
-2

I think your main issue is that your rails_helper.rb has the following line commented out:

Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } 

This means your database_cleaner.rb is never getting loaded.

Cermet answered 6/5, 2015 at 23:17 Comment(1)
What makes you think that @Mark Johnson ?Maugham

© 2022 - 2024 — McMap. All rights reserved.