Reputation: 233
I have used RSpec in conjunction with Capybara and Capybara-webkit on many Rails projects and it usually works smoothly. For some reason I'm having problems configuring the js: true
feature specs to work this time around. They are not interacting with the database properly. I use factory_girl
and database_cleaner
to manage the test db content. I have DatabaseCleaner.strategy = :truncation
in database_cleaner.rb
for the js: true
tests but it still doesn't work. Oddly, when I put in ActiveRecord::Base.establish_connection
into databse_cleaner.rb
the tests work fine. Why??
Here is rails_helper.rb
:
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if
Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
ActiveRecord::Migration.maintain_test_schema!
Capybara::Webkit.configure(&:block_unknown_urls)
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = false
config.infer_spec_type_from_file_location!
# Filter lines from Rails gems in backtraces.
config.filter_rails_from_backtrace!
# arbitrary gems may also be filtered via:
# config.filter_gems_from_backtrace("gem name")
end
This is the important parts of spec_helper.rb
:
ENV['RAILS_ENV'] ||= 'test'
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup'
Bundler.require
require 'pry-byebug'
require 'capybara/rspec'
require 'capybara/webkit'
require 'database_cleaner'
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
# use `describe 'Feature', type: :feature, js: true` to use this driver
Capybara.javascript_driver = :webkit
# tests use regular (faster) driver if they don't require js
Capybara.default_driver = :rack_test
Capybara::Webkit.configure do |config|
config.allow_unknown_urls
end
RSpec.configure do |config|
config.after(:suite) do
FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"])
end
config.include Capybara::DSL
...
This is database_cleaner.rb
(located in spec/support
):
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
When I change this, the tests can interact with the db properly:
config.before(:each, js: true) do
ActiveRecord::Base.establish_connection
DatabaseCleaner.strategy = :truncation
end
Why? I shouldn't have to explicitly tell it to establish a db connection.
Upvotes: 0
Views: 1012
Reputation: 376
When you set js: true
, you're essentially just using Capybara which in essence is a Selenium-driven browser request. Any code running outside the test process (like this Selenium browser request) does not see the database fixture.
Preferable to what you're doing though, is to share the data state across the Selenium web server and test the code itself.
Somewhere in Rspec.config (possibly your database_cleaner.rb), you'll want to set
config.use_transactional_fixtures = false
"Everyday Rails Testing with Rspec" has a trick that was sometimes needed for certain test scenarios where you need to share the same DB connection before Rails 5. Although it can cause other issues as pointed out in comments below:
Make a spec/support/shared_db_connection.rb file and add this content:
class ActiveRecord::Base
mattr_accessor :shared_connection
@@shared_connection = nil
def self.connection
@@shared_connection || retrieve_connection
end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
Upvotes: 0
Reputation: 49870
Your question states that you're using :transaction for your js tests, but the code shows :truncation. Truncation is what you should be using for your js tests so I assume the question is a typo.
You should be using the recommended database_cleaner - https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example - which detects whether truncation is needed based on the driver being used rather than the 'js: true' metadata and also uses append_after
rather than just after
, which is very important for test stability.
I also don't see a require 'capybara/rails'
anywhere in your rails_helper or spec_helper
Upvotes: 1