class Rack::Test::Session

Experimental RBS support (using type sampling data from the type_fusion project).

# sig/rack/test.rbs

class Rack::Test::Session
  def self.new: (Rack::Test::Session app, ?String default_host) -> Rack::Test::Session
end

which will automatically build a session when it’s first used.
Rack::Test::Session’s methods are most often called through Rack::Test::Methods,
and a default rack environment that is used for future requests.
It keeps track of the cookies for the session, and allows for setting headers
Rack::Test::Session handles a series of requests issued to a Rack app.

def self.new(app, default_host = DEFAULT_HOST) # :nodoc:

Experimental RBS support (using type sampling data from the type_fusion project).

def self.new: (Rack::Test::Session app, ?String default_host) -> Rack::Test::Session

This signature was generated using 1 sample from 1 application.

:nodoc:
def self.new(app, default_host = DEFAULT_HOST) # :nodoc:
  if app.is_a?(self)
    # Backwards compatibility for initializing with Rack::MockSession
    app
  else
    super
  end
end

def after_request(&block)

Run a block after the each request completes.
def after_request(&block)
  @after_request << block
end

def append_query_params(query_array, query_params)

Append a string version of the query params to the array of query params.
def append_query_params(query_array, query_params)
  query_params = parse_nested_query(query_params) if query_params.is_a?(String)
  query_array << build_nested_query(query_params)
end

def basic_authorize(username, password)

basic_authorize "bryan", "secret"
Example:

included in subsequent requests in the HTTP_AUTHORIZATION header.
Set the username and password for HTTP Basic authorization, to be
def basic_authorize(username, password)
  encoded_login = ["#{username}:#{password}"].pack('m0')
  header('Authorization', "Basic #{encoded_login}")
end

def clear_cookies

Replace the current cookie jar with an empty cookie jar.
def clear_cookies
  @cookie_jar = CookieJar.new([], @default_host)
end

def close_body(body)

def close_body(body)
  body.close if body.respond_to?(:close)
end

def close_body(body)

close() gets called automatically in newer Rack versions.
def close_body(body)
end

def custom_request(verb, uri, params = {}, env = {}, &block)

custom_request "LINK", "/"

params and rack environment. Example:
Issue a request using the given HTTP verb for the given URI, with optional
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

def env(name, value)

env "rack.session", {:csrf => 'token'}

value. Example:
requests through the session. Use a value of nil to remove a previously
Set an entry in the rack environment to be included on all subsequent
def env(name, value)
  if value.nil?
    @env.delete(name)
  else
    @env[name] = value
  end
end

def env_for(uri, env)

Update environment to use based on given URI.
def env_for(uri, env)
  env = DEFAULT_ENV.merge(@env).merge!(env)
  env['HTTP_HOST'] ||= [uri.host, (uri.port if uri.port != uri.default_port)].compact.join(':')
  env['HTTPS'] = 'on' if URI::HTTPS === uri
  env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' if env[:xhr]
  env['REQUEST_METHOD'] ||= env[:method] ? env[:method].to_s.upcase : 'GET'
  params = env.delete(:params)
  query_array = [uri.query]
  if env['REQUEST_METHOD'] == 'GET'
    # Treat params as query params
    if params
      append_query_params(query_array, params)
    end
  elsif !env.key?(:input)
    env['CONTENT_TYPE'] ||= 'application/x-www-form-urlencoded'
    params ||= {}
    multipart = env.has_key?(:multipart) ? env.delete(:multipart) : env['CONTENT_TYPE'].start_with?('multipart/')
    if params.is_a?(Hash)
      if !params.empty? && data = build_multipart(params, false, multipart)
        env[:input] = data
        env['CONTENT_LENGTH'] ||= data.length.to_s
        env['CONTENT_TYPE'] = "#{multipart_content_type(env)}; boundary=#{MULTIPART_BOUNDARY}"
      else
        env[:input] = build_nested_query(params)
      end
    else
      env[:input] = params
    end
  end
  if query_params = env.delete(:query_params)
    append_query_params(query_array, query_params)
  end
  query_array.compact!
  query_array.reject!(&:empty?)
  uri.query = query_array.join('&')
  set_cookie(env.delete(:cookie), uri) if env.key?(:cookie)
  Rack::MockRequest.env_for(uri.to_s, env)
end

def follow_redirect!

