RackSessionAccess provides rack middleware for 'rack.session' environment management.
Acceptance testing assumes that you can't directly access an applications session. For example, if you use capybara with selenium webdriver you can't change some session values because your tests use the same browser that accesses the application(via the backend server).
But what if you still want to change session values? One possible solution is to inject into the application some code that will manage the session independently. If you use rack based framework this gem does it!
gem install rack_session_access
Add to Gemfile
:
gem 'rack_session_access'
Add RackSessionAccess middleware to rails middleware stack.
Add the following inconfig/environments/test.rb
:
[MyRailsApp]::Application.configure do |config|
...
# Access to rack session
config.middleware.use RackSessionAccess::Middleware
...
end
Note Ensure you include rack_session_access middleware only for test environment otherwise you will have security issue.
Add to your sinatra application:
class MySinatraApplication < Sinatra::Base
enable :sessions
use RackSessionAccess::Middleware if environment == :test
...
end
If you use rspec you may prefer to inject middleware only for rspec tests:
Put into spec/spec_helper
:
MySinatraApplication.configure do |app|
app.use RackSessionAccess::Middleware
end
Rack::Builder.new do
...
use Rack::Session::Cookie
use RackSessionAccess::Middleware
use MyRackApplication
end.to_app
Add to spec/spec_helper.rb
require "rack_session_access/capybara"
Use:
page.set_rack_session
to set your desired session datapage.get_rack_session
to obtain your application session datapage.get_rack_session_key
to obtain certain key of your application session dataExample:
require 'spec_helper'
feature "My feature" do
given!(:user) { create(:user, email: 'jack@daniels.com') }
scenario "logged in user access profile page" do
page.set_rack_session(user_id: user.id)
visit "/profile"
expect(page).to have_content("Hi, jack@daniels.com")
end
scenario "visit landing page" do
visit "/landing?ref=123"
expect(page.get_rack_session_key('ref')).to eq("123")
end
end
module FeatureHelpers
def logged_as(user)
page.set_rack_session('user_credentials' => user.persistence_token)
end
end
module FeatureHelpers
def logged_as(user)
# Devise v3.x.x
page.set_rack_session('warden.user.user.key' => User.serialize_into_session(user).unshift('User'))
# Devise v4.x.x
page.set_rack_session('warden.user.user.key' => User.serialize_into_session(user))
end
end
Put corresponding implementation of logged_as
in spec/support/feature_helpers.rb
and include module into rspec config:
RSpec.configure do |config|
...
config.include FeatureHelpers, type: :feature
...
end
Start your scenarios with already logged in user:
feature 'User dashboard', type: :feature do
given(:user) { create(:user) }
background do
logged_as user
end
scenario 'User reviews a dashboard' do
...
end
end
Thus we use marshalized data it's possible to set any ruby object into application session hash.
Enjoy!
Run to test against Rails4, Sinatra and Rack applications
BUNDLE_GEMFILE=Gemfile.rails4 bundle install
BUNDLE_GEMFILE=Gemfile.rails4 bundle exec rspec -fd spec/
BUNDLE_GEMFILE=Gemfile.rails5 bundle install
BUNDLE_GEMFILE=Gemfile.rails5 bundle exec rspec -fd spec/