Rspec Helpers: Testing Rack::Flash (Ruby)

Tue 14 Jul 2020
Reading time: (~ mins)

Rspec is one of the libraries that really shows off how fun ruby is. An elegant DSL for testing that is a joy to use. Unfortunately user sessions can be a pain to test so I'll show you how to easily make specs for flash messages in your Rack apps.

We have a simple Sinatra app with three routes. /flash redirects and sets a flash message, which is what we want to verify with our tests

# my_app.rb
require 'sinatra'
require 'rack-flash'
class MyApp < Sinatra::Base
  enable :sessions # need this for flash to work
  use Rack::Flash

  get '/' do
    "Hello World. <a href='/flash'>Test Rack::Flash</a>"
  end

  get '/flash' do
    flash[:success] = 'Flashed!' # set the flash message we want
    redirect '/flash/message'
  end

  get '/flash/message' do
    "Here is your flash message: #{flash[:success]}" # display flash
  end
end

Before writing the tests we setup a spec helper to load our testing tools and environment, which includes RSpec and Rack::Test:

# spec/spec_helper.rb
ENV['APP_ENV'] = 'test'

require_relative '../my_app.rb'
require 'rspec'
require 'rack/test'

module RSpecMixin
  include Rack::Test::Methods # loads in rack/test methods

  def app; described_class; end # tells rspec where our app is

  def flash # the secret sauce
    response
    last_request.env['x-rack.flash']
  end
end

RSpec.configure do |config|
  config.include RSpecMixin # include our settings into RSpec
end
# spec/my_app_spec.rb
require 'spec_helper'
describe MyApp do
  context '/' do
    let!(:response) { get '/' } # Rack::Test let us do this

    it "says hello" do
      expect(last_response.body).to include 'Hello World'
    end
  end

  context '/flash' do
    let(:response) { get '/flash' }

    it 'sets flash success' do
      expect(flash[:success]).to eq 'Flashed!' # TADA!
    end
  end

  context '/flash/success' do
    let(:response) { get '/flash/message' }

    it 'does not show flash when accessed directly' do
      expect(flash[:success]).to be_nil # further testing
    end
  end
end
And for completeness here is the Gemfile and config.ru for this little project:
# Gemfile
source 'https://rubygems.org'

gem 'sinatra'
gem 'rack-flash3'
group :test do
  gem 'rack-test'
  gem 'rspec'
end  

# config.ru
require_relative 'my_app.rb'
run MyApp

Hopefully this helps you with your testing. Seems like a lot of people were scratching their heads about it when I tried to google solutions.

Enjoy!


Questions? Free free to contact me anytime :)

Get Notified of Future Posts