Skip to content

Instantly share code, notes, and snippets.

@cohuman
Created April 22, 2010 23:32
Show Gist options
  • Save cohuman/375973 to your computer and use it in GitHub Desktop.
Save cohuman/375973 to your computer and use it in GitHub Desktop.
# A simple app that implements a naive session-based login, to demonstrate the problems with testing sessions in Sinatra.
require 'rubygems'
require 'sinatra/base'
class LoginApp < Sinatra::Base
enable :sessions
get '/' do
if session[:current_user]
"Hi, #{session[:current_user]}" +
"<form action='/logout' method='post'><input type='submit' value='log out'></form>"
else
"Please log in." +
"<form action='/login' method='post'><input name='username'><input type='submit' value='log in'></form>"
end
end
post '/login' do
session[:current_user] = params[:username]
redirect '/'
end
post '/logout' do
session[:current_user] = nil
redirect '/'
end
end
LoginApp.run! if __FILE__ == $0
require "app"
require "spec"
require "rack/test"
require 'cgi'
describe LoginApp do
include Rack::Test::Methods
def app
LoginApp
end
class SessionData
def initialize(cookies)
@cookies = cookies
@data = cookies['rack.session']
if @data
@data = @data.unpack("m*").first
@data = Marshal.load(@data)
else
@data = {}
end
end
def [](key)
@data[key]
end
def []=(key, value)
@data[key] = value
session_data = Marshal.dump(@data)
session_data = [session_data].pack("m*")
@cookies.merge("rack.session=#{Rack::Utils.escape(session_data)}", URI.parse("//example.org//"))
raise "session variable not set" unless @cookies['rack.session'] == session_data
end
end
def session
SessionData.new(rack_test_session.instance_variable_get(:@rack_mock_session).cookie_jar)
end
it "renders the login form" do
get "/"
last_response.body.should include("Please log in")
end
it "redirects afer a login" do
post "/login", :username => "brad"
last_response.should be_redirect
end
it "displays the logged in user after a login" do
post "/login", :username => "brad"
get "/"
last_response.body.should include("Hi, brad")
end
it "logs out" do
post "/login", :username => "brad"
post "/logout"
get "/"
last_response.body.should include("Please log in")
end
it "can fake a login" do
session[:current_user] = "chad"
get "/"
last_response.body.should include("Hi, chad")
end
it "can fake a logout" do
post "/login", :username => "brad"
session[:current_user] = nil
session[:current_user].should == nil
get "/"
last_response.body.should include("Please log in")
end
it "can fake a user switch" do
post "/login", :username => "brad"
session[:current_user] = "chad"
get "/"
last_response.body.should include("Hi, chad")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment