diff options
Diffstat (limited to 'actionpack/test')
22 files changed, 457 insertions, 35 deletions
diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb index 34bc2c0caa..409a4ec2e6 100644 --- a/actionpack/test/controller/flash_test.rb +++ b/actionpack/test/controller/flash_test.rb @@ -342,6 +342,21 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest end end + def test_flash_usable_in_metal_without_helper + controller_class = nil + + assert_nothing_raised do + controller_class = Class.new(ActionController::Metal) do + include ActionController::Flash + end + end + + controller = controller_class.new + + assert_respond_to controller, :alert + assert_respond_to controller, :notice + end + private # Overwrite get to send SessionSecret in env hash diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index 3f211cd60d..b133afb343 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -272,7 +272,7 @@ class HttpDigestAuthenticationTest < ActionController::TestCase credentials.merge!(options) path_info = @request.env["PATH_INFO"].to_s uri = options[:uri] || path_info - credentials.merge!(uri: uri) + credentials[:uri] = uri @request.env["ORIGINAL_FULLPATH"] = path_info ActionController::HttpAuthentication::Digest.encode_credentials(method, credentials, password, options[:password_is_ha1]) end diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 9cdf04b886..39ede1442a 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -349,6 +349,16 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest end end + def test_redirect_with_arguments + with_test_route_set do + get "/redirect" + follow_redirect! params: { foo: :bar } + + assert_response :ok + assert_equal "bar", request.parameters["foo"] + end + end + def test_xml_http_request_get with_test_route_set do get "/get", xhr: true @@ -1069,6 +1079,20 @@ class IntegrationRequestEncodersTest < ActionDispatch::IntegrationTest end end + def test_get_request_with_json_excludes_null_query_string + with_routing do |routes| + routes.draw do + ActiveSupport::Deprecation.silence do + get ":action" => FooController + end + end + + get "/foos_json", as: :json + + assert_equal "http://www.example.com/foos_json", request.url + end + end + private def post_to_foos(as:) with_routing do |routes| diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index be455642de..0562c16284 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -82,9 +82,7 @@ module Another @last_payload = payload end - def last_payload - @last_payload - end + attr_reader :last_payload end end diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb index 771eccb29b..1163775d3c 100644 --- a/actionpack/test/controller/mime/respond_to_test.rb +++ b/actionpack/test/controller/mime/respond_to_test.rb @@ -102,6 +102,26 @@ class RespondToController < ActionController::Base end end + def using_conflicting_nested_js_then_html + respond_to do |outer_type| + outer_type.js do + respond_to do |inner_type| + inner_type.html { render body: "HTML" } + end + end + end + end + + def using_non_conflicting_nested_js_then_js + respond_to do |outer_type| + outer_type.js do + respond_to do |inner_type| + inner_type.js { render body: "JS" } + end + end + end + end + def custom_type_handling respond_to do |type| type.html { render body: "HTML" } @@ -430,6 +450,20 @@ class RespondToControllerTest < ActionController::TestCase assert_equal "<p>Hello world!</p>\n", @response.body end + def test_using_conflicting_nested_js_then_html + @request.accept = "*/*" + assert_raises(ActionController::RespondToMismatchError) do + get :using_conflicting_nested_js_then_html + end + end + + def test_using_non_conflicting_nested_js_then_js + @request.accept = "*/*" + get :using_non_conflicting_nested_js_then_js + assert_equal "text/javascript", @response.content_type + assert_equal "JS", @response.body + end + def test_with_atom_content_type @request.accept = "" @request.env["CONTENT_TYPE"] = "application/atom+xml" diff --git a/actionpack/test/controller/parameters/accessors_test.rb b/actionpack/test/controller/parameters/accessors_test.rb index 674b2c6266..68c7f2d9ea 100644 --- a/actionpack/test/controller/parameters/accessors_test.rb +++ b/actionpack/test/controller/parameters/accessors_test.rb @@ -190,6 +190,27 @@ class ParametersAccessorsTest < ActiveSupport::TestCase assert_not_predicate @params.transform_values { |v| v }, :permitted? end + test "transform_values converts hashes to parameters" do + @params.transform_values do |value| + assert_kind_of ActionController::Parameters, value + value + end + end + + test "transform_values without block yieds an enumerator" do + assert_kind_of Enumerator, @params.transform_values + end + + test "transform_values! converts hashes to parameters" do + @params.transform_values! do |value| + assert_kind_of ActionController::Parameters, value + end + end + + test "transform_values! without block yields an enumerator" do + assert_kind_of Enumerator, @params.transform_values! + end + test "value? returns true if the given value is present in the params" do params = ActionController::Parameters.new(city: "Chicago", state: "Illinois") assert params.value?("Chicago") diff --git a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb index fe0e5e368d..974612fb7b 100644 --- a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb +++ b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb @@ -20,7 +20,7 @@ class AlwaysPermittedParametersTest < ActiveSupport::TestCase end end - test "permits parameters that are whitelisted" do + test "allows both explicitly listed and always-permitted parameters" do params = ActionController::Parameters.new( book: { pages: 65 }, format: "json") diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index 2959dc3e4d..461e627154 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -5,6 +5,12 @@ require "abstract_unit" class Workshop extend ActiveModel::Naming include ActiveModel::Conversion + + OUT_OF_SCOPE_BLOCK = proc do + raise "Not executed in controller's context" unless RedirectController === self + request.original_url + end + attr_accessor :id def initialize(id) @@ -119,6 +125,10 @@ class RedirectController < ActionController::Base redirect_to proc { { action: "hello_world" } } end + def redirect_to_out_of_scope_block + redirect_to Workshop::OUT_OF_SCOPE_BLOCK + end + def redirect_with_header_break redirect_to "/lol\r\nwat" end @@ -326,6 +336,12 @@ class RedirectTest < ActionController::TestCase assert_redirected_to "http://www.rubyonrails.org/" end + def test_redirect_to_out_of_scope_block + get :redirect_to_out_of_scope_block + assert_response :redirect + assert_redirected_to "http://test.host/redirect/redirect_to_out_of_scope_block" + end + def test_redirect_to_with_block_and_accepted_options with_routing do |set| set.draw do diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 24c5761e41..306b245bd1 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -141,6 +141,16 @@ class TestController < ActionController::Base render action: "hello_world" end + def conditional_hello_with_expires_in_with_stale_while_revalidate + expires_in 1.minute, public: true, stale_while_revalidate: 5.minutes + render action: "hello_world" + end + + def conditional_hello_with_expires_in_with_stale_if_error + expires_in 1.minute, public: true, stale_if_error: 5.minutes + render action: "hello_world" + end + def conditional_hello_with_expires_in_with_public_with_more_keys expires_in 1.minute, :public => true, "s-maxage" => 5.hours render action: "hello_world" @@ -240,6 +250,15 @@ class TestController < ActionController::Base head 204 end + def head_default_content_type + # simulating path like "/1.foobar" + request.formats = [] + + respond_to do |format| + format.any { head 200 } + end + end + private def set_variable_for_layout @@ -358,6 +377,16 @@ class ExpiresInRenderTest < ActionController::TestCase assert_equal "max-age=60, public, must-revalidate", @response.headers["Cache-Control"] end + def test_expires_in_header_with_stale_while_revalidate + get :conditional_hello_with_expires_in_with_stale_while_revalidate + assert_equal "max-age=60, public, stale-while-revalidate=300", @response.headers["Cache-Control"] + end + + def test_expires_in_header_with_stale_if_error + get :conditional_hello_with_expires_in_with_stale_if_error + assert_equal "max-age=60, public, stale-if-error=300", @response.headers["Cache-Control"] + end + def test_expires_in_header_with_additional_headers get :conditional_hello_with_expires_in_with_public_with_more_keys assert_equal "max-age=60, public, s-maxage=18000", @response.headers["Cache-Control"] @@ -794,6 +823,11 @@ class HeadRenderTest < ActionController::TestCase get :head_and_return end end + + def test_head_default_content_type + post :head_default_content_type + assert_equal "text/html", @response.header["Content-Type"] + end end class HttpCacheForeverTest < ActionController::TestCase diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 7a02c27c99..ea94a3e048 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -521,6 +521,11 @@ module RequestForgeryProtectionTests get :negotiate_same_origin end + assert_cross_origin_blocked do + @request.accept = "application/javascript" + get :negotiate_same_origin + end + assert_cross_origin_not_blocked { get :same_origin_js, xhr: true } assert_cross_origin_not_blocked { get :same_origin_js, xhr: true, format: "js" } assert_cross_origin_not_blocked do diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 30bea64c55..d336b96eff 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -66,7 +66,6 @@ class ResourcesTest < ActionController::TestCase member_methods.each_key do |action| assert_named_route "/messages/1/#{path_names[action] || action}", "#{action}_message_path", action: action, id: "1" end - end end end @@ -1323,7 +1322,7 @@ class ResourcesTest < ActionController::TestCase def assert_resource_allowed_routes(controller, options, shallow_options, allowed, not_allowed, path = controller) shallow_path = "#{path}/#{shallow_options[:id]}" format = options[:format] && ".#{options[:format]}" - options.merge!(controller: controller) + options[:controller] = controller shallow_options.merge!(options) assert_whether_allowed(allowed, not_allowed, options, "index", "#{path}#{format}", :get) @@ -1337,7 +1336,7 @@ class ResourcesTest < ActionController::TestCase def assert_singleton_resource_allowed_routes(controller, options, allowed, not_allowed, path = controller.singularize) format = options[:format] && ".#{options[:format]}" - options.merge!(controller: controller) + options[:controller] = controller assert_whether_allowed(allowed, not_allowed, options, "new", "#{path}/new#{format}", :get) assert_whether_allowed(allowed, not_allowed, options, "create", "#{path}#{format}", :post) diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 9d0a8b4f00..a7033b2d30 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -937,7 +937,6 @@ class RouteSetTest < ActiveSupport::TestCase @default_route_set ||= begin set = ActionDispatch::Routing::RouteSet.new set.draw do - ActiveSupport::Deprecation.silence do get "/:controller(/:action(/:id))" end @@ -1342,11 +1341,9 @@ class RouteSetTest < ActiveSupport::TestCase def test_namespace set.draw do - namespace "api" do get "inventory" => "products#inventory" end - end params = request_path_params("/api/inventory", method: :get) diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb index 734da3de9c..dda2686a9b 100644 --- a/actionpack/test/controller/test_case_test.rb +++ b/actionpack/test/controller/test_case_test.rb @@ -223,6 +223,27 @@ XML assert_equal params.to_query, @response.body end + def test_params_round_trip + params = { "foo" => { "contents" => [{ "name" => "gorby", "id" => "123" }, { "name" => "puff", "d" => "true" }] } } + post :test_params, params: params.dup + + controller_info = { "controller" => "test_case_test/test", "action" => "test_params" } + assert_equal params.merge(controller_info), JSON.parse(@response.body) + end + + def test_handle_to_params + klass = Class.new do + def to_param + "bar" + end + end + + post :test_params, params: { foo: klass.new } + + assert_equal JSON.parse(@response.body)["foo"], "bar" + end + + def test_body_stream params = Hash[:page, { name: "page name" }, "some key", 123] @@ -380,7 +401,13 @@ XML process :test_xml_output, params: { response_as: "text/html" } # <area> auto-closes, so the <p> becomes a sibling - assert_select "root > area + p" + if defined?(JRUBY_VERSION) + # https://github.com/sparklemotion/nokogiri/issues/1653 + # HTML parser "fixes" "broken" markup in slightly different ways + assert_select "root > map > area + p" + else + assert_select "root > area + p" + end end def test_should_not_impose_childless_html_tags_in_xml diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index aba778fad6..6637c2cae9 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -289,6 +289,46 @@ class CookiesTest < ActionController::TestCase cookies[:user_name] = { value: "assain", expires: 2.hours } head :ok end + + def encrypted_discount_and_user_id_cookie + cookies.encrypted[:user_id] = { value: 50, expires: 1.hour } + cookies.encrypted[:discount_percentage] = 10 + + head :ok + end + + def signed_discount_and_user_id_cookie + cookies.signed[:user_id] = { value: 50, expires: 1.hour } + cookies.signed[:discount_percentage] = 10 + + head :ok + end + + def rails_5_2_stable_encrypted_cookie_with_authenticated_encryption_flag_on + # cookies.encrypted[:favorite] = { value: "5-2-Stable Chocolate Cookies", expires: 1000.years } + cookies[:favorite] = "KvH5lIHvX5vPQkLIK63r/NuIMwzWky8M0Zwk8SZ6DwUv8+srf36geR4nWq5KmhsZIYXA8NRdCZYIfxMKJsOFlz77Gf+Fq8vBBCWJTp95rx39A28TCUTJEyMhCNJO5eie7Skef76Qt5Jo/SCnIADAhzyGQkGBopKRcA==--qXZZFWGbCy6N8AGy--WswoH+xHrNh9MzSXDpB2fA==" + + head :ok + end + + def rails_5_2_stable_encrypted_cookie_with_authenticated_encryption_flag_off + cookies[:favorite] = "Wmg4amgvcVVvWGcwK3c4WjJEbTdRQUgrWXhBdDliUTR0cVNidXpmVTMrc2RjcitwUzVsWWEwZGtuVGtFUjJwNi0tcVhVMTFMOTQ1d0hIVE1FK0pJc05SQT09--8b2a55c375049a50f7a959b9d42b31ef0b2bb594" + + head :ok + end + + def rails_5_2_stable_signed_cookie_with_authenticated_encryption_flag_on + # cookies.signed[:favorite] = { value: "5-2-Stable Choco Chip Cookie", expires: 1000.years } + cookies[:favorite] = "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaUUxTFRJdFUzUmhZbXhsSUVOb2IyTnZJRU5vYVhBZ1EyOXZhMmxsQmpvR1JWUT0iLCJleHAiOiIzMDE4LTA3LTExVDE2OjExOjI2Ljc1M1oiLCJwdXIiOm51bGx9fQ==--7df5d885b78b70a501d6e82140ae91b24060ac00" + + head :ok + end + + def rails_5_2_stable_signed_cookie_with_authenticated_encryption_flag_off + cookies[:favorite] = "BAhJIiE1LTItU3RhYmxlIENob2NvIENoaXAgQ29va2llBjoGRVQ=--50bbdbf8d64f5a3ec3e54878f54d4f55b6cb3aff" + + head :ok + end end tests TestController @@ -1274,6 +1314,8 @@ class CookiesTest < ActionController::TestCase end def test_signed_cookie_with_expires_set_relatively + request.env["action_dispatch.use_cookies_with_metadata"] = true + cookies.signed[:user_name] = { value: "assain", expires: 2.hours } travel 1.hour @@ -1284,6 +1326,8 @@ class CookiesTest < ActionController::TestCase end def test_encrypted_cookie_with_expires_set_relatively + request.env["action_dispatch.use_cookies_with_metadata"] = true + cookies.encrypted[:user_name] = { value: "assain", expires: 2.hours } travel 1.hour @@ -1300,6 +1344,124 @@ class CookiesTest < ActionController::TestCase end end + def test_purpose_metadata_for_encrypted_cookies + get :encrypted_discount_and_user_id_cookie + + cookies[:discount_percentage] = cookies[:user_id] + assert_equal 50, cookies.encrypted[:discount_percentage] + + request.env["action_dispatch.use_cookies_with_metadata"] = true + + get :encrypted_discount_and_user_id_cookie + + cookies[:discount_percentage] = cookies[:user_id] + assert_nil cookies.encrypted[:discount_percentage] + end + + def test_purpose_metadata_for_signed_cookies + get :signed_discount_and_user_id_cookie + + cookies[:discount_percentage] = cookies[:user_id] + assert_equal 50, cookies.signed[:discount_percentage] + + request.env["action_dispatch.use_cookies_with_metadata"] = true + + get :signed_discount_and_user_id_cookie + + cookies[:discount_percentage] = cookies[:user_id] + assert_nil cookies.signed[:discount_percentage] + end + + def test_switch_off_metadata_for_encrypted_cookies_if_config_is_false + request.env["action_dispatch.use_cookies_with_metadata"] = false + + get :encrypted_discount_and_user_id_cookie + + travel 2.hours + assert_equal 50, cookies.encrypted[:user_id] + + cookies[:discount_percentage] = cookies[:user_id] + assert_not_equal 10, cookies.encrypted[:discount_percentage] + assert_equal 50, cookies.encrypted[:discount_percentage] + end + + def test_switch_off_metadata_for_signed_cookies_if_config_is_false + request.env["action_dispatch.use_cookies_with_metadata"] = false + + get :signed_discount_and_user_id_cookie + + travel 2.hours + assert_equal 50, cookies.signed[:user_id] + + cookies[:discount_percentage] = cookies[:user_id] + assert_not_equal 10, cookies.signed[:discount_percentage] + assert_equal 50, cookies.signed[:discount_percentage] + end + + def test_read_rails_5_2_stable_encrypted_cookies_if_config_is_false + request.env["action_dispatch.use_cookies_with_metadata"] = false + + get :rails_5_2_stable_encrypted_cookie_with_authenticated_encryption_flag_on + + assert_equal "5-2-Stable Chocolate Cookies", cookies.encrypted[:favorite] + + travel 1001.years do + assert_nil cookies.encrypted[:favorite] + end + + get :rails_5_2_stable_encrypted_cookie_with_authenticated_encryption_flag_off + + assert_equal "5-2-Stable Chocolate Cookies", cookies.encrypted[:favorite] + end + + def test_read_rails_5_2_stable_signed_cookies_if_config_is_false + request.env["action_dispatch.use_cookies_with_metadata"] = false + + get :rails_5_2_stable_signed_cookie_with_authenticated_encryption_flag_on + + assert_equal "5-2-Stable Choco Chip Cookie", cookies.signed[:favorite] + + travel 1001.years do + assert_nil cookies.signed[:favorite] + end + + get :rails_5_2_stable_signed_cookie_with_authenticated_encryption_flag_off + + assert_equal "5-2-Stable Choco Chip Cookie", cookies.signed[:favorite] + end + + def test_read_rails_5_2_stable_encrypted_cookies_if_use_metadata_config_is_true + request.env["action_dispatch.use_cookies_with_metadata"] = true + + get :rails_5_2_stable_encrypted_cookie_with_authenticated_encryption_flag_on + + assert_equal "5-2-Stable Chocolate Cookies", cookies.encrypted[:favorite] + + travel 1001.years do + assert_nil cookies.encrypted[:favorite] + end + + get :rails_5_2_stable_encrypted_cookie_with_authenticated_encryption_flag_off + + assert_equal "5-2-Stable Chocolate Cookies", cookies.encrypted[:favorite] + end + + def test_read_rails_5_2_stable_signed_cookies_if_use_metadata_config_is_true + request.env["action_dispatch.use_cookies_with_metadata"] = true + + get :rails_5_2_stable_signed_cookie_with_authenticated_encryption_flag_on + + assert_equal "5-2-Stable Choco Chip Cookie", cookies.signed[:favorite] + + travel 1001.years do + assert_nil cookies.signed[:favorite] + end + + get :rails_5_2_stable_signed_cookie_with_authenticated_encryption_flag_off + + assert_equal "5-2-Stable Choco Chip Cookie", cookies.signed[:favorite] + end + private def assert_cookie_header(expected) header = @response.headers["Set-Cookie"] diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb index 045567ff83..44b79c0e5d 100644 --- a/actionpack/test/dispatch/debug_exceptions_test.rb +++ b/actionpack/test/dispatch/debug_exceptions_test.rb @@ -26,6 +26,18 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest raise StandardError.new "error in framework" end + def raise_nested_exceptions + begin + raise "First error" + rescue + begin + raise "Second error" + rescue + raise "Third error" + end + end + end + def call(env) env["action_dispatch.show_detailed_exceptions"] = @detailed req = ActionDispatch::Request.new(env) @@ -74,6 +86,8 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest end when %r{/framework_raises} method_that_raises + when %r{/nested_exceptions} + raise_nested_exceptions else raise "puke!" end @@ -440,8 +454,8 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest get "/original_syntax_error", headers: { "action_dispatch.backtrace_cleaner" => ActiveSupport::BacktraceCleaner.new } assert_response 500 - assert_select "#Application-Trace" do - assert_select "pre code", /syntax error, unexpected/ + assert_select "#Application-Trace-0" do + assert_select "code", /syntax error, unexpected/ end end @@ -454,9 +468,9 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest assert_select "#container h2", /^Missing template/ - assert_select "#Application-Trace" - assert_select "#Framework-Trace" - assert_select "#Full-Trace" + assert_select "#Application-Trace-0" + assert_select "#Framework-Trace-0" + assert_select "#Full-Trace-0" assert_select "h2", /Request/ end @@ -467,8 +481,8 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest get "/syntax_error_into_view", headers: { "action_dispatch.backtrace_cleaner" => ActiveSupport::BacktraceCleaner.new } assert_response 500 - assert_select "#Application-Trace" do - assert_select "pre code", /syntax error, unexpected/ + assert_select "#Application-Trace-0" do + assert_select "code", /syntax error, unexpected/ end end @@ -497,13 +511,13 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest end # assert application trace refers to line that calls method_that_raises is first - assert_select "#Application-Trace" do - assert_select "pre code a:first", %r{test/dispatch/debug_exceptions_test\.rb:\d+:in `call} + assert_select "#Application-Trace-0" do + assert_select "code a:first", %r{test/dispatch/debug_exceptions_test\.rb:\d+:in `call} end # assert framework trace that threw the error is first - assert_select "#Framework-Trace" do - assert_select "pre code a:first", /method_that_raises/ + assert_select "#Framework-Trace-0" do + assert_select "code a:first", /method_that_raises/ end end end @@ -523,4 +537,39 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest assert_response 500 assert_match(/puke/, body) end + + test "debug exceptions app shows all the nested exceptions in source view" do + @app = DevelopmentApp + Rails.stub :root, Pathname.new(".") do + cleaner = ActiveSupport::BacktraceCleaner.new.tap do |bc| + bc.add_silencer { |line| line !~ %r{test/dispatch/debug_exceptions_test.rb} } + end + + get "/nested_exceptions", headers: { "action_dispatch.backtrace_cleaner" => cleaner } + + # Assert correct error + assert_response 500 + assert_select "h2", /Third error/ + + # assert source view line shows the last error + assert_select "div.source:not(.hidden)" do + assert_select "pre .line.active", /raise "Third error"/ + end + + # assert application trace refers to line that raises the last exception + assert_select "#Application-Trace-0" do + assert_select "code a:first", %r{in `rescue in rescue in raise_nested_exceptions'} + end + + # assert the second application trace refers to the line that raises the second exception + assert_select "#Application-Trace-1" do + assert_select "code a:first", %r{in `rescue in raise_nested_exceptions'} + end + + # assert the third application trace refers to the line that raises the first exception + assert_select "#Application-Trace-2" do + assert_select "code a:first", %r{in `raise_nested_exceptions'} + end + end + end end diff --git a/actionpack/test/dispatch/exception_wrapper_test.rb b/actionpack/test/dispatch/exception_wrapper_test.rb index f6e70382a8..668469a01d 100644 --- a/actionpack/test/dispatch/exception_wrapper_test.rb +++ b/actionpack/test/dispatch/exception_wrapper_test.rb @@ -20,6 +20,7 @@ module ActionDispatch setup do @cleaner = ActiveSupport::BacktraceCleaner.new + @cleaner.remove_filters! @cleaner.add_silencer { |line| line !~ /^lib/ } end @@ -108,11 +109,27 @@ module ActionDispatch wrapper = ExceptionWrapper.new(@cleaner, exception) assert_equal({ - "Application Trace" => [ id: 0, trace: "lib/file.rb:42:in `index'" ], - "Framework Trace" => [ id: 1, trace: "/gems/rack.rb:43:in `index'" ], + "Application Trace" => [ + exception_object_id: exception.object_id, + id: 0, + trace: "lib/file.rb:42:in `index'" + ], + "Framework Trace" => [ + exception_object_id: exception.object_id, + id: 1, + trace: "/gems/rack.rb:43:in `index'" + ], "Full Trace" => [ - { id: 0, trace: "lib/file.rb:42:in `index'" }, - { id: 1, trace: "/gems/rack.rb:43:in `index'" } + { + exception_object_id: exception.object_id, + id: 0, + trace: "lib/file.rb:42:in `index'" + }, + { + exception_object_id: exception.object_id, + id: 1, + trace: "/gems/rack.rb:43:in `index'" + } ] }, wrapper.traces) end diff --git a/actionpack/test/dispatch/header_test.rb b/actionpack/test/dispatch/header_test.rb index 3a265a056b..bd2a5b35fb 100644 --- a/actionpack/test/dispatch/header_test.rb +++ b/actionpack/test/dispatch/header_test.rb @@ -156,7 +156,7 @@ class HeaderTest < ActiveSupport::TestCase env = { "HTTP_REFERER" => "/" } headers = make_headers(env) headers["Referer"] = "http://example.com/" - headers.merge! "CONTENT_TYPE" => "text/plain" + headers["CONTENT_TYPE"] = "text/plain" assert_equal({ "HTTP_REFERER" => "http://example.com/", "CONTENT_TYPE" => "text/plain" }, env) end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 84a2d1f69e..0ac8713527 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -1078,10 +1078,13 @@ class RequestParameterFilter < BaseRequestTest filter_words << lambda { |key, value| value.reverse! if key =~ /bargain/ } + filter_words << lambda { |key, value, original_params| + value.replace("world!") if original_params["barg"]["blah"] == "bar" && key == "hello" + } parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words) - before_filter["barg"] = { :bargain => "gain", "blah" => "bar", "bar" => { "bargain" => { "blah" => "foo" } } } - after_filter["barg"] = { :bargain => "niag", "blah" => "[FILTERED]", "bar" => { "bargain" => { "blah" => "[FILTERED]" } } } + before_filter["barg"] = { :bargain => "gain", "blah" => "bar", "bar" => { "bargain" => { "blah" => "foo", "hello" => "world" } } } + after_filter["barg"] = { :bargain => "niag", "blah" => "[FILTERED]", "bar" => { "bargain" => { "blah" => "[FILTERED]", "hello" => "world!" } } } assert_equal after_filter, parameter_filter.filter(before_filter) end diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb index 9150d5010b..f1f6547889 100644 --- a/actionpack/test/dispatch/routing/inspector_test.rb +++ b/actionpack/test/dispatch/routing/inspector_test.rb @@ -368,7 +368,7 @@ module ActionDispatch assert_equal [ "No routes were found for this grep pattern.", - "For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html." + "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html." ], output end @@ -380,7 +380,7 @@ module ActionDispatch "", "Please add some routes in config/routes.rb.", "", - "For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html." + "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html." ], output end @@ -434,7 +434,7 @@ module ActionDispatch assert_equal [ "No routes were found for this controller.", - "For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html." + "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html." ], output end @@ -445,7 +445,7 @@ module ActionDispatch assert_equal [ "No routes were found for this grep pattern.", - "For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html." + "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html." ], output end @@ -457,7 +457,7 @@ module ActionDispatch "", "Please add some routes in config/routes.rb.", "", - "For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html." + "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html." ], output end diff --git a/actionpack/test/dispatch/uploaded_file_test.rb b/actionpack/test/dispatch/uploaded_file_test.rb index 5a584b12e5..21169fcb5c 100644 --- a/actionpack/test/dispatch/uploaded_file_test.rb +++ b/actionpack/test/dispatch/uploaded_file_test.rb @@ -103,6 +103,12 @@ module ActionDispatch assert_predicate uf, :eof? end + def test_delegate_to_path_to_tempfile + tf = Class.new { def to_path; "/any/file/path" end; } + uf = Http::UploadedFile.new(tempfile: tf.new) + assert_equal "/any/file/path", uf.to_path + end + def test_respond_to? tf = Class.new { def read; yield end } uf = Http::UploadedFile.new(tempfile: tf.new) diff --git a/actionpack/test/journey/route/definition/scanner_test.rb b/actionpack/test/journey/route/definition/scanner_test.rb index bcbe4388c3..092177d315 100644 --- a/actionpack/test/journey/route/definition/scanner_test.rb +++ b/actionpack/test/journey/route/definition/scanner_test.rb @@ -30,6 +30,12 @@ module ActionDispatch ["/~page", [[:SLASH, "/"], [:LITERAL, "~page"]]], ["/pa-ge", [[:SLASH, "/"], [:LITERAL, "pa-ge"]]], ["/:page", [[:SLASH, "/"], [:SYMBOL, ":page"]]], + ["/:page|*foo", [ + [:SLASH, "/"], + [:SYMBOL, ":page"], + [:OR, "|"], + [:STAR, "*foo"] + ]], ["/(:page)", [ [:SLASH, "/"], [:LPAREN, "("], diff --git a/actionpack/test/journey/router_test.rb b/actionpack/test/journey/router_test.rb index 183f421bcf..1f4e14aef6 100644 --- a/actionpack/test/journey/router_test.rb +++ b/actionpack/test/journey/router_test.rb @@ -493,6 +493,15 @@ module ActionDispatch assert_not called end + def test_eager_load_with_routes + get "/foo-bar", to: "foo#bar" + assert_nil router.eager_load! + end + + def test_eager_load_without_routes + assert_nil router.eager_load! + end + private def get(*args) |