├── .gitignore ├── .travis.yml ├── Gemfile.rails4 ├── Gemfile.rails5 ├── Gemfile.rails6 ├── LICENSE ├── README.md ├── Rakefile ├── apps ├── test_rack_app.rb ├── test_rails_app.rb └── test_sinatra_app.rb ├── lib ├── rack_session_access.rb └── rack_session_access │ ├── capybara.rb │ ├── middleware.rb │ └── version.rb ├── rack_session_access.gemspec └── spec ├── middleware_spec.rb ├── rack_session_access_spec.rb └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | pkg/* 2 | *.gem 3 | .bundle 4 | Gemfile.lock 5 | Gemfile.*.lock 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | addons: 3 | chrome: stable 4 | language: ruby 5 | rvm: 6 | - 2.4.1 7 | gemfile: 8 | - Gemfile.rails4 9 | - Gemfile.rails5 10 | - Gemfile.rails6 11 | cache: bundler 12 | script: 13 | - "export DISPLAY=:99.0" 14 | - "sh -e /etc/init.d/xvfb start" 15 | - sleep 3 # give xvfb some time to start 16 | - bundle exec rspec 17 | -------------------------------------------------------------------------------- /Gemfile.rails4: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | gemspec 4 | 5 | gem 'rails', '4.2.10' 6 | gem 'sinatra', '1.4.8' 7 | -------------------------------------------------------------------------------- /Gemfile.rails5: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | gemspec 4 | 5 | gem 'rails', '5.2.3' 6 | gem 'sinatra', '2.0.1' 7 | -------------------------------------------------------------------------------- /Gemfile.rails6: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | gemspec 4 | 5 | gem 'rails', '6.0.0' 6 | gem 'sinatra', '2.0.7' 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Railsware (www.railsware.com) 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rack Session Access [![Build Status](https://travis-ci.org/railsware/rack_session_access.svg?branch=master)](https://travis-ci.org/railsware/rack_session_access) 2 | 3 | RackSessionAccess provides rack middleware for 'rack.session' environment management. 4 | 5 | ## Problem 6 | 7 | Acceptance testing assumes that you can't directly access an applications session. 8 | For example, if you use capybara with selenium webdriver you can't change some session values 9 | because your tests use the same browser that accesses the application(via the backend server). 10 | 11 | ## Solution 12 | 13 | But what if you still want to change session values? 14 | One possible solution is to inject into the application some code that will manage the session independently. 15 | If you use rack based framework this gem does it! 16 | 17 | ## Installation 18 | 19 | ```ruby 20 | gem install rack_session_access 21 | ``` 22 | 23 | ## Using with Rails 24 | 25 | Add to `Gemfile`: 26 | 27 | ```ruby 28 | gem 'rack_session_access' 29 | ``` 30 | 31 | Add RackSessionAccess middleware to rails middleware stack. 32 | Add the following in`config/environments/test.rb`: 33 | 34 | ```ruby 35 | [MyRailsApp]::Application.configure do |config| 36 | ... 37 | # Access to rack session 38 | config.middleware.use RackSessionAccess::Middleware 39 | ... 40 | end 41 | ``` 42 | 43 | *Note* Ensure you include rack_session_access middleware only for *test* environment 44 | otherwise you will have security issue. 45 | 46 | 47 | ## Using with Sinatra 48 | 49 | Add to your sinatra application: 50 | 51 | ```ruby 52 | class MySinatraApplication < Sinatra::Base 53 | enable :sessions 54 | use RackSessionAccess::Middleware if environment == :test 55 | ... 56 | end 57 | ``` 58 | 59 | If you use rspec you may prefer to inject middleware only for rspec tests: 60 | Put into `spec/spec_helper`: 61 | 62 | ```ruby 63 | MySinatraApplication.configure do |app| 64 | app.use RackSessionAccess::Middleware 65 | end 66 | ``` 67 | 68 | ## Using with Rack builder 69 | 70 | ```ruby 71 | Rack::Builder.new do 72 | ... 73 | use Rack::Session::Cookie 74 | use RackSessionAccess::Middleware 75 | use MyRackApplication 76 | end.to_app 77 | ``` 78 | 79 | ## Testing with Capybara 80 | 81 | Add to `spec/spec_helper.rb` 82 | 83 | ```ruby 84 | require "rack_session_access/capybara" 85 | ``` 86 | 87 | Use: 88 | 89 | * `page.set_rack_session` to set your desired session data 90 | * `page.get_rack_session` to obtain your application session data 91 | * `page.get_rack_session_key` to obtain certain key of your application session data 92 | 93 | Example: 94 | 95 | ```ruby 96 | require 'spec_helper' 97 | 98 | feature "My feature" do 99 | given!(:user) { create(:user, email: 'jack@daniels.com') } 100 | 101 | scenario "logged in user access profile page" do 102 | page.set_rack_session(user_id: user.id) 103 | visit "/profile" 104 | expect(page).to have_content("Hi, jack@daniels.com") 105 | end 106 | 107 | scenario "visit landing page" do 108 | visit "/landing?ref=123" 109 | expect(page.get_rack_session_key('ref')).to eq("123") 110 | end 111 | end 112 | ``` 113 | 114 | ### Authlogic integration 115 | 116 | ```ruby 117 | module FeatureHelpers 118 | def logged_as(user) 119 | page.set_rack_session('user_credentials' => user.persistence_token) 120 | end 121 | end 122 | ``` 123 | 124 | ### Devise integration 125 | 126 | ```ruby 127 | module FeatureHelpers 128 | def logged_as(user) 129 | # Devise v3.x.x 130 | page.set_rack_session('warden.user.user.key' => User.serialize_into_session(user).unshift('User')) 131 | 132 | # Devise v4.x.x 133 | page.set_rack_session('warden.user.user.key' => User.serialize_into_session(user)) 134 | end 135 | end 136 | ``` 137 | 138 | ## Authentication helper 139 | 140 | Put corresponding implementation of `logged_as` in `spec/support/feature_helpers.rb` and include module into rspec config: 141 | 142 | ```ruby 143 | RSpec.configure do |config| 144 | ... 145 | config.include FeatureHelpers, type: :feature 146 | ... 147 | end 148 | ``` 149 | Start your scenarios with already logged in user: 150 | 151 | ```ruby 152 | feature 'User dashboard', type: :feature do 153 | given(:user) { create(:user) } 154 | background do 155 | logged_as user 156 | end 157 | scenario 'User reviews a dashboard' do 158 | ... 159 | end 160 | end 161 | ``` 162 | 163 | ## Notes 164 | 165 | Thus we use marshalized data it's possible to set any ruby object into application session hash. 166 | 167 | Enjoy! 168 | 169 | ## Running rack_session_access tests 170 | 171 | 172 | Run to test against Rails4, Sinatra and Rack applications 173 | 174 | ```sh 175 | BUNDLE_GEMFILE=Gemfile.rails4 bundle install 176 | BUNDLE_GEMFILE=Gemfile.rails4 bundle exec rspec -fd spec/ 177 | ``` 178 | 179 | ```sh 180 | BUNDLE_GEMFILE=Gemfile.rails5 bundle install 181 | BUNDLE_GEMFILE=Gemfile.rails5 bundle exec rspec -fd spec/ 182 | ``` 183 | 184 | ## Author 185 | 186 | [Andriy Yanko](http://ayanko.github.com/) 187 | 188 | ## License 189 | 190 | * Copyright (c) 2015 Railsware [www.railsware.com](http://www.railsware.com) 191 | * [MIT](www.opensource.org/licenses/MIT) 192 | 193 | 194 | ## References 195 | 196 | * [capybara](https://github.com/jnicklas/capybara) 197 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | -------------------------------------------------------------------------------- /apps/test_rack_app.rb: -------------------------------------------------------------------------------- 1 | require 'rack' 2 | 3 | TestRackApp = Rack::Builder.new do 4 | use Rack::Session::Cookie 5 | use RackSessionAccess::Middleware 6 | run lambda { |env| [200, { 'Content-Type' => 'text/plain'}, [ "DUMMY"] ] } 7 | end.to_app 8 | -------------------------------------------------------------------------------- /apps/test_rails_app.rb: -------------------------------------------------------------------------------- 1 | require 'action_controller/railtie' 2 | 3 | module TestRailsApp 4 | class Application < Rails::Application 5 | config.hosts.clear if Rails::VERSION::MAJOR >= 6 6 | 7 | config.secret_token = '572c86f5ede338bd8aba8dae0fd3a326aabababc98d1e6ce34b9f5' 8 | 9 | config.secret_key_base = '6dfb795086781f017c63cadcd2653fac40967ac60f621e6299a0d6d811417156d81efcdf1d234c' 10 | 11 | routes.draw do 12 | get '/login' => 'test_rails_app/sessions#new' 13 | post '/login' => 'test_rails_app/sessions#create' 14 | get '/profile' => 'test_rails_app/profiles#show' 15 | end 16 | end 17 | 18 | class SessionsController < ActionController::Base 19 | def new 20 | render plain: 'Please log in' 21 | end 22 | 23 | def create 24 | session[:user_email] = params[:user_email] 25 | redirect_to '/profile' 26 | end 27 | end 28 | 29 | class ProfilesController < ActionController::Base 30 | def show 31 | if user_email = session[:user_email] 32 | render plain: "Welcome, #{user_email}!" 33 | else 34 | redirect_to '/login' 35 | end 36 | end 37 | end 38 | end 39 | 40 | Rails.logger = Logger.new('/dev/null') 41 | -------------------------------------------------------------------------------- /apps/test_sinatra_app.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra' 2 | 3 | class TestSinatraApp < Sinatra::Base 4 | enable :sessions 5 | 6 | get '/login' do 7 | body "Please log in" 8 | end 9 | 10 | post '/login' do 11 | session[:user_email] = params[:user_email] 12 | redirect to('/profile') 13 | end 14 | 15 | get '/profile' do 16 | if user_email = session[:user_email] 17 | body "Welcome, #{user_email}!" 18 | else 19 | redirect to('/login') 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/rack_session_access.rb: -------------------------------------------------------------------------------- 1 | module RackSessionAccess 2 | autoload :Middleware, 'rack_session_access/middleware' 3 | 4 | class << self 5 | # session resource path 6 | attr_accessor :path 7 | 8 | # session resource edit path 9 | attr_accessor :edit_path 10 | 11 | # encode session hash to string 12 | def encode(hash) 13 | [Marshal.dump(hash)].pack('m') 14 | end 15 | 16 | # decode string to session hash 17 | def decode(string) 18 | Marshal.load(string.unpack('m').first) 19 | end 20 | 21 | def configure 22 | yield self 23 | end 24 | end 25 | end 26 | 27 | RackSessionAccess.configure do |config| 28 | config.path = '/rack_session' 29 | config.edit_path = '/rack_session/edit' 30 | end 31 | -------------------------------------------------------------------------------- /lib/rack_session_access/capybara.rb: -------------------------------------------------------------------------------- 1 | module RackSessionAccess 2 | module Capybara 3 | def set_rack_session(hash) 4 | data = ::RackSessionAccess.encode(hash) 5 | 6 | visit ::RackSessionAccess.edit_path 7 | has_content?("Update rack session") 8 | fill_in "data", :with => data 9 | click_button "Update" 10 | has_content?("Rack session data") 11 | end 12 | 13 | def get_rack_session 14 | visit ::RackSessionAccess.path + '.raw' 15 | has_content?("Raw rack session data") 16 | raw_data = find(:xpath, '//body/pre').text 17 | ::RackSessionAccess.decode(raw_data) 18 | end 19 | 20 | def get_rack_session_key(key) 21 | get_rack_session.fetch(key) 22 | end 23 | end 24 | end 25 | 26 | require 'capybara/session' 27 | Capybara::Session.send :include, RackSessionAccess::Capybara 28 | -------------------------------------------------------------------------------- /lib/rack_session_access/middleware.rb: -------------------------------------------------------------------------------- 1 | require 'rack/request' 2 | require 'builder' 3 | 4 | module RackSessionAccess 5 | class Middleware 6 | # Initialize RackSessionAccess middleware 7 | # 8 | # @param app a rack application 9 | # @param options 10 | # 11 | # Options: 12 | # * :key - rack session key 13 | def initialize(app, options = {}) 14 | @app = app 15 | @key = options[:key] || 'rack.session' 16 | @routing = [ 17 | [ 'GET', RackSessionAccess.path, :show ], 18 | [ 'GET', RackSessionAccess.edit_path, :edit ], 19 | [ 'PUT', RackSessionAccess.path, :update ] 20 | ] 21 | end 22 | 23 | def call(env) 24 | return render(500) do |xml| 25 | xml.h2("#{@key} env is not initialized") 26 | end unless env[@key] 27 | 28 | request = ::Rack::Request.new(env) 29 | 30 | if action = dispatch_action(request) 31 | send(action, request) 32 | else 33 | @app.call(env) 34 | end 35 | end 36 | 37 | protected 38 | 39 | # List session data 40 | def show(request) 41 | # force load session because it can be lazy loaded 42 | request.env[@key].delete(:rack_session_access_force_load_session) 43 | 44 | # session hash object 45 | session_hash = request.env[@key].to_hash 46 | 47 | case File.extname(request.path) 48 | when ".raw" 49 | render do |xml| 50 | xml.h2 "Raw rack session data" 51 | xml.pre RackSessionAccess.encode(session_hash) 52 | end 53 | else 54 | render do |xml| 55 | xml.h2 "Rack session data" 56 | xml.ul do |ul| 57 | session_hash.each do |k,v| 58 | ul.li("#{k.inspect} : #{v.inspect}") 59 | end 60 | end 61 | xml.p do |p| 62 | p.a("Edit", :href => action_path(:edit)) 63 | end 64 | end 65 | end 66 | end 67 | 68 | # Render form for submit new session data 69 | def edit(request) 70 | render do |xml| 71 | xml.h2 "Update rack session" 72 | xml.p "Put marshalized and encoded with base64 ruby hash into the form" 73 | xml.form({ 74 | :action => action_path(:update), 75 | :method => 'post', 76 | :enctype => 'application/x-www-form-urlencoded' 77 | }) do |form| 78 | form.input(:type => 'hidden', :name =>'_method', :value => 'put') 79 | form.textarea(:cols => 40, :rows => 10, :name => 'data') {} 80 | form.p do |p| 81 | p.input(:type => 'submit', :value => "Update") 82 | end 83 | end 84 | end 85 | end 86 | 87 | # Update session data 88 | def update(request) 89 | begin 90 | data = request.params['data'] 91 | hash = RackSessionAccess.decode(data) 92 | hash.each { |k, v| request.env[@key][k] = v } 93 | rescue => e 94 | return render(400) do |xml| 95 | xml.h2("Bad data #{data.inspect}: #{e.message} ") 96 | end 97 | end 98 | 99 | redirect_to action_path(:show) 100 | end 101 | 102 | private 103 | 104 | # Dispatch action from request 105 | def dispatch_action(request) 106 | method = request_method(request) 107 | path = request.path.sub(/\.\w+$/, '') 108 | route = @routing.detect { |r| r[0] == method && r[1] == path } 109 | route[2] if route 110 | end 111 | 112 | # Return HTTP method, detect emulated method with _method param 113 | def request_method(request) 114 | return request.request_method if request.request_method != 'POST' 115 | return request.params['_method'].upcase if request.params['_method'] 116 | request.request_method 117 | end 118 | 119 | # @return path for given action name 120 | def action_path(action) 121 | @routing.detect { |r| r[2] == action }[1] 122 | end 123 | 124 | # @return redirect response to specified url 125 | def redirect_to(url) 126 | render(302, {"Location" => url}) do |xml| 127 | xml.a "You are being redirected", :href => url 128 | end 129 | end 130 | 131 | # @return html response 132 | def render(code = 200, headers = {}) 133 | headers["Content-Type"] ||= "text/html" 134 | 135 | builder = Builder::XmlMarkup.new(:indent => 2) 136 | 137 | builder.html do |xml| 138 | xml.body do |body| 139 | yield body 140 | end 141 | end 142 | 143 | [ code, headers, [builder.target!] ] 144 | end 145 | 146 | end 147 | end 148 | -------------------------------------------------------------------------------- /lib/rack_session_access/version.rb: -------------------------------------------------------------------------------- 1 | module RackSessionAccess 2 | VERSION = "0.2.0" 3 | end 4 | -------------------------------------------------------------------------------- /rack_session_access.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "rack_session_access/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "rack_session_access" 7 | s.version = RackSessionAccess::VERSION 8 | s.authors = ["Andriy Yanko"] 9 | s.email = ["andriy.yanko@gmail.com"] 10 | s.homepage = "https://github.com/railsware/rack_session_access" 11 | s.summary = %q{Rack middleware that provides access to rack.session environment} 12 | s.license = 'MIT' 13 | 14 | s.rubyforge_project = "rack_session_access" 15 | 16 | s.files = `git ls-files`.split("\n") 17 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 18 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 19 | s.require_paths = ["lib"] 20 | 21 | s.add_runtime_dependency "rack", ">=1.0.0" 22 | s.add_runtime_dependency "builder", ">=2.0.0" 23 | 24 | s.add_development_dependency 'rspec', '~>3.7.0' 25 | s.add_development_dependency 'capybara', '~>3.0.1' 26 | s.add_development_dependency 'chromedriver-helper' 27 | s.add_development_dependency 'selenium-webdriver', '~>3.11.0' 28 | s.add_development_dependency 'rails', '>=4.0.0' 29 | end 30 | -------------------------------------------------------------------------------- /spec/middleware_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | shared_examples "common scenarios" do 4 | scenario "changing session data" do 5 | visit RackSessionAccess.edit_path 6 | expect(page).to have_content("Update rack session") 7 | 8 | fill_in "data", with: RackSessionAccess.encode({'user_id' => 1}) 9 | click_button "Update" 10 | expect(page).to have_content("Rack session data") 11 | expect(page).to have_content('"user_id" : 1') 12 | expect(page.current_path).to eq(RackSessionAccess.path) 13 | end 14 | 15 | scenario "providing no session data" do 16 | visit RackSessionAccess.edit_path 17 | expect(page).to have_content("Update rack session") 18 | 19 | click_button "Update" 20 | expect(page).to have_content("Bad data") 21 | expect(page.current_path).to eq(RackSessionAccess.path) 22 | end 23 | 24 | scenario "providing bad data" do 25 | visit RackSessionAccess.edit_path 26 | expect(page).to have_content("Update rack session") 27 | 28 | fill_in "data", :with => "qwertyuiop" 29 | click_button "Update" 30 | expect(page).to have_content("Bad data") 31 | expect(page.current_path).to eq(RackSessionAccess.path) 32 | end 33 | 34 | scenario "modify session data with set_rack_session helper" do 35 | page.set_rack_session(data) 36 | 37 | visit(RackSessionAccess.path) 38 | expect(page).to have_content('"user_email" : "jack@daniels.com"') 39 | expect(page).to have_content('"user_profile" : {:age=>12}') 40 | expect(page).to have_content('"role_ids" : [1, 20, 30]') 41 | end 42 | 43 | scenario "accessing raw session data" do 44 | page.set_rack_session(data) 45 | 46 | visit(RackSessionAccess.path + '.raw') 47 | raw_data = find(:xpath, "//body/pre").text 48 | expect(raw_data).to be_present 49 | actual_data = RackSessionAccess.decode(raw_data) 50 | expect(actual_data).to be_kind_of(Hash) 51 | data.each do |key, value| 52 | expect(actual_data[key]).to eq(value) 53 | end 54 | end 55 | 56 | scenario "accessing raw session data using get_rack_session helper" do 57 | page.set_rack_session(data) 58 | 59 | actual_data = page.get_rack_session 60 | 61 | expect(actual_data).to be_kind_of(Hash) 62 | data.each do |key, value| 63 | expect(actual_data[key]).to eq(value) 64 | end 65 | end 66 | 67 | scenario "accessing raw session data using get_rack_session_key helper" do 68 | page.set_rack_session(data) 69 | 70 | expect(page.get_rack_session_key('role_ids')).to eq([1, 20, 30]) 71 | end 72 | end 73 | 74 | shared_examples "rack scenarios" do 75 | scenario "accessing application" do 76 | visit "/welcome" 77 | expect(page.text).to eq("DUMMY") 78 | end 79 | end 80 | 81 | shared_examples "sinatra scenarios" do 82 | scenario "test application itself" do 83 | visit "/login" 84 | expect(page).to have_content("Please log in") 85 | 86 | visit "/profile" 87 | expect(page).to have_content("Please log in") 88 | end 89 | 90 | scenario "accessing application" do 91 | visit "/profile" 92 | expect(page.text).to eq("Please log in") 93 | 94 | page.set_rack_session(user_email: "jack@daniels.com") 95 | 96 | visit "/profile" 97 | expect(page.text).to eq("Welcome, jack@daniels.com!") 98 | end 99 | end 100 | 101 | shared_examples "rails scenarios" do 102 | scenario "test application itself" do 103 | visit "/login" 104 | expect(page).to have_content("Please log in") 105 | 106 | visit "/profile" 107 | expect(page).to have_content("Please log in") 108 | end 109 | 110 | scenario "accessing application" do 111 | visit "/profile" 112 | expect(page.text).to eq("Please log in") 113 | 114 | page.set_rack_session(user_email: "jack@daniels.com") 115 | 116 | visit "/profile" 117 | expect(page.text).to eq("Welcome, jack@daniels.com!") 118 | end 119 | end 120 | 121 | feature "manage rack session", %q( 122 | As developer 123 | I want to have ability to modify rack session 124 | So I can write faster tests 125 | ) do 126 | 127 | let(:data) do 128 | { 129 | 'user_email' => 'jack@daniels.com', 130 | 'user_profile' => {age: 12}, 131 | 'role_ids' => [1, 20, 30] 132 | } 133 | end 134 | 135 | context ":rack_test driver", driver: :rack_test do 136 | context "rack application" do 137 | background { Capybara.app = TestRackApp } 138 | include_examples "common scenarios" 139 | #include_examples "rack scenarios" 140 | end 141 | 142 | context "sinatra application" do 143 | background { Capybara.app = TestSinatraApp } 144 | include_examples "common scenarios" 145 | include_examples "sinatra scenarios" 146 | end 147 | 148 | context "rails application" do 149 | background { Capybara.app = TestRailsApp::Application } 150 | include_examples "common scenarios" 151 | include_examples "rails scenarios" 152 | end 153 | end 154 | 155 | context ":selenium driver", driver: :selenium do 156 | context "rack application" do 157 | background { Capybara.app = TestRackApp } 158 | include_examples "common scenarios" 159 | include_examples "rack scenarios" 160 | end 161 | 162 | context "sinatra application" do 163 | background { Capybara.app = TestSinatraApp } 164 | include_examples "common scenarios" 165 | include_examples "sinatra scenarios" 166 | end 167 | 168 | context "rails application" do 169 | background { Capybara.app = TestRailsApp::Application } 170 | include_examples "common scenarios" 171 | include_examples "rails scenarios" 172 | end 173 | end 174 | 175 | end 176 | -------------------------------------------------------------------------------- /spec/rack_session_access_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe RackSessionAccess do 4 | subject { described_class } 5 | 6 | it 'should have configured default path' do 7 | expect(subject.path).to eq('/rack_session') 8 | end 9 | 10 | it 'should have configured default edit_path' do 11 | expect(subject.edit_path).to eq('/rack_session/edit') 12 | end 13 | 14 | describe '.encode' do 15 | it 'should encode ruby hash to string' do 16 | result = subject.encode( { 'a' => 'b' }) 17 | expect(result).to be_kind_of(String) 18 | end 19 | end 20 | 21 | describe '.decode' do 22 | it 'should decode marshalized and base64 encoded string' do 23 | # Array(Marshal.dump({ :user_id => 100 })).pack("m") 24 | # => "BAh7BjoMdXNlcl9pZGlp\n" 25 | expect(subject.decode("BAh7BjoMdXNlcl9pZGlp\n")).to eq(user_id: 100) 26 | end 27 | end 28 | 29 | it 'should encode and decode value' do 30 | source = { 'klass' => Class, :id => 100, '1' => 2 } 31 | data = subject.encode(source) 32 | result = subject.decode(data) 33 | expect(result).to eq(source) 34 | end 35 | 36 | it 'should encode and decode values with line brake characters' do 37 | source = { 'line' => "one\ntwo" } 38 | data = subject.encode(source) 39 | result = subject.decode(data) 40 | expect(result).to eq(source) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'capybara/rspec' 2 | 3 | require 'rack_session_access' 4 | require 'rack_session_access/capybara' 5 | 6 | Dir[File.expand_path('../../apps/*.rb', __FILE__)].each do |f| 7 | require f 8 | end 9 | 10 | Capybara.server = :webrick 11 | 12 | Capybara.register_driver :selenium do |app| 13 | Capybara::Selenium::Driver.new app, 14 | browser: ENV.fetch('SELENIUM_BROWSER', 'chrome').to_sym 15 | end 16 | 17 | TestSinatraApp.configure do |app| 18 | app.environment = :test 19 | app.use RackSessionAccess::Middleware 20 | end 21 | 22 | TestRailsApp::Application.configure do |app| 23 | app.middleware.use ActionDispatch::Session::CookieStore 24 | app.middleware.use RackSessionAccess::Middleware 25 | end 26 | --------------------------------------------------------------------------------