class Rack::Test::Session
This class represents a series of requests issued to a Rack
app, sharing a single cookie jar
Rack::Test::Session's methods are most often called through Rack::Test::Methods
, which will automatically build a session when it's first used.
Public Class Methods
Creates a Rack::Test::Session
for a given Rack
app or Rack::MockSession
.
Note: Generally, you won't need to initialize a Rack::Test::Session
directly. Instead, you should include Rack::Test::Methods
into your testing context. (See README.rdoc for an example)
# File lib/rack/test.rb, line 35 def initialize(mock_session) @headers = {} @env = {} @digest_username = nil @digest_password = nil @rack_mock_session = if mock_session.is_a?(MockSession) mock_session else MockSession.new(mock_session) end @default_host = @rack_mock_session.default_host end
Public Instance Methods
Issue a request using the given verb for the given URI. See get
Example:
custom_request "LINK", "/"
# File lib/rack/test.rb, line 126 def custom_request(verb, uri, params = {}, env = {}, &block) uri = parse_uri(uri, env) env = env_for(uri, env.merge(method: verb.to_s.upcase, params: params)) process_request(uri, env, &block) end
Issue a DELETE request for the given URI. See get
Example:
delete "/"
# File lib/rack/test.rb, line 89 def delete(uri, params = {}, env = {}, &block) custom_request('DELETE', uri, params, env, &block) 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'}
# File lib/rack/test.rb, line 153 def env(name, value) if value.nil? @env.delete(name) else @env[name] = value end end
Rack::Test
will not follow any redirects automatically. This method will follow the redirect returned (including setting the Referer header on the new request) in the last response. If the last response was not a redirect, an error will be raised.
# File lib/rack/test.rb, line 187 def follow_redirect! unless last_response.redirect? raise Error, 'Last response was not a redirect. Cannot follow_redirect!' end request_method, params = if last_response.status == 307 [last_request.request_method.downcase.to_sym, last_request.params] else [:get, {}] end # Compute the next location by appending the location header with the # last request, as per https://tools.ietf.org/html/rfc7231#section-7.1.2 # Adding two absolute locations returns the right-hand location next_location = URI.parse(last_request.url) + URI.parse(last_response['Location']) send( request_method, next_location.to_s, params, 'HTTP_REFERER' => last_request.url, 'rack.session' => last_request.session, 'rack.session.options' => last_request.session_options ) end
Issue a GET request for the given URI with the given params and Rack
environment. Stores the issues request object in last_request and the app's response in last_response. Yield last_response to a block if given.
Example:
get "/"
# File lib/rack/test.rb, line 57 def get(uri, params = {}, env = {}, &block) custom_request('GET', uri, params, env, &block) end
Issue a HEAD request for the given URI. See get
Example:
head "/"
# File lib/rack/test.rb, line 105 def head(uri, params = {}, env = {}, &block) custom_request('HEAD', uri, params, env, &block) end
Set a header to be included on all subsequent requests through the session. Use a value of nil to remove a previously configured header.
In accordance with the Rack
spec, headers will be included in the Rack
environment hash in HTTP_USER_AGENT form.
Example:
header "User-Agent", "Firefox"
# File lib/rack/test.rb, line 140 def header(name, value) if value.nil? @headers.delete(name) else @headers[name] = value end end
Issue an OPTIONS request for the given URI. See get
Example:
options "/"
# File lib/rack/test.rb, line 97 def options(uri, params = {}, env = {}, &block) custom_request('OPTIONS', uri, params, env, &block) end
Issue a PATCH request for the given URI. See get
Example:
patch "/"
# File lib/rack/test.rb, line 81 def patch(uri, params = {}, env = {}, &block) custom_request('PATCH', uri, params, env, &block) end
Issue a POST request for the given URI. See get
Example:
post "/signup", "name" => "Bryan"
# File lib/rack/test.rb, line 65 def post(uri, params = {}, env = {}, &block) custom_request('POST', uri, params, env, &block) end
Issue a PUT request for the given URI. See get
Example:
put "/"
# File lib/rack/test.rb, line 73 def put(uri, params = {}, env = {}, &block) custom_request('PUT', uri, params, env, &block) end
Issue a request to the Rack
app for the given URI and optional Rack
environment. Stores the issues request object in last_request and the app's response in last_response. Yield last_response to a block if given.
Example:
request "/"
# File lib/rack/test.rb, line 116 def request(uri, env = {}, &block) uri = parse_uri(uri, env) env = env_for(uri, env) process_request(uri, env, &block) end
Private Instance Methods
# File lib/rack/test.rb, line 305 def default_env { 'rack.test' => true, 'REMOTE_ADDR' => '127.0.0.1' }.merge(@env).merge(headers_for_env) end
# File lib/rack/test.rb, line 301 def digest_auth_configured? @digest_username end
# File lib/rack/test.rb, line 280 def digest_auth_header challenge = last_response['WWW-Authenticate'].split(' ', 2).last params = Rack::Auth::Digest::Params.parse(challenge) params.merge!('username' => @digest_username, 'nc' => '00000001', 'cnonce' => 'nonsensenonce', 'uri' => last_request.fullpath, 'method' => last_request.env['REQUEST_METHOD']) params['response'] = MockDigestRequest.new(params).response(@digest_password) "Digest #{params}" end
# File lib/rack/test.rb, line 221 def env_for(uri, env) env = default_env.merge(env) env['HTTP_HOST'] ||= [uri.host, (uri.port if uri.port != uri.default_port)].compact.join(':') env.update('HTTPS' => 'on') if URI::HTTPS === uri env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' if env[:xhr] # TODO: Remove this after Rack 1.1 has been released. # Stringifying and upcasing methods has be commit upstream env['REQUEST_METHOD'] ||= env[:method] ? env[:method].to_s.upcase : 'GET' params = env.delete(:params) do {} end if env['REQUEST_METHOD'] == 'GET' # merge :params with the query string if params params = parse_nested_query(params) if params.is_a?(String) uri.query = [uri.query, build_nested_query(params)].compact.reject { |v| v == '' }.join('&') end elsif !env.key?(:input) env['CONTENT_TYPE'] ||= 'application/x-www-form-urlencoded' if params.is_a?(Hash) if data = build_multipart(params) env[:input] = data env['CONTENT_LENGTH'] ||= data.length.to_s env['CONTENT_TYPE'] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}" else # NB: We do not need to set CONTENT_LENGTH here; # Rack::ContentLength will determine it automatically. env[:input] = params_to_string(params) end else env[:input] = params end end set_cookie(env.delete(:cookie), uri) if env.key?(:cookie) Rack::MockRequest.env_for(uri.to_s, env) end
# File lib/rack/test.rb, line 309 def headers_for_env converted_headers = {} @headers.each do |name, value| env_key = name.upcase.tr('-', '_') env_key = 'HTTP_' + env_key unless env_key == 'CONTENT_TYPE' converted_headers[env_key] = value end converted_headers end
# File lib/rack/test.rb, line 321 def params_to_string(params) case params when Hash then build_nested_query(params) when nil then '' else params end end
# File lib/rack/test.rb, line 213 def parse_uri(path, env) URI.parse(path).tap do |uri| uri.path = "/#{uri.path}" unless uri.path[0] == '/' uri.host ||= @default_host uri.scheme ||= 'https' if env['HTTPS'] == 'on' end end
# File lib/rack/test.rb, line 265 def process_request(uri, env) @rack_mock_session.request(uri, env) if retry_with_digest_auth?(env) auth_env = env.merge('HTTP_AUTHORIZATION' => digest_auth_header, 'rack-test.digest_auth_retry' => true) auth_env.delete('rack.request') process_request(uri.path, auth_env) else yield last_response if block_given? last_response end end
# File lib/rack/test.rb, line 295 def retry_with_digest_auth?(env) last_response.status == 401 && digest_auth_configured? && !env['rack-test.digest_auth_retry'] end