diff options
Diffstat (limited to 'actionpack/lib/action_controller/test_case.rb')
-rw-r--r-- | actionpack/lib/action_controller/test_case.rb | 147 |
1 files changed, 90 insertions, 57 deletions
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index f922e134f7..b43bb9dc17 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -1,4 +1,5 @@ require 'rack/session/abstract/id' +require 'active_support/core_ext/hash/conversions' require 'active_support/core_ext/object/to_query' require 'active_support/core_ext/module/anonymous' require 'active_support/core_ext/hash/keys' @@ -6,6 +7,13 @@ require 'action_controller/template_assertions' require 'rails-dom-testing' module ActionController + # :stopdoc: + class Metal + include Testing::Functional + end + + # ActionController::TestCase will be deprecated and moved to a gem in Rails 5.1. + # Please use ActionDispatch::IntegrationTest going forward. class TestRequest < ActionDispatch::TestRequest #:nodoc: DEFAULT_ENV = ActionDispatch::TestRequest::DEFAULT_ENV.dup DEFAULT_ENV.delete 'PATH_INFO' @@ -32,24 +40,25 @@ module ActionController self.session = session self.session_options = TestSession::DEFAULT_OPTIONS + @custom_param_parsers = { + Mime[:xml] => lambda { |raw_post| Hash.from_xml(raw_post)['hash'] } + } end def query_string=(string) - @env[Rack::QUERY_STRING] = string + set_header Rack::QUERY_STRING, string end - def request_parameters=(params) - @env["action_dispatch.request.request_parameters"] = params + def content_type=(type) + set_header 'CONTENT_TYPE', type end - def assign_parameters(routes, controller_path, action, parameters = {}) - parameters = parameters.symbolize_keys - generated_path, extra_keys = routes.generate_extras(parameters.merge(:controller => controller_path, :action => action)) + def assign_parameters(routes, controller_path, action, parameters, generated_path, query_string_keys) non_path_parameters = {} path_parameters = {} parameters.each do |key, value| - if extra_keys.include?(key) || key == :action || key == :controller + if query_string_keys.include?(key) non_path_parameters[key] = value else if value.is_a?(Array) @@ -68,36 +77,35 @@ module ActionController end else if ENCODER.should_multipart?(non_path_parameters) - @env['CONTENT_TYPE'] = ENCODER.content_type + self.content_type = ENCODER.content_type data = ENCODER.build_multipart non_path_parameters else - @env['CONTENT_TYPE'] ||= 'application/x-www-form-urlencoded' - - # FIXME: setting `request_parametes` is normally handled by the - # params parser middleware, and we should remove this roundtripping - # when we switch to caling `call` on the controller + fetch_header('CONTENT_TYPE') do |k| + set_header k, 'application/x-www-form-urlencoded' + end - case content_mime_type.ref + case content_mime_type.to_sym + when nil + raise "Unknown Content-Type: #{content_type}" when :json data = ActiveSupport::JSON.encode(non_path_parameters) - params = ActiveSupport::JSON.decode(data).with_indifferent_access - self.request_parameters = params when :xml data = non_path_parameters.to_xml - params = Hash.from_xml(data)['hash'] - self.request_parameters = params when :url_encoded_form data = non_path_parameters.to_query else - raise "Unknown Content-Type: #{content_type}" + @custom_param_parsers[content_mime_type] = ->(_) { non_path_parameters } + data = non_path_parameters.to_query end end - @env['CONTENT_LENGTH'] = data.length.to_s - @env['rack.input'] = StringIO.new(data) + set_header 'CONTENT_LENGTH', data.length.to_s + set_header 'rack.input', StringIO.new(data) end - @env["PATH_INFO"] ||= generated_path + fetch_header("PATH_INFO") do |k| + set_header k, generated_path + end path_parameters[:controller] = controller_path path_parameters[:action] = action @@ -130,6 +138,12 @@ module ActionController "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}" end end.new + + private + + def params_parsers + super.merge @custom_param_parsers + end end class LiveTestResponse < Live::Response @@ -146,7 +160,7 @@ module ActionController # Methods #destroy and #load! are overridden to avoid calling methods on the # @store object, which does not exist for the TestSession class. class TestSession < Rack::Session::Abstract::SessionHash #:nodoc: - DEFAULT_OPTIONS = Rack::Session::Abstract::ID::DEFAULT_OPTIONS + DEFAULT_OPTIONS = Rack::Session::Abstract::Persisted::DEFAULT_OPTIONS def initialize(session = {}) super(nil, nil) @@ -171,6 +185,10 @@ module ActionController clear end + def fetch(key, *args, &block) + @data.fetch(key.to_s, *args, &block) + end + private def load! @@ -199,11 +217,11 @@ module ActionController # # Simulate a POST response with the given HTTP parameters. # post(:create, params: { book: { title: "Love Hina" }}) # - # # Assert that the controller tried to redirect us to + # # Asserts that the controller tried to redirect us to # # the created book's URI. # assert_response :found # - # # Assert that the controller really put the book in the database. + # # Asserts that the controller really put the book in the database. # assert_not_nil Book.find_by(title: "Love Hina") # end # end @@ -391,7 +409,7 @@ module ActionController MSG @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' - @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ') + @request.env['HTTP_ACCEPT'] ||= [Mime[:js], Mime[:html], Mime[:xml], 'text/xml', '*/*'].join(', ') __send__(*args).tap do @request.env.delete 'HTTP_X_REQUESTED_WITH' @request.env.delete 'HTTP_ACCEPT' @@ -441,16 +459,16 @@ module ActionController parameters = nil end - if parameters.present? || session.present? || flash.present? + if parameters || session || flash non_kwarg_request_warning end end - if body.present? - @request.env['RAW_POST_DATA'] = body + if body + @request.set_header 'RAW_POST_DATA', body end - if http_method.present? + if http_method http_method = http_method.to_s.upcase else http_method = "GET" @@ -458,55 +476,57 @@ module ActionController parameters ||= {} - if format.present? + if format parameters[:format] = format end @html_document = nil - unless @controller.respond_to?(:recycle!) - @controller.extend(Testing::Functional) - end - self.cookies.update @request.cookies - @request.env['HTTP_COOKIE'] = cookies.to_header - @request.env['action_dispatch.cookies'] = nil + self.cookies.update_cookies_from_jar + @request.set_header 'HTTP_COOKIE', cookies.to_header + @request.delete_header 'action_dispatch.cookies' @request = TestRequest.new scrub_env!(@request.env), @request.session @response = build_response @response_klass @response.request = @request @controller.recycle! - @request.env['REQUEST_METHOD'] = http_method + @request.set_header 'REQUEST_METHOD', http_method - controller_class_name = @controller.class.anonymous? ? - "anonymous" : - @controller.class.controller_path + parameters = parameters.symbolize_keys - @request.assign_parameters(@routes, controller_class_name, action.to_s, parameters) + generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action.to_s)) + generated_path = generated_path(generated_extras) + query_string_keys = query_parameter_names(generated_extras) + + @request.assign_parameters(@routes, controller_class_name, action.to_s, parameters, generated_path, query_string_keys) @request.session.update(session) if session @request.flash.update(flash || {}) if xhr - @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' - @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ') + @request.set_header 'HTTP_X_REQUESTED_WITH', 'XMLHttpRequest' + @request.fetch_header('HTTP_ACCEPT') do |k| + @request.set_header k, [Mime[:js], Mime[:html], Mime[:xml], 'text/xml', '*/*'].join(', ') + end end - @controller.request = @request - @controller.response = @response - - @request.env["SCRIPT_NAME"] ||= @controller.config.relative_url_root + @request.fetch_header("SCRIPT_NAME") do |k| + @request.set_header k, @controller.config.relative_url_root + end @controller.recycle! - @controller.process(action) + @controller.dispatch(action, @request, @response) + @request = @controller.request + @response = @controller.response - @request.env.delete 'HTTP_COOKIE' + @request.delete_header 'HTTP_COOKIE' - if cookies = @request.env['action_dispatch.cookies'] - unless @response.committed? - cookies.write(@response) - self.cookies.update(cookies.instance_variable_get(:@cookies)) + if @request.have_cookie_jar? + unless @request.cookie_jar.committed? + @request.cookie_jar.write(@response) + self.cookies.update(@request.cookie_jar.instance_variable_get(:@cookies)) end end @response.prepare! @@ -518,14 +538,26 @@ module ActionController end if xhr - @request.env.delete 'HTTP_X_REQUESTED_WITH' - @request.env.delete 'HTTP_ACCEPT' + @request.delete_header 'HTTP_X_REQUESTED_WITH' + @request.delete_header 'HTTP_ACCEPT' end @request.query_string = '' @response end + def controller_class_name + @controller.class.anonymous? ? "anonymous" : @controller.class.controller_path + end + + def generated_path(generated_extras) + generated_extras[0] + end + + def query_parameter_names(generated_extras) + generated_extras[1] + [:controller, :action] + end + def setup_controller_request_and_response @controller = nil unless defined? @controller @@ -555,7 +587,7 @@ module ActionController end def build_response(klass) - klass.new + klass.create end included do @@ -629,4 +661,5 @@ module ActionController include Behavior end + # :startdoc: end |