lib/rack/mock.rb in rack-2.0.9.4 vs lib/rack/mock.rb in rack-2.1.0

- old
+ new

@@ -1,11 +1,14 @@ +# frozen_string_literal: true + require 'uri' require 'stringio' require 'rack' require 'rack/lint' require 'rack/utils' require 'rack/response' +require 'cgi/cookie' module Rack # Rack::MockRequest helps testing your Rack application without # actually using HTTP. # @@ -51,29 +54,29 @@ def initialize(app) @app = app end - def get(uri, opts={}) request(GET, uri, opts) end - def post(uri, opts={}) request(POST, uri, opts) end - def put(uri, opts={}) request(PUT, uri, opts) end - def patch(uri, opts={}) request(PATCH, uri, opts) end - def delete(uri, opts={}) request(DELETE, uri, opts) end - def head(uri, opts={}) request(HEAD, uri, opts) end - def options(uri, opts={}) request(OPTIONS, uri, opts) end + def get(uri, opts = {}) request(GET, uri, opts) end + def post(uri, opts = {}) request(POST, uri, opts) end + def put(uri, opts = {}) request(PUT, uri, opts) end + def patch(uri, opts = {}) request(PATCH, uri, opts) end + def delete(uri, opts = {}) request(DELETE, uri, opts) end + def head(uri, opts = {}) request(HEAD, uri, opts) end + def options(uri, opts = {}) request(OPTIONS, uri, opts) end - def request(method=GET, uri="", opts={}) - env = self.class.env_for(uri, opts.merge(:method => method)) + def request(method = GET, uri = "", opts = {}) + env = self.class.env_for(uri, opts.merge(method: method)) if opts[:lint] app = Rack::Lint.new(@app) else app = @app end errors = env[RACK_ERRORS] - status, headers, body = app.call(env) + status, headers, body = app.call(env) MockResponse.new(status, headers, body, errors) ensure body.close if body.respond_to?(:close) end @@ -83,11 +86,11 @@ @parser ||= URI::Parser.new @parser.parse(uri) end # Return the Rack environment used for a request to +uri+. - def self.env_for(uri="", opts={}) + def self.env_for(uri = "", opts = {}) uri = parse_uri_rfc2396(uri) uri.path = "/#{uri.path}" unless uri.path[0] == ?/ env = DEFAULT_ENV.dup @@ -137,11 +140,11 @@ end rack_input.set_encoding(Encoding::BINARY) env[RACK_INPUT] = rack_input - env["CONTENT_LENGTH"] ||= env[RACK_INPUT].length.to_s + env["CONTENT_LENGTH"] ||= env[RACK_INPUT].size.to_s if env[RACK_INPUT].respond_to?(:size) opts.each { |field, value| env[field] = value if String === field } @@ -153,20 +156,23 @@ # Usually, you don't create the MockResponse on your own, but use # MockRequest. class MockResponse < Rack::Response # Headers - attr_reader :original_headers + attr_reader :original_headers, :cookies # Errors attr_accessor :errors - def initialize(status, headers, body, errors=StringIO.new("")) + def initialize(status, headers, body, errors = StringIO.new("")) @original_headers = headers @errors = errors.string if errors.respond_to?(:string) + @cookies = parse_cookies_from_header super(body, status, headers) + + buffered_body! end def =~(other) body =~ other end @@ -184,13 +190,66 @@ # # should "not replace existing messages" do # ... # res.body.should == "foo!" # end - super.join + buffer = String.new + + super.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 + if original_headers.has_key? 'Set-Cookie' + set_cookie_header = original_headers.fetch('Set-Cookie') + set_cookie_header.split("\n").each do |cookie| + cookie_name, cookie_filling = cookie.split('=', 2) + cookie_attributes = identify_cookie_attributes cookie_filling + parsed_cookie = CGI::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', cookie_bits[0].strip) + cookie_bits.each do |bit| + if bit.include? '=' + cookie_attribute, attribute_value = bit.split('=') + cookie_attributes.store(cookie_attribute.strip, attribute_value.strip) + if cookie_attribute.include? 'max-age' + cookie_attributes.store('expires', Time.now + attribute_value.strip.to_i) + end + end + if bit.include? 'secure' + cookie_attributes.store('secure', true) + end + end + cookie_attributes + end + end end