I've seen a lot of examples of how to set up Capybara, Database Cleaner, and Factorybot with Rspec, but none with the Minitest setup that comes out of the box with Rails.
I'm struggling with Capybara::ElementNotFound errors when I run my test suite as a whole, but all of the tests that fail pass when run in isolation.
So, this leads me to believe that I need to use database_cleaner, but I can't figure out a setup that gets the test suite passing. What should my test_helper.rb look like if I'd like to use Minitest, Capybara, Factorybot, and Database Cleaner?
Here's my current test_helper.rb:
ENV['RAILS_ENV'] ||= 'test'
Minitest::Reporters.use!
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'minitest/reporters'
require 'capybara/rails'
require 'capybara/minitest'
require 'database_cleaner'
DatabaseCleaner.strategy = :truncation
class ActiveSupport::TestCase
include FactoryBot::Syntax::Methods
end
class ActionDispatch::IntegrationTest
include Capybara::DSL
include Capybara::Minitest::Assertions # Make `assert_*` methods behave like Minitest assertions
Capybara.server = :puma
Capybara.server_port = 3001
Capybara.app_host = 'http://localhost:3001'
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, browser: :chrome)
end
Capybara.javascript_driver = :chrome
Capybara.configure do |config|
config.default_max_wait_time = 10 # seconds
config.default_driver = :selenium
end
def teardown
Capybara.reset_sessions!
Capybara.use_default_driver
DatabaseCleaner.clean
end
end
Gemfile:
group :test do
gem 'capybara'
gem 'webdrivers'
gem 'capybara-selenium'
gem 'capybara-email'
gem 'faker'
gem 'database_cleaner'
gem 'rails-controller-testing'
gem 'minitest'
gem 'minitest-reporters'
gem 'guard'
gem 'guard-minitest'
end
The I call DatabaseCleaner.start in the setup for any test using Factorybot like this:
require 'test_helper'
class AccountTenancyTest < ActionDispatch::IntegrationTest
setup do
DatabaseCleaner.start
@acme_widgets_owner = create(:acme_widgets_owner)
@generic_gadgets_owner = create(:generic_gadgets_owner)
end
test "Account owners can't access someone else's account" do
# test goes here
end
end
What am I doing wrong with this setup that is causing the Capybara::ElementNotFound: errors when I run rails test if the tests are passing in isolation?
Since you're running Rails >= 5.1 you don't need DatabaseCleaner (Rails 5.1+ shares the DB connection between the app and the tests and uses transactions to isolate each test from others). Remove all references to database cleaner. Then change your integration tests to System Tests which is what you should be writing for Capybara tests in Rails 5.1+. That will then automatically set up all the before and teardown blocks necessary for basic Capybara tests.
I'm guessing your email tests are failing because the url being put in the emails isn't including the port number the test is being run on. Switching to system tests may fix that, if not you can specify
Capybara.always_include_port = trueto ensure the port gets added into the URL from the email.