select command allows searching a HTML select field and selecting an option that matches the supplied value by name, id or label text. Additionally, the
match option allows the user to indicate the behaviour if more than one option is found. For example,
match: :first will select the first item out of multiple matches, while
match: :one will throw an error if more than one item is found.
I was recently dealing with a time zone select list based on
ActiveRecord::TimeZone. I was receiving an error when Capybara tried to select “Samoa” from the option list (“Samoa” due to test randomisation), since there were items named “American Samoa” and “Samoa”. I ended up having to select the option via its ‘value’ attribute instead:
time_zone = ActiveRecord::TimeZone.all.sample
RSpec by default issues a database transactional rollback that is executed after the completion of a block. When using Capybara with the
:js option (to enable testing with Selenium or Webkit), the transactional rollback offered by RSpec is unusable as the browser is loaded via a separate thread and has a separate database connection. Thus any uncommitted data cannot be read by the browser.
Most people suggest employing DatabaseCleaner using a truncation strategy to overcome this deficiency. The performance of cleaning via truncation vs transaction depends on the size of data – with smaller fixtures, transactions are preferable.
Instead of using one or the other, we can mix strategies to have the best of both worlds:
config.use_transactional_fixtures = false # Using DatabaseCleaner instead
DatabaseCleaner.strategy = :transaction # Default strategy
DatabaseCleaner.clean_with(:truncation) # Initially clean with truncation
config.before(:each, type: :request) do
# Swap to truncation as Selenium runs in separate thread with a different
# database connection
DatabaseCleaner.strategy = :truncation
config.after(:each, type: :request) do
# Reset so non-request specs can use transaction
DatabaseCleaner.strategy = :transaction
On my current test suite of around 461 tests with 73 request specs, this dropped the run time by just over a minute.