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?

Amir Shabani
  • 3,857
  • 6
  • 30
  • 67
David Tuite
  • 22,258
  • 25
  • 106
  • 176
  • Just wondering what would happen if the book = FactoryGirl.create :book was in a before(:each) do...end block? – Neil Billingham Nov 07 '13 at 13:55
  • Did you set `config.use_transactional_fixtures = false`? – Steve Nov 07 '13 at 13:58
  • if you want to know how i handle it, you can read my two cents here: https://gist.github.com/phoet/6683280#file-readme-md – phoet Nov 07 '13 at 14:00
  • @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. – David Tuite Nov 07 '13 at 14:01
  • @Steve Yep. Sorry, should have mentioned that in the question. – David Tuite Nov 07 '13 at 14:02
  • 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? – Neil Billingham Nov 07 '13 at 14:18
  • @NeilBillingham Capybara 2.1.0 and Capybara Webkit 1.0.0 – David Tuite Nov 07 '13 at 14:29
  • Here's a simplified version of my spec_helper.rb (i.e. the basic RSpec.configure bit) it you wish to compare: https://gist.github.com/neilbilly/7356139 – Neil Billingham Nov 07 '13 at 15:12
  • Have you checked if the correct before(:each) is called? – Kristiina Nov 14 '13 at 12:36
  • 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. – faron Dec 03 '13 at 17:21

6 Answers6

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.

Adam Nowak
  • 127
  • 8
RubeOnRails
  • 1,153
  • 11
  • 22
  • doing this would would be one of the *causes* of the problem seen here, not the solution. – sevenseacat May 14 '14 at 04:40
  • 1
    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. – RubeOnRails May 14 '14 at 04:49
  • oh my apologies, I misinterpreted what you said. It read to me like you were telling him thats what he needed to set. – sevenseacat May 14 '14 at 04:51
  • Sorry for the ambiguity. Hopefully this helps clarify. I had this same issue, and doing this solved it for me. – RubeOnRails May 14 '14 at 04:51
  • 1
    I have `config.use_transactional_fixtures = true`, still same problem – RAJ Dec 11 '16 at 13:38
  • 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. – RubeOnRails Dec 12 '16 at 15:54
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.

Nick
  • 9,493
  • 8
  • 43
  • 66
  • 1
    This solved a very similar problem for me where I was missing database records in my AJAX calls from a feature spec. – dominik May 01 '17 at 12:27
  • This solved the following issue when running feature specs `ActiveRecord::ConnectionNotEstablished: No connection pool with 'primary' found.` – Jonas Porto Nov 12 '19 at 15:06
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

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
sumskyi
  • 1,827
  • 13
  • 13
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
jwadsack
  • 5,708
  • 2
  • 40
  • 50
1

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!

James
  • 608
  • 6
  • 11
-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.

EyasSH
  • 3,679
  • 22
  • 36