a redirect, an error will be raised.
on the new request) in the last response. If the last response was not
will follow the redirect returned (including setting the Referer header
Rack::Test will not follow any redirects automatically. This method
def follow_redirect!
  unless last_response.redirect?
    raise Error, 'Last response was not a redirect. Cannot follow_redirect!'
  end
  if last_response.status == 307
    request_method = last_request.request_method
    params = last_request.params
  else
    request_method = 'GET'
    params = {}
  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'])
  custom_request(
    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

def header(name, value)

header "user-agent", "Firefox"

environment hash in HTTP_USER_AGENT form. Example:
In accordance with the Rack spec, headers will be included in the Rack

session. Use a value of nil to remove a previously configured header.
Set a header to be included on all subsequent requests through the
def header(name, value)
  name = name.upcase
  name.tr!('-', '_')
  name = "HTTP_#{name}" unless name == 'CONTENT_TYPE' || name == 'CONTENT_LENGTH'
  env(name, value)
end

def initialize(app, default_host = DEFAULT_HOST)

If a block is given, #last_response is also yielded to the block.
response in #last_response. #last_response is also returned by the methods.
submitted in #last_request. The methods store a Rack::MockResponse based on the
The above methods as well as #request and #custom_request store the Rack::Request

get("/bar", {'foo'=>'baz'}, 'HTTP_ACCEPT'=>'*')
get("/bar", {}, 'CONTENT_TYPE'=>'foo')
# URI, parameters, and rack environment

post("/foo", 'bar'=>'baz') # POST /foo (bar=baz in request body)
get("/foo", 'bar'=>'baz') # GET /foo?bar=baz
# URI and parameters

get("/?foo=bar") # GET /?foo=bar
get("/") # GET /
# URI only:

Examples:
method, with the given URI and optional parameters and rack environment.
delete, options, and head. Each method submits a request with the given request
The following methods are defined via metaprogramming: get, post, put, patch,

(See README.rdoc for an example)
Instead, you should include Rack::Test::Methods into your testing context.
Note: Generally, you won't need to initialize a Rack::Test::Session directly.

Creates a Rack::Test::Session for a given Rack app or Rack::Test::BasicSession.
def initialize(app, default_host = DEFAULT_HOST)
  @env = {}
  @app = app
  @after_request = []
  @default_host = default_host
  @last_request = nil
  @last_response = nil
  clear_cookies
end

def last_request

requests have been sent yet.
Return the last request issued in the session. Raises an error if no
def last_request
  raise Error, 'No request yet. Request a page first.' unless @last_request
  @last_request
end

def last_response

no requests have been sent yet.
Return the last response received in the session. Raises an error if
def last_response
  raise Error, 'No response yet. Request a page first.' unless @last_response
  @last_response
end

def multipart_content_type(env)

Return the multipart content type to use based on the environment.
def multipart_content_type(env)
  requested_content_type = env['CONTENT_TYPE']
  if requested_content_type.start_with?('multipart/')
    requested_content_type
  else
    'multipart/form-data'
  end
end

def parse_uri(path, env)

Normalize URI based on given URI/path and environment.
def parse_uri(path, env)
  uri = URI.parse(path)
  uri.path = "/#{uri.path}" unless uri.path.start_with?('/')
  uri.host ||= @default_host
  uri.scheme ||= 'https' if env['HTTPS'] == 'on'
  uri
end

def process_request(uri, env)

the mock session. Returns and potentially yields the last response.
Submit the request with the given URI and rack environment to
def process_request(uri, env)
  env['HTTP_COOKIE'] ||= cookie_jar.for(uri)
  @last_request = Rack::Request.new(env)
  status, headers, body = @app.call(env).to_a
  @last_response = MockResponse.new(status, headers, body, env['rack.errors'].flush)
  close_body(body)
  cookie_jar.merge(last_response.headers['set-cookie'], uri)
  @after_request.each(&:call)
  @last_response.finish
  yield @last_response if block_given?
  @last_response
end

def request(uri, env = {}, &block)

request "/"

environment. Example:
Issue a request to the Rack app for the given URI and optional Rack
def request(uri, env = {}, &block)
  uri = parse_uri(uri, env)
  env = env_for(uri, env)
  process_request(uri, env, &block)
end

def restore_state

exiting the block.
cookie jar to the state they were prior to block execution upon
Yield to the block, and restore the last request, last response, and
def restore_state
  request = @last_request
  response = @last_response
  cookie_jar = @cookie_jar.dup
  after_request = @after_request.dup
  begin
    yield
  ensure
    @last_request = request
    @last_response = response
    @cookie_jar = cookie_jar
    @after_request = after_request
  end
end

def set_cookie(cookie, uri = nil)

Set a cookie in the current cookie jar.
def set_cookie(cookie, uri = nil)
  cookie_jar.merge(cookie, uri)
end