diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/testing')
9 files changed, 155 insertions, 132 deletions
diff --git a/actionpack/lib/action_dispatch/testing/assertion_response.rb b/actionpack/lib/action_dispatch/testing/assertion_response.rb index 404b96bbcd..c37726957e 100644 --- a/actionpack/lib/action_dispatch/testing/assertion_response.rb +++ b/actionpack/lib/action_dispatch/testing/assertion_response.rb @@ -34,12 +34,12 @@ module ActionDispatch private - def code_from_name(name) - GENERIC_RESPONSE_CODES[name] || Rack::Utils::SYMBOL_TO_STATUS_CODE[name] - end + def code_from_name(name) + GENERIC_RESPONSE_CODES[name] || Rack::Utils::SYMBOL_TO_STATUS_CODE[name] + end - def name_from_code(code) - GENERIC_RESPONSE_CODES.invert[code] || Rack::Utils::HTTP_STATUS_CODES[code] - end + def name_from_code(code) + GENERIC_RESPONSE_CODES.invert[code] || Rack::Utils::HTTP_STATUS_CODES[code] + end end end diff --git a/actionpack/lib/action_dispatch/testing/assertions.rb b/actionpack/lib/action_dispatch/testing/assertions.rb index fae266273e..b362931ef7 100644 --- a/actionpack/lib/action_dispatch/testing/assertions.rb +++ b/actionpack/lib/action_dispatch/testing/assertions.rb @@ -1,9 +1,9 @@ -require 'rails-dom-testing' +require "rails-dom-testing" module ActionDispatch module Assertions - autoload :ResponseAssertions, 'action_dispatch/testing/assertions/response' - autoload :RoutingAssertions, 'action_dispatch/testing/assertions/routing' + autoload :ResponseAssertions, "action_dispatch/testing/assertions/response" + autoload :RoutingAssertions, "action_dispatch/testing/assertions/routing" extend ActiveSupport::Concern diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb index cd55b7d975..a00602ed70 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/response.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb @@ -83,7 +83,7 @@ module ActionDispatch end def location_if_redirected - return '' unless @response.redirection? && @response.location.present? + return "" unless @response.redirection? && @response.location.present? location = normalize_argument_to_redirection(@response.location) " redirect to <#{location}>" end diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index 44ad2c10d8..e53bc6af12 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -1,7 +1,7 @@ -require 'uri' -require 'active_support/core_ext/hash/indifferent_access' -require 'active_support/core_ext/string/access' -require 'action_controller/metal/exceptions' +require "uri" +require "active_support/core_ext/hash/indifferent_access" +require "active_support/core_ext/string/access" +require "action_controller/metal/exceptions" module ActionDispatch module Assertions @@ -82,7 +82,7 @@ module ActionDispatch expected_path = uri.path.to_s.empty? ? "/" : uri.path end else - expected_path = "/#{expected_path}" unless expected_path.first == '/' + expected_path = "/#{expected_path}" unless expected_path.first == "/" end # Load routes.rb if it hasn't been loaded. @@ -127,7 +127,7 @@ module ActionDispatch options[:controller] = "/#{controller}" end - generate_options = options.dup.delete_if{ |k, _| defaults.key?(k) } + generate_options = options.dup.delete_if { |k, _| defaults.key?(k) } assert_generates(path.is_a?(Hash) ? path[:path] : path, generate_options, defaults, extras, message) end @@ -184,7 +184,7 @@ module ActionDispatch end # Assume given controller - request = ActionController::TestRequest.create + request = ActionController::TestRequest.create @controller.class if path =~ %r{://} fail_on(URI::InvalidURIError, msg) do @@ -202,7 +202,7 @@ module ActionDispatch request.request_method = method if method params = fail_on(ActionController::RoutingError, msg) do - @routes.recognize_path(path, { :method => method, :extras => extras }) + @routes.recognize_path(path, method: method, extras: extras) end request.path_parameters = params.with_indifferent_access diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index 10cd1e5787..13f7fc6fa6 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -1,10 +1,12 @@ -require 'stringio' -require 'uri' -require 'active_support/core_ext/kernel/singleton_class' -require 'active_support/core_ext/object/try' -require 'active_support/core_ext/string/strip' -require 'rack/test' -require 'minitest' +require "stringio" +require "uri" +require "active_support/core_ext/kernel/singleton_class" +require "active_support/core_ext/object/try" +require "active_support/core_ext/string/strip" +require "rack/test" +require "minitest" + +require "action_dispatch/testing/request_encoder" module ActionDispatch module Integration #:nodoc: @@ -122,7 +124,7 @@ module ActionDispatch # params: { ref_id: 14 }, # headers: { "X-Test-Header" => "testvalue" } def request_via_redirect(http_method, path, *args) - ActiveSupport::Deprecation.warn('`request_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.') + ActiveSupport::Deprecation.warn("`request_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.") process_with_kwargs(http_method, path, *args) follow_redirect! while redirect? @@ -132,35 +134,35 @@ module ActionDispatch # Performs a GET request, following any subsequent redirect. # See +request_via_redirect+ for more information. def get_via_redirect(path, *args) - ActiveSupport::Deprecation.warn('`get_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.') + ActiveSupport::Deprecation.warn("`get_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.") request_via_redirect(:get, path, *args) end # Performs a POST request, following any subsequent redirect. # See +request_via_redirect+ for more information. def post_via_redirect(path, *args) - ActiveSupport::Deprecation.warn('`post_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.') + ActiveSupport::Deprecation.warn("`post_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.") request_via_redirect(:post, path, *args) end # Performs a PATCH request, following any subsequent redirect. # See +request_via_redirect+ for more information. def patch_via_redirect(path, *args) - ActiveSupport::Deprecation.warn('`patch_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.') + ActiveSupport::Deprecation.warn("`patch_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.") request_via_redirect(:patch, path, *args) end # Performs a PUT request, following any subsequent redirect. # See +request_via_redirect+ for more information. def put_via_redirect(path, *args) - ActiveSupport::Deprecation.warn('`put_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.') + ActiveSupport::Deprecation.warn("`put_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.") request_via_redirect(:put, path, *args) end # Performs a DELETE request, following any subsequent redirect. # See +request_via_redirect+ for more information. def delete_via_redirect(path, *args) - ActiveSupport::Deprecation.warn('`delete_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.') + ActiveSupport::Deprecation.warn("`delete_via_redirect` is deprecated and will be removed in Rails 5.1. Please use `follow_redirect!` manually after the request call for the same behavior.") request_via_redirect(:delete, path, *args) end end @@ -180,11 +182,11 @@ module ActionDispatch include TestProcess, RequestHelpers, Assertions %w( status status_message headers body redirect? ).each do |method| - delegate method, :to => :response, :allow_nil => true + delegate method, to: :response, allow_nil: true end %w( path ).each do |method| - delegate method, :to => :request, :allow_nil => true + delegate method, to: :request, allow_nil: true end # The hostname used in the last request. @@ -235,7 +237,7 @@ module ActionDispatch url_options.reverse_merge!(@app.routes.default_url_options) end - url_options.reverse_merge!(:host => host, :protocol => https? ? "https" : "http") + url_options.reverse_merge!(host: host, protocol: https? ? "https" : "http") end end @@ -296,7 +298,7 @@ module ActionDispatch process(http_method, path, *args) else non_kwarg_request_warning if args.any? - process(http_method, path, { params: args[0], headers: args[1] }) + process(http_method, path, params: args[0], headers: args[1]) end end @@ -325,6 +327,12 @@ module ActionDispatch # Performs the actual request. def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: nil) request_encoder = RequestEncoder.encoder(as) + headers ||= {} + + if method == :get && as == :json && params + headers["X-Http-Method-Override"] = "GET" + method = :post + end if path =~ %r{://} path = build_expanded_path(path, request_encoder) do |location| @@ -340,7 +348,7 @@ module ActionDispatch path = build_expanded_path(path, request_encoder) end - hostname, port = host.split(':') + hostname, port = host.split(":") request_env = { :method => method, @@ -358,15 +366,17 @@ module ActionDispatch "HTTP_ACCEPT" => accept } + wrapped_headers = Http::Headers.from_hash({}) + wrapped_headers.merge!(headers) if headers + if xhr - headers ||= {} - headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' - headers['HTTP_ACCEPT'] ||= [Mime[:js], Mime[:html], Mime[:xml], 'text/xml', '*/*'].join(', ') + wrapped_headers["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" + wrapped_headers["HTTP_ACCEPT"] ||= [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(", ") end # this modifies the passed request_env directly - if headers.present? - Http::Headers.from_hash(request_env).merge!(headers) + if wrapped_headers.present? + Http::Headers.from_hash(request_env).merge!(wrapped_headers) end if env.present? Http::Headers.from_hash(request_env).merge!(env) @@ -383,7 +393,6 @@ module ActionDispatch response = _mock_session.last_response @response = ActionDispatch::TestResponse.from_response(response) @response.request = @request - @response.response_parser = RequestEncoder.parser(@response.content_type) @html_document = nil @url_options = nil @@ -402,59 +411,6 @@ module ActionDispatch path = request_encoder.append_format_to location.path location.query ? "#{path}?#{location.query}" : path end - - class RequestEncoder # :nodoc: - @encoders = {} - - attr_reader :response_parser - - def initialize(mime_name, param_encoder, response_parser, url_encoded_form = false) - @mime = Mime[mime_name] - - unless @mime - raise ArgumentError, "Can't register a request encoder for " \ - "unregistered MIME Type: #{mime_name}. See `Mime::Type.register`." - end - - @url_encoded_form = url_encoded_form - @path_format = ".#{@mime.symbol}" unless @url_encoded_form - @response_parser = response_parser || -> body { body } - @param_encoder = param_encoder || :"to_#{@mime.symbol}".to_proc - end - - def append_format_to(path) - if @url_encoded_form - path - else - path + @path_format - end - end - - def content_type - @mime.to_s - end - - def encode_params(params) - @param_encoder.call(params) - end - - def self.parser(content_type) - mime = Mime::Type.lookup(content_type) - encoder(mime ? mime.ref : nil).response_parser - end - - def self.encoder(name) - @encoders[name] || WWWFormEncoder - end - - def self.register_encoder(mime_name, param_encoder: nil, response_parser: nil) - @encoders[mime_name] = new(mime_name, param_encoder, response_parser) - end - - register_encoder :json, response_parser: -> body { JSON.parse(body) } - - WWWFormEncoder = new(:url_encoded_form, -> params { params }, nil, true) - end end module Runner @@ -500,7 +456,7 @@ module ActionDispatch xml_http_request xhr get_via_redirect post_via_redirect).each do |method| define_method(method) do |*args| # reset the html_document variable, except for cookies/assigns calls - unless method == 'cookies' || method == 'assigns' + unless method == "cookies" || method == "assigns" @html_document = nil end @@ -711,38 +667,42 @@ module ActionDispatch # end # end # + # See the {request helpers documentation}[rdoc-ref:ActionDispatch::Integration::RequestHelpers] for help on how to + # use +get+, etc. + # + # === Changing the request encoding + # # You can also test your JSON API easily by setting what the request should # be encoded as: # - # require 'test_helper' + # require "test_helper" # # class ApiTest < ActionDispatch::IntegrationTest - # test 'creates articles' do + # test "creates articles" do # assert_difference -> { Article.count } do - # post articles_path, params: { article: { title: 'Ahoy!' } }, as: :json + # post articles_path, params: { article: { title: "Ahoy!" } }, as: :json # end # # assert_response :success - # assert_equal({ id: Arcticle.last.id, title: 'Ahoy!' }, response.parsed_body) + # assert_equal({ id: Arcticle.last.id, title: "Ahoy!" }, response.parsed_body) # end # end # - # The `as` option sets the format to JSON, sets the content type to - # 'application/json' and encodes the parameters as JSON. + # The +as+ option sets the format to JSON, sets the content type to + # "application/json" and encodes the parameters as JSON. # - # Calling `parsed_body` on the response parses the response body as what - # the last request was encoded as. If the request wasn't encoded `as` something, - # it's the same as calling `body`. + # Calling +parsed_body+ on the response parses the response body based on the + # last response MIME type. # - # For any custom MIME Types you've registered, you can even add your own encoders with: + # For any custom MIME types you've registered, you can even add your own encoders with: # # ActionDispatch::IntegrationTest.register_encoder :wibble, # param_encoder: -> params { params.to_wibble }, # response_parser: -> body { body } # - # Where `param_encoder` defines how the params should be encoded and - # `response_parser` defines how the response body should be parsed through - # `parsed_body`. + # Where +param_encoder+ defines how the params should be encoded and + # +response_parser+ defines how the response body should be parsed through + # +parsed_body+. # # Consult the Rails Testing Guide for more. @@ -769,7 +729,11 @@ module ActionDispatch module ClassMethods def app - defined?(@@app) ? @@app : ActionDispatch.test_app + if defined?(@@app) && @@app + @@app + else + ActionDispatch.test_app + end end def app=(app) @@ -777,7 +741,7 @@ module ActionDispatch end def register_encoder(*args) - Integration::Session::RequestEncoder.register_encoder(*args) + RequestEncoder.register_encoder(*args) end end diff --git a/actionpack/lib/action_dispatch/testing/request_encoder.rb b/actionpack/lib/action_dispatch/testing/request_encoder.rb new file mode 100644 index 0000000000..b0b994b2d0 --- /dev/null +++ b/actionpack/lib/action_dispatch/testing/request_encoder.rb @@ -0,0 +1,54 @@ +module ActionDispatch + class RequestEncoder # :nodoc: + @encoders = {} + + attr_reader :response_parser + + def initialize(mime_name, param_encoder, response_parser, url_encoded_form = false) + @mime = Mime[mime_name] + + unless @mime + raise ArgumentError, "Can't register a request encoder for " \ + "unregistered MIME Type: #{mime_name}. See `Mime::Type.register`." + end + + @url_encoded_form = url_encoded_form + @path_format = ".#{@mime.symbol}" unless @url_encoded_form + @response_parser = response_parser || -> body { body } + @param_encoder = param_encoder || :"to_#{@mime.symbol}".to_proc + end + + def append_format_to(path) + if @url_encoded_form + path + else + path + @path_format + end + end + + def content_type + @mime.to_s + end + + def encode_params(params) + @param_encoder.call(params) + end + + def self.parser(content_type) + mime = Mime::Type.lookup(content_type) + encoder(mime ? mime.ref : nil).response_parser + end + + def self.encoder(name) + @encoders[name] || WWWFormEncoder + end + + def self.register_encoder(mime_name, param_encoder: nil, response_parser: nil) + @encoders[mime_name] = new(mime_name, param_encoder, response_parser) + end + + register_encoder :json, response_parser: -> body { JSON.parse(body) } + + WWWFormEncoder = new(:url_encoded_form, -> params { params }, nil, true) + end +end diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb index 1ecd7d14a7..1456a0afcf 100644 --- a/actionpack/lib/action_dispatch/testing/test_process.rb +++ b/actionpack/lib/action_dispatch/testing/test_process.rb @@ -1,5 +1,5 @@ -require 'action_dispatch/middleware/cookies' -require 'action_dispatch/middleware/flash' +require "action_dispatch/middleware/cookies" +require "action_dispatch/middleware/flash" module ActionDispatch module TestProcess diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb index 46523a8600..d0beb72a41 100644 --- a/actionpack/lib/action_dispatch/testing/test_request.rb +++ b/actionpack/lib/action_dispatch/testing/test_request.rb @@ -1,12 +1,12 @@ -require 'active_support/core_ext/hash/indifferent_access' -require 'rack/utils' +require "active_support/core_ext/hash/indifferent_access" +require "rack/utils" module ActionDispatch class TestRequest < Request - DEFAULT_ENV = Rack::MockRequest.env_for('/', - 'HTTP_HOST' => 'test.host', - 'REMOTE_ADDR' => '0.0.0.0', - 'HTTP_USER_AGENT' => 'Rails Testing', + DEFAULT_ENV = Rack::MockRequest.env_for("/", + "HTTP_HOST" => "test.host", + "REMOTE_ADDR" => "0.0.0.0", + "HTTP_USER_AGENT" => "Rails Testing", ) # Create a new test request with default `env` values @@ -22,23 +22,23 @@ module ActionDispatch private_class_method :default_env def request_method=(method) - set_header('REQUEST_METHOD', method.to_s.upcase) + set_header("REQUEST_METHOD", method.to_s.upcase) end def host=(host) - set_header('HTTP_HOST', host) + set_header("HTTP_HOST", host) end def port=(number) - set_header('SERVER_PORT', number.to_i) + set_header("SERVER_PORT", number.to_i) end def request_uri=(uri) - set_header('REQUEST_URI', uri) + set_header("REQUEST_URI", uri) end def path=(path) - set_header('PATH_INFO', path) + set_header("PATH_INFO", path) end def action=(action_name) @@ -46,24 +46,24 @@ module ActionDispatch end def if_modified_since=(last_modified) - set_header('HTTP_IF_MODIFIED_SINCE', last_modified) + set_header("HTTP_IF_MODIFIED_SINCE", last_modified) end def if_none_match=(etag) - set_header('HTTP_IF_NONE_MATCH', etag) + set_header("HTTP_IF_NONE_MATCH", etag) end def remote_addr=(addr) - set_header('REMOTE_ADDR', addr) + set_header("REMOTE_ADDR", addr) end def user_agent=(user_agent) - set_header('HTTP_USER_AGENT', user_agent) + set_header("HTTP_USER_AGENT", user_agent) end def accept=(mime_types) - delete_header('action_dispatch.request.accepts') - set_header('HTTP_ACCEPT', Array(mime_types).collect(&:to_s).join(",")) + delete_header("action_dispatch.request.accepts") + set_header("HTTP_ACCEPT", Array(mime_types).collect(&:to_s).join(",")) end end end diff --git a/actionpack/lib/action_dispatch/testing/test_response.rb b/actionpack/lib/action_dispatch/testing/test_response.rb index 9d4b73a43d..5c89f9c75e 100644 --- a/actionpack/lib/action_dispatch/testing/test_response.rb +++ b/actionpack/lib/action_dispatch/testing/test_response.rb @@ -1,3 +1,5 @@ +require "action_dispatch/testing/request_encoder" + module ActionDispatch # Integration test methods such as ActionDispatch::Integration::Session#get # and ActionDispatch::Integration::Session#post return objects of class @@ -10,6 +12,11 @@ module ActionDispatch new response.status, response.headers, response.body end + def initialize(*) # :nodoc: + super + @response_parser = RequestEncoder.parser(content_type) + end + # Was the response successful? alias_method :success?, :successful? @@ -19,8 +26,6 @@ module ActionDispatch # Was there a server-side error? alias_method :error?, :server_error? - attr_writer :response_parser # :nodoc: - def parsed_body @parsed_body ||= @response_parser.call(body) end |