Skip to content

Commit

Permalink
- Added support for managing extra env settings you may want to use
Browse files Browse the repository at this point in the history
  through subsequent requests.
  - There's an env method that allows managing those in the same way
  that `header` works.
  - Added tests for that too.
- Added a csrf method to automatically add everything a csrf
  token/request needs to work so you can save tons of lines in testing
  csrf enabled controllers.
  • Loading branch information
Darío Javier Cravero committed Apr 13, 2013
1 parent a8a3d8f commit fd375e3
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 9 deletions.
25 changes: 23 additions & 2 deletions lib/rack/test.rb
Expand Up @@ -4,7 +4,8 @@
require "rack/test/cookie_jar"
require "rack/test/mock_digest_request"
require "rack/test/utils"
require "rack/test/methods"
load '/Users/daris/Documents/uxtemple/opensource/rack-test/lib/rack/test/methods.rb'
# require "rack/test/methods"
require "rack/test/uploaded_file"

module Rack
Expand Down Expand Up @@ -35,6 +36,7 @@ class Session
# (See README.rdoc for an example)
def initialize(mock_session)
@headers = {}
@env = {}

if mock_session.is_a?(MockSession)
@rack_mock_session = mock_session
Expand Down Expand Up @@ -139,6 +141,19 @@ def header(name, value)
end
end

# Set an env var to be included on all subsequent requests through the
# session. Use a value of nil to remove a previously configured env.
#
# Example:
# env "rack.session", {:csrf => 'token'}
def env(name, value)
if value.nil?
@env.delete(name)
else
@env[name] = value
end
end

# Set the username and password for HTTP Basic authorization, to be
# included in subsequent requests in the HTTP_AUTHORIZATION header.
#
Expand Down Expand Up @@ -173,6 +188,12 @@ def follow_redirect!
get(last_response["Location"], {}, { "HTTP_REFERER" => last_request.url })
end

# Set a CSRF token so you can easily test safe services
def csrf(enable=true)
header('X-CSRF-Token', enable ? 'token' : nil)
env('rack.session', enable ? {:csrf => 'token'} : nil)
end

private

def env_for(path, env)
Expand Down Expand Up @@ -271,7 +292,7 @@ def digest_auth_configured?
end

def default_env
{ "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(headers_for_env)
{ "rack.test" => true, "REMOTE_ADDR" => "127.0.0.1" }.merge(@env).merge(headers_for_env)
end

def headers_for_env
Expand Down
2 changes: 2 additions & 0 deletions lib/rack/test/methods.rb
Expand Up @@ -67,11 +67,13 @@ def _current_session_names # :nodoc:
:head,
:follow_redirect!,
:header,
:env,
:set_cookie,
:clear_cookies,
:authorize,
:basic_authorize,
:digest_authorize,
:csrf,
:last_response,
:last_request
]
Expand Down
92 changes: 85 additions & 7 deletions spec/rack/test_spec.rb
Expand Up @@ -237,10 +237,10 @@ def close

describe "#header" do
it "sets a header to be sent with requests" do
header "User-Agent", "Firefox"
header "User-Agent", "token"
request "/"

last_request.env["HTTP_USER_AGENT"].should == "Firefox"
last_request.env["HTTP_USER_AGENT"].should == "token"
end

it "sets a Content-Type to be sent with requests" do
Expand All @@ -258,37 +258,77 @@ def close
end

it "persists across multiple requests" do
header "User-Agent", "Firefox"
header "User-Agent", "token"
request "/"
request "/"

last_request.env["HTTP_USER_AGENT"].should == "Firefox"
last_request.env["HTTP_USER_AGENT"].should == "token"
end

it "overwrites previously set headers" do
header "User-Agent", "Firefox"
header "User-Agent", "token"
header "User-Agent", "Safari"
request "/"

last_request.env["HTTP_USER_AGENT"].should == "Safari"
end

it "can be used to clear a header" do
header "User-Agent", "Firefox"
header "User-Agent", "token"
header "User-Agent", nil
request "/"

last_request.env.should_not have_key("HTTP_USER_AGENT")
end

it "is overridden by headers sent during the request" do
header "User-Agent", "Firefox"
header "User-Agent", "token"
request "/", "HTTP_USER_AGENT" => "Safari"

last_request.env["HTTP_USER_AGENT"].should == "Safari"
end
end

describe "#env" do
it "sets the env to be sent with requests" do
env "rack.session", {:csrf => 'token'}
request "/"

last_request.env["rack.session"].should == {:csrf => 'token'}
end

it "persists across multiple requests" do
env "rack.session", {:csrf => 'token'}
request "/"
request "/"

last_request.env["rack.session"].should == {:csrf => 'token'}
end

it "overwrites previously set envs" do
env "rack.session", {:csrf => 'token'}
env "rack.session", {:some => :thing}
request "/"

last_request.env["rack.session"].should == {:some => :thing}
end

it "can be used to clear a env" do
env "rack.session", {:csrf => 'token'}
env "rack.session", nil
request "/"

last_request.env.should_not have_key("X_CSRF_TOKEN")
end

it "is overridden by envs sent during the request" do
env "rack.session", {:csrf => 'token'}
request "/", "rack.session" => {:some => :thing}

last_request.env["rack.session"].should == {:some => :thing}
end
end

describe "#authorize" do
it "sets the HTTP_AUTHORIZATION header" do
authorize "bryan", "secret"
Expand Down Expand Up @@ -338,6 +378,44 @@ def close
end
end

describe "#csrf" do
it "sets the HTTP_X_CSRF_TOKEN header" do
csrf
request "/"

last_request.env["HTTP_X_CSRF_TOKEN"].should == "token"
end

it "sets the rack.session to include CSRF token" do
csrf
request "/"

last_request.env["rack.session"].should == {:csrf => "token"}
end

it "includes the header & rack.session for subsequent requests" do
csrf
request "/"
request "/"

last_request.env["HTTP_X_CSRF_TOKEN"].should == "token"
last_request.env["rack.session"].should == {:csrf => "token"}
end

it "can be cleared out" do
csrf
request "/"
last_request.env["HTTP_X_CSRF_TOKEN"].should == "token"
last_request.env["rack.session"].should == {:csrf => "token"}

csrf(false)
request "/"

last_request.env.should_not have_key("HTTP_X_CSRF_TOKEN")
last_request.env.should_not have_key("rack.session")
end
end

describe "#last_request" do
it "returns the most recent request" do
request "/"
Expand Down

0 comments on commit fd375e3

Please sign in to comment.