rspec-tapas is a set of small helpers and extensions we often use in Selleo when testing our ruby apps.
To install rspec-tapas just add following line to your Gemfiles :test group
gem 'rspec-tapas'then just bundle install and require it in rails_helper.rb
require 'rspec_tapas/all'StubEnv is an extension that allows you to quickly stub values that should be retrieved from ENV.
It is assumed here, that you will use fetch method to retrieve such value (so it yields an exception when given ENV is not defined what sounds like a reasonable default).
Example
it 'sends a notification after checkout' do
stub_env('CHECKOUT_TIME', '13:00')
#...
endTo include this extension only, call require rspec_tapas/stub_env
StubEnv is accessible in all types of specs
DateHelpers is a set of two methods that facilitate using ActiveSupport::Testing::TimeHelpers. Therefore you need to include ActiveSupport::Testing::TimeHelpers in your config if you want to use DateHelpers. It is as simple as
RSpec.configure do |config|
config.include ActiveSupport::Testing::TimeHelpers
endat_date runs contents of the block at given date, provided in a format acceptable by Date.new. It is basically a shortcut to travel_to(Date.new(*args)){}.
Example
context 'one day before deadline' do
it 'sends a reminder' do
#...
at_date(2018, 1, 12) do
SendPendingReminders.call
end
#...
end
endfreeze_time freezes the time and runs contents of the block at. It is basically a shortcut to travel_to(Time.current){}.
Example
it 'discards records created at the same time' do
#...
freeze_time do
user_1 = create(:user)
user_2 = create(:user)
end
#...
endTo include this extension only, call require rspec_tapas/date_helpers
DateHelpers are accessible in all types of specs
ViewPage is a small helper that allows testing views using capybara helpers, usually limited only to feature specs.
Example
RSpec.describe 'users/show.html.erb', type: :view do
it 'renders user name' do
user = create(:user, name: "Tony")
allow(view).to receive(:user) { user }
render
expect(page).to have_content("Tony")
end
endTo include this extension only, call require rspec_tapas/view_page
ViewPage is accessible only in view specs
InvokeTask is a small helper that facilitates calling rake tasks when testing them.
Example
RSpec.describe 'db:materialize', type: :rake do
it 'materializes db view by name' do
database = double(:database)
allow(Scenic).to receive(:database) { database }
allow(database).to receive(:refresh_materialized_view)
invoke_task('db:materialize', view_name: 'sample_view')
expect(database).to \
have_received(:refresh_materialized_view).with('sample_view')
end
endTo include this extension only, call require rspec_tapas/invoke_task
InvokeTask is accessible only in rake specs
GetMessagePart is a set of helpers to facilitate extraction of html/plain parts of emails sent. To extract plaintext part from email, use text_part(mail). To extract HTML part, use html_part(mail).
RSpec.describe ReportMailer, type: :mailer do
describe '#summary' do
it 'creates email containing orders summary' do
create_list(:order, 2)
mail = ReportMailer.summary
expect(mail.subject).to eq('Orders summary')
expect(html_part(mail)).to include_html(
<<~HTML
<h1>Orders summary</h1>
<strong>Total orders created:</strong> 2 <br />
HTML
)
expect(text_part(mail)).to include('Total orders created: 2')
end
end
endTo include this extension only, call require rspec_tapas/get_message_part
GetMessagePart is accessible only in mailer specs
JsonResponse is a simple helper that transforms JSON encoded response body to HashWithIndifferentAccess or an array of those. This is to facilitate using regular matchers to assert such response.
Example
it 'returns user names and emails' do
create(:user, name: 'Tony', email: '[email protected]')
create(:user, name: 'Bruce', email: '[email protected]')
get '/v1/users'
expect(json_response).to match(
data: [
{ name: 'Tony', email: '[email protected]' },
{ name: 'Bruce', email: '[email protected]' },
]
)
endTo include this extension only, call require rspec_tapas/json_response
JsonResponse is accessible only in request and controller specs
DownloadsHelpers is a set of two helpers oriented on facilitating testing downloads. First, we need to allow downloading file in given feature spec by calling allow_file_downloads(page). Then, to get downloaded file contents, we need to use downloaded_file_contents(file_name) helper.
To allow downloads with headless-chrome capybara driver, we need to configure it in specific way. See example below:
require 'selenium/webdriver'
Capybara.register_driver :headless_chrome do |app|
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-gpu')
options.add_argument('--disable-popup-blocking')
options.add_argument('--window-size=1920,1200')
options.add_preference(
:download,
directory_upgrade: true,
prompt_for_download: false,
default_directory: RspecExtensions::DownloadsHelpers::DOWNLOADS_PATH
)
options.add_preference(:browser, set_download_behavior: { behavior: 'allow' })
Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end
Capybara.javascript_driver = :headless_chromeThen, testing downloads is just a matter of few lines of code.
Example
allow_file_downloads(page)
click_on 'Download report'
expect(downloaded_file_contents('daily_report.csv')).to eq("Name, Total revenue\nBatman suits, 1000")To include this extension only, call require rspec_tapas/downloads_helpers
DownloadsHelpers are accessible only in feature specs
FeatureHelpers module contains a couple of methods useful in features specs.
display_logswill display browser logs in console. This is useful for debugging javascript errors in feature specs.ssis a shortcut forpage.save_and_open_screenshotreload_pageis a handy shortcut for reloading current page.
To include this extension only, call require rspec_tapas/feature_helpers
FeatureHelpers are accessible only in feature specs
BehaviorDSL module has two roles. First one is to add some syntactic sugar to feature specs, by introducing additional level of describing context, but without interrupting test. This way you can group actions and assertions in readable blocks.
Second role of BehaviorDSL is to add capability of asserting feature - controller integration. This way we can ensure, that given block of capybara interactions were using particular controller action.
Example
RSpec.describe 'Users management' do
scenario do
behavior 'Admin browses existing users', using: 'Admin::UsersController#index' do
create(:user, name: 'Luke Cage')
create(:unit, name: 'Jessica Jones')
visit '/admin/users'
expect(page).to have_row_content('Full name' => 'Luke Cage')
expect(page).to have_row_content('Full name' => 'Jessica Jones')
end
behavior 'Admin updates existing user' do
#...
end
end
endTo include this extension only, call require rspec_tapas/behavior_dsl
BehaviorDSL is accessible only in feature specs
have_table_row is a matcher dedicated to finding table rows by their values correlated with specific headers. As so, this is mostly useful in feature specs.
Examples
# Asserting headers by their names
expect(page).to have_table_row('First name' => 'Tony', 'Last name' => 'Stark', 'Rating' => 4.5)
# Asserting headers by their indices
expect(page).to have_table_row(1 => 'Tony', 2 => 'Stark', 3 => 4.5)
# Asserting headers by their indices - shorter version
expect(page).to have_table_row('Tony', 'Stark', 4.5)
# Composing matchers
expect(page).to have_table_row(have_content('ny'), 'Stark')To include this matcher use: config.include RSpecTapas::Matchers
Software development teams with an entrepreneurial sense of ownership at their core delivering great digital products and building culture people want to belong to. We are a community of engaged co-workers passionate about crafting impactful web solutions which transform the way our clients do business.
All names and logos for Selleo are trademark of Selleo Labs Sp. z o.o. (formerly Selleo Sp. z o.o. Sp.k.)
