Issue with Capybara request specs with JS - can't find the model - ruby-on-rails

I'm having an issue with JS request specs - basic visiting of a model edit page:
it "can edit a doc", :js => true do
doc = FactoryGirl.create(:doc) # tried with Doc.create as well
puts Doc.find(doc.id) # 1 <- so it's definitely in the DB!
visit edit_doc_path(doc)
end
Result: "ActiveRecord::RecordNotFound - Couldn't find doc with id=1"
The odd thing is it works with standard request spec. I tried both webkit and selenium drivers. My spec_helper looks like this (should be pretty standard):
RSpec.configure do |config|
config.use_transactional_fixtures = false
Capybara.javascript_driver = :webkit
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
config.before(:each, :type => :request) do
Capybara.reset_sessions!
end
end
Rails 3.1.4, no versioning for capybara, rspec, etc. test libraries.
Any input much appreciated! Thanks!

Seems like you have same problem as this:
Capybara with :js => true causes test to fail
Try setting DatabaseCleaner strategy to :truncation and see if it works
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end

Related

Resetting table IDs and re-creating the test DB with Rspec on Rails

I have various tests that create models using FactoryGirl in Rails
it "does something" do
user = create(:user)
...
expect(user.name).to eq("foo")
end
I noticed that each time I run the spec suite, it does not reset the table id's on the test schema (using Postgres). So after several executions the user might have an id of something like 2894.
I use Database Cleaner to clean my DB between subsequent runs - see below.
Is there a way to reset table ID's directly between rspec runs? A company I previously worked at did it with their app, but I'm not aware how.
If #1 is not an option, is it possible to drop and recreate the test DB between runs?
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:deletion)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, js: true) do
DatabaseCleaner.strategy = :deletion
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
I am also using DatabaseCleaner gem and don't experience the same issue you do (though I'm using mysql instead).
Not sure if this helps in your case but would be worth trying my configuration:
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
Rails.application.load_seed
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
end
config.after(:each) do
DatabaseCleaner.clean
end
end
My rails_helper.rb
require 'support/database_cleaner'
RSpec.configure do |config|
config.use_transactional_fixtures = false

Data persisting with RSpec-rails in a before(:each)

I have transactions set up in my rails_helper...
config.use_transactional_fixtures = true
My before each blocks look like this:
before(:each) do
allow(subject).to receive_messages(
:authenticate => true,
:authorize => true
)
#user_song = FactoryGirl.create(:user_song)
FactoryGirl.create(:user_playlist, user_id: #user_song.user_id,
album_id: #user_song.song.album_id)
allow_any_instance_of(ApplicationController).to receive_messages(
:current_user => #user_song.user
)
Tests fail with validation errors, but, if I insert a Model.destroy_all for each used model before FactoryGirl's creation, it works. I'm confused.
Why? The Rspec rails guide says that it should be rolled-back? Is it something with FactoryGirl?
config.use_transactional_fixtures = true
is for Rails builtin fixeture cleanup. It wound work with factory_girl. You should disable that and, install a db cleaner gem like this one: https://github.com/DatabaseCleaner/database_cleaner
Try to configure the database cleaner.
Add this to your Gemfile
gem 'database_cleaner'
then update your
spec/rails_helper.rb:
RSpec.configure do |config|
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
end
config.after(:each) do
DatabaseCleaner.clean
end
end
You need to install and setup database cleaner gem. Configured and installed properly, it will fix this problem you're having. There are many blog articles to help with the setup and install if the github read me docs seem confusing. Such as this article

Clear database after testing a rake task using RSpec

I'm trying to test my rake task using rspec and it runs fine, but the problem is that the records aren't being deleted afterwards.
I've put config.use_transactional_fixtures = true in the config file to no affect. In other tests it's was working fine.
Here's my code:
require 'rspec'
require 'spec_helper'
require 'rake'
describe 'my_app rake tasks' do
describe 'rake_task_1' do
before { MyApp::Application.load_tasks }
it 'should test it!' do
10.times { create(:record) }
Rake::Task["rake_task_1"].invoke
Record.count.should == 10
end
end
end
In my rake task I'm executing a query using ActiveRecord::Base.connection.execute.
I'm sure it has something with SQL transitions in RSepc....
any ideas?
Have you tried using database_cleaner gem?
You can check the great article by Avdi Grimm about how to configure it.
config.use_transactional_fixtures = false
In file spec/support/database_cleaner.rb:
RSpec.configure do |config|
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
end
config.after(:each) do
DatabaseCleaner.clean
end
end

Capybara can't find database records during feature specs

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?
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.
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.
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
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
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!
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.

Rails Rspec Capybara and DatabaseCleaner - using truncation only on feature tests

I saw this cool method for only using Database cleaners :truncation for capybara test using :js => true
In spec_helper.rb:
config.before(:each) do
DatabaseCleaner.strategy = if example.metadata[:js]
:truncation
else
:transaction
end
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
The problem is that any feature test done with capybara seems to need the cleaning strategy to be :truncation.
All the other specs, however, are fine with :transaction, which is significantly faster.
Is there a way of specifying strategy for only capybara feature tests? SOmething like:
DataCleaner.strategy( :truncation ) if :type => :feature
this should do it, let me know
config.after(:all, :type => :feature) do
DatabaseCleaner.clean_with :truncation
end

Resources