1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
# frozen_string_literal: true
require 'time'
require_relative 'response'
module Rack
# Rack::MockResponse provides useful helpers for testing your apps.
# Usually, you don't create the MockResponse on your own, but use
# MockRequest.
class MockResponse < Rack::Response
class Cookie
attr_reader :name, :value, :path, :domain, :expires, :secure
def initialize(args)
@name = args["name"]
@value = args["value"]
@path = args["path"]
@domain = args["domain"]
@expires = args["expires"]
@secure = args["secure"]
end
def method_missing(method_name, *args, &block)
@value.send(method_name, *args, &block)
end
# :nocov:
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
# :nocov:
def respond_to_missing?(method_name, include_all = false)
@value.respond_to?(method_name, include_all) || super
end
end
class << self
alias [] new
end
# Headers
attr_reader :original_headers, :cookies
# Errors
attr_accessor :errors
def initialize(status, headers, body, errors = nil)
@original_headers = headers
if errors
@errors = errors.string if errors.respond_to?(:string)
else
@errors = ""
end
super(body, status, headers)
@cookies = parse_cookies_from_header
buffered_body!
end
def =~(other)
body =~ other
end
def match(other)
body.match other
end
def body
return @buffered_body if defined?(@buffered_body)
# FIXME: apparently users of MockResponse expect the return value of
# MockResponse#body to be a string. However, the real response object
# returns the body as a list.
#
# See spec_showstatus.rb:
#
# should "not replace existing messages" do
# ...
# res.body.should == "foo!"
# end
buffer = @buffered_body = String.new
@body.each do |chunk|
buffer << chunk
end
return buffer
end
def empty?
[201, 204, 304].include? status
end
def cookie(name)
cookies.fetch(name, nil)
end
private
def parse_cookies_from_header
cookies = Hash.new
set_cookie_header = headers['set-cookie']
if set_cookie_header && !set_cookie_header.empty?
Array(set_cookie_header).each do |cookie|
cookie_name, cookie_filling = cookie.split('=', 2)
cookie_attributes = identify_cookie_attributes cookie_filling
parsed_cookie = Cookie.new(
'name' => cookie_name.strip,
'value' => cookie_attributes.fetch('value'),
'path' => cookie_attributes.fetch('path', nil),
'domain' => cookie_attributes.fetch('domain', nil),
'expires' => cookie_attributes.fetch('expires', nil),
'secure' => cookie_attributes.fetch('secure', false)
)
cookies.store(cookie_name, parsed_cookie)
end
end
cookies
end
def identify_cookie_attributes(cookie_filling)
cookie_bits = cookie_filling.split(';')
cookie_attributes = Hash.new
cookie_attributes.store('value', Array(cookie_bits[0].strip))
cookie_bits.drop(1).each do |bit|
if bit.include? '='
cookie_attribute, attribute_value = bit.split('=', 2)
cookie_attributes.store(cookie_attribute.strip.downcase, attribute_value.strip)
end
if bit.include? 'secure'
cookie_attributes.store('secure', true)
end
end
if cookie_attributes.key? 'max-age'
cookie_attributes.store('expires', Time.now + cookie_attributes['max-age'].to_i)
elsif cookie_attributes.key? 'expires'
cookie_attributes.store('expires', Time.httpdate(cookie_attributes['expires']))
end
cookie_attributes
end
end
end
|