aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/test
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/test')
-rw-r--r--actionpack/test/abstract/callbacks_test.rb4
-rw-r--r--actionpack/test/abstract/collector_test.rb2
-rw-r--r--actionpack/test/abstract_unit.rb100
-rw-r--r--actionpack/test/controller/action_pack_assertions_test.rb54
-rw-r--r--actionpack/test/controller/api/conditional_get_test.rb2
-rw-r--r--actionpack/test/controller/api/force_ssl_test.rb4
-rw-r--r--actionpack/test/controller/base_test.rb6
-rw-r--r--actionpack/test/controller/caching_test.rb28
-rw-r--r--actionpack/test/controller/filters_test.rb22
-rw-r--r--actionpack/test/controller/flash_hash_test.rb10
-rw-r--r--actionpack/test/controller/flash_test.rb23
-rw-r--r--actionpack/test/controller/force_ssl_test.rb40
-rw-r--r--actionpack/test/controller/http_digest_authentication_test.rb18
-rw-r--r--actionpack/test/controller/http_token_authentication_test.rb2
-rw-r--r--actionpack/test/controller/integration_test.rb42
-rw-r--r--actionpack/test/controller/live_stream_test.rb2
-rw-r--r--actionpack/test/controller/log_subscriber_test.rb4
-rw-r--r--actionpack/test/controller/metal_test.rb8
-rw-r--r--actionpack/test/controller/mime/respond_to_test.rb40
-rw-r--r--actionpack/test/controller/new_base/bare_metal_test.rb2
-rw-r--r--actionpack/test/controller/new_base/render_context_test.rb54
-rw-r--r--actionpack/test/controller/output_escaping_test.rb2
-rw-r--r--actionpack/test/controller/parameters/accessors_test.rb143
-rw-r--r--actionpack/test/controller/parameters/always_permitted_parameters_test.rb4
-rw-r--r--actionpack/test/controller/parameters/dup_test.rb6
-rw-r--r--actionpack/test/controller/parameters/multi_parameter_attributes_test.rb2
-rw-r--r--actionpack/test/controller/parameters/mutators_test.rb37
-rw-r--r--actionpack/test/controller/parameters/nested_parameters_permit_test.rb4
-rw-r--r--actionpack/test/controller/parameters/parameters_permit_test.rb107
-rw-r--r--actionpack/test/controller/parameters/serialization_test.rb11
-rw-r--r--actionpack/test/controller/params_parse_test.rb34
-rw-r--r--actionpack/test/controller/redirect_test.rb52
-rw-r--r--actionpack/test/controller/render_test.rb76
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb7
-rw-r--r--actionpack/test/controller/rescue_test.rb48
-rw-r--r--actionpack/test/controller/resources_test.rb27
-rw-r--r--actionpack/test/controller/routing_test.rb23
-rw-r--r--actionpack/test/controller/runner_test.rb4
-rw-r--r--actionpack/test/controller/send_file_test.rb4
-rw-r--r--actionpack/test/controller/test_case_test.rb85
-rw-r--r--actionpack/test/controller/url_for_test.rb10
-rw-r--r--actionpack/test/controller/webservice_test.rb6
-rw-r--r--actionpack/test/dispatch/content_disposition_test.rb37
-rw-r--r--actionpack/test/dispatch/content_security_policy_test.rb264
-rw-r--r--actionpack/test/dispatch/cookies_test.rb354
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb178
-rw-r--r--actionpack/test/dispatch/exception_wrapper_test.rb25
-rw-r--r--actionpack/test/dispatch/executor_test.rb6
-rw-r--r--actionpack/test/dispatch/header_test.rb2
-rw-r--r--actionpack/test/dispatch/host_authorization_test.rb161
-rw-r--r--actionpack/test/dispatch/live_response_test.rb4
-rw-r--r--actionpack/test/dispatch/middleware_stack_test.rb2
-rw-r--r--actionpack/test/dispatch/mime_type_test.rb68
-rw-r--r--actionpack/test/dispatch/mount_test.rb6
-rw-r--r--actionpack/test/dispatch/prefix_generation_test.rb2
-rw-r--r--actionpack/test/dispatch/reloader_test.rb4
-rw-r--r--actionpack/test/dispatch/request/json_params_parsing_test.rb58
-rw-r--r--actionpack/test/dispatch/request/session_test.rb13
-rw-r--r--actionpack/test/dispatch/request_id_test.rb5
-rw-r--r--actionpack/test/dispatch/request_test.rb280
-rw-r--r--actionpack/test/dispatch/response_test.rb32
-rw-r--r--actionpack/test/dispatch/routing/inspector_test.rb102
-rw-r--r--actionpack/test/dispatch/routing/non_dispatch_routed_app_test.rb27
-rw-r--r--actionpack/test/dispatch/routing_assertions_test.rb6
-rw-r--r--actionpack/test/dispatch/routing_test.rb72
-rw-r--r--actionpack/test/dispatch/session/mem_cache_store_test.rb9
-rw-r--r--actionpack/test/dispatch/show_exceptions_test.rb28
-rw-r--r--actionpack/test/dispatch/ssl_test.rb12
-rw-r--r--actionpack/test/dispatch/static_test.rb15
-rw-r--r--actionpack/test/dispatch/system_testing/driver_test.rb76
-rw-r--r--actionpack/test/dispatch/system_testing/screenshot_helper_test.rb31
-rw-r--r--actionpack/test/dispatch/system_testing/server_test.rb2
-rw-r--r--actionpack/test/dispatch/system_testing/system_test_case_test.rb1
-rw-r--r--actionpack/test/dispatch/test_response_test.rb7
-rw-r--r--actionpack/test/dispatch/uploaded_file_test.rb12
-rw-r--r--actionpack/test/fixtures/alternate_helpers/foo_helper.rb2
-rw-r--r--actionpack/test/fixtures/functional_caching/_formatted_partial.html.erb1
-rw-r--r--actionpack/test/fixtures/functional_caching/xml_fragment_cached_with_html_partial.xml.builder5
-rw-r--r--actionpack/test/fixtures/public/foo/さようなら.html1
-rw-r--r--actionpack/test/fixtures/public/foo/さようなら.html.gzbin0 -> 67 bytes
-rw-r--r--actionpack/test/fixtures/公共/foo/さようなら.html1
-rw-r--r--actionpack/test/fixtures/公共/foo/さようなら.html.gzbin0 -> 67 bytes
-rw-r--r--actionpack/test/journey/nodes/symbol_test.rb4
-rw-r--r--actionpack/test/journey/path/pattern_test.rb22
-rw-r--r--actionpack/test/journey/route/definition/scanner_test.rb103
-rw-r--r--actionpack/test/journey/router/utils_test.rb2
-rw-r--r--actionpack/test/journey/router_test.rb15
-rw-r--r--actionpack/test/journey/routes_test.rb6
-rw-r--r--actionpack/test/tmp/.gitignore0
89 files changed, 2067 insertions, 1155 deletions
diff --git a/actionpack/test/abstract/callbacks_test.rb b/actionpack/test/abstract/callbacks_test.rb
index fdc09bd951..4512ea27b3 100644
--- a/actionpack/test/abstract/callbacks_test.rb
+++ b/actionpack/test/abstract/callbacks_test.rb
@@ -154,7 +154,7 @@ module AbstractController
test "when :except is specified, an after action is not triggered on that action" do
@controller.process(:index)
- assert !@controller.instance_variable_defined?("@authenticated")
+ assert_not @controller.instance_variable_defined?("@authenticated")
end
end
@@ -198,7 +198,7 @@ module AbstractController
test "when :except is specified with an array, an after action is not triggered on that action" do
@controller.process(:index)
- assert !@controller.instance_variable_defined?("@authenticated")
+ assert_not @controller.instance_variable_defined?("@authenticated")
end
end
diff --git a/actionpack/test/abstract/collector_test.rb b/actionpack/test/abstract/collector_test.rb
index a4770b66e1..6db045fcd7 100644
--- a/actionpack/test/abstract/collector_test.rb
+++ b/actionpack/test/abstract/collector_test.rb
@@ -30,7 +30,7 @@ module AbstractController
end
test "register mime types on method missing" do
- AbstractController::Collector.send(:remove_method, :js)
+ AbstractController::Collector.remove_method :js
begin
collector = MyCollector.new
assert_not_respond_to collector, :js
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index deffa63e12..f23151e518 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -13,13 +13,6 @@ silence_warnings do
Encoding.default_external = Encoding::UTF_8
end
-require "drb"
-begin
- require "drb/unix"
-rescue LoadError
- puts "'drb/unix' is not available"
-end
-
if ENV["TRAVIS"]
PROCESS_COUNT = 0
else
@@ -80,7 +73,7 @@ end
module ActiveSupport
class TestCase
if RUBY_ENGINE == "ruby" && PROCESS_COUNT > 0
- parallelize_me!
+ parallelize(workers: PROCESS_COUNT)
end
end
end
@@ -232,6 +225,7 @@ module ActionController
routes = ActionDispatch::Routing::RouteSet.new
routes.draw(&block)
include routes.url_helpers
+ routes
end
end
@@ -358,95 +352,21 @@ class ImagesController < ResourcesController; end
require "active_support/testing/method_call_assertions"
-class ForkingExecutor
- class Server
- include DRb::DRbUndumped
-
- def initialize
- @queue = Queue.new
- end
-
- def record(reporter, result)
- reporter.record result
- end
-
- def <<(o)
- o[2] = DRbObject.new(o[2]) if o
- @queue << o
- end
- def pop; @queue.pop; end
- end
-
- def initialize(size)
- @size = size
- @queue = Server.new
- file = File.join Dir.tmpdir, tmpname
- @url = "drbunix://#{file}"
- @pool = nil
- DRb.start_service @url, @queue
- end
-
- def <<(work); @queue << work; end
-
- def shutdown
- pool = @size.times.map {
- fork {
- DRb.stop_service
- queue = DRbObject.new_with_uri @url
- while job = queue.pop
- klass = job[0]
- method = job[1]
- reporter = job[2]
- result = Minitest.run_one_method klass, method
- if result.error?
- translate_exceptions result
- end
- queue.record reporter, result
- end
- }
- }
- @size.times { @queue << nil }
- pool.each { |pid| Process.waitpid pid }
- end
+class ActiveSupport::TestCase
+ include ActiveSupport::Testing::MethodCallAssertions
private
- def translate_exceptions(result)
- result.failures.map! { |e|
- begin
- Marshal.dump e
- e
- rescue TypeError
- ex = Exception.new e.message
- ex.set_backtrace e.backtrace
- Minitest::UnexpectedError.new ex
- end
- }
+ # Skips the current run on Rubinius using Minitest::Assertions#skip
+ def rubinius_skip(message = "")
+ skip message if RUBY_ENGINE == "rbx"
end
- def tmpname
- t = Time.now.strftime("%Y%m%d")
- "rails-tests-#{t}-#{$$}-#{rand(0x100000000).to_s(36)}-fd"
+ # Skips the current run on JRuby using Minitest::Assertions#skip
+ def jruby_skip(message = "")
+ skip message if defined?(JRUBY_VERSION)
end
end
-if RUBY_ENGINE == "ruby" && PROCESS_COUNT > 0
- # Use N processes (N defaults to 4)
- Minitest.parallel_executor = ForkingExecutor.new(PROCESS_COUNT)
-end
-
-class ActiveSupport::TestCase
- include ActiveSupport::Testing::MethodCallAssertions
-
- # Skips the current run on Rubinius using Minitest::Assertions#skip
- private def rubinius_skip(message = "")
- skip message if RUBY_ENGINE == "rbx"
- end
- # Skips the current run on JRuby using Minitest::Assertions#skip
- private def jruby_skip(message = "")
- skip message if defined?(JRUBY_VERSION)
- end
-end
-
class DrivenByRackTest < ActionDispatch::SystemTestCase
driven_by :rack_test
end
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index f9a037e3cc..ecb8c37e6b 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -276,43 +276,41 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
end
def test_assert_redirect_failure_message_with_protocol_relative_url
- begin
- process :redirect_external_protocol_relative
- assert_redirected_to "/foo"
- rescue ActiveSupport::TestCase::Assertion => ex
- assert_no_match(
- /#{request.protocol}#{request.host}\/\/www.rubyonrails.org/,
- ex.message,
- "protocol relative url was incorrectly normalized"
- )
- end
+ process :redirect_external_protocol_relative
+ assert_redirected_to "/foo"
+ rescue ActiveSupport::TestCase::Assertion => ex
+ assert_no_match(
+ /#{request.protocol}#{request.host}\/\/www.rubyonrails.org/,
+ ex.message,
+ "protocol relative url was incorrectly normalized"
+ )
end
def test_template_objects_exist
process :assign_this
- assert !@controller.instance_variable_defined?(:"@hi")
+ assert_not @controller.instance_variable_defined?(:"@hi")
assert @controller.instance_variable_get(:"@howdy")
end
def test_template_objects_missing
process :nothing
- assert !@controller.instance_variable_defined?(:@howdy)
+ assert_not @controller.instance_variable_defined?(:@howdy)
end
def test_empty_flash
process :flash_me_naked
- assert flash.empty?
+ assert_empty flash
end
def test_flash_exist
process :flash_me
- assert flash.any?
- assert flash["hello"].present?
+ assert_predicate flash, :any?
+ assert_predicate flash["hello"], :present?
end
def test_flash_does_not_exist
process :nothing
- assert flash.empty?
+ assert_empty flash
end
def test_session_exist
@@ -322,7 +320,7 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
def session_does_not_exist
process :nothing
- assert session.empty?
+ assert_empty session
end
def test_redirection_location
@@ -343,46 +341,46 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
def test_server_error_response_code
process :response500
- assert @response.server_error?
+ assert_predicate @response, :server_error?
process :response599
- assert @response.server_error?
+ assert_predicate @response, :server_error?
process :response404
- assert !@response.server_error?
+ assert_not_predicate @response, :server_error?
end
def test_missing_response_code
process :response404
- assert @response.not_found?
+ assert_predicate @response, :not_found?
end
def test_client_error_response_code
process :response404
- assert @response.client_error?
+ assert_predicate @response, :client_error?
end
def test_redirect_url_match
process :redirect_external
- assert @response.redirect?
+ assert_predicate @response, :redirect?
assert_match(/rubyonrails/, @response.redirect_url)
- assert !/perloffrails/.match(@response.redirect_url)
+ assert_no_match(/perloffrails/, @response.redirect_url)
end
def test_redirection
process :redirect_internal
- assert @response.redirect?
+ assert_predicate @response, :redirect?
process :redirect_external
- assert @response.redirect?
+ assert_predicate @response, :redirect?
process :nothing
- assert !@response.redirect?
+ assert_not_predicate @response, :redirect?
end
def test_successful_response_code
process :nothing
- assert @response.successful?
+ assert_predicate @response, :successful?
end
def test_response_object
diff --git a/actionpack/test/controller/api/conditional_get_test.rb b/actionpack/test/controller/api/conditional_get_test.rb
index fd1997f26c..e366ce9532 100644
--- a/actionpack/test/controller/api/conditional_get_test.rb
+++ b/actionpack/test/controller/api/conditional_get_test.rb
@@ -53,7 +53,7 @@ class ConditionalGetApiTest < ActionController::TestCase
@request.if_modified_since = @last_modified
get :one
assert_equal 304, @response.status.to_i
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_equal @last_modified, @response.headers["Last-Modified"]
end
end
diff --git a/actionpack/test/controller/api/force_ssl_test.rb b/actionpack/test/controller/api/force_ssl_test.rb
index 07459c3753..8191578eb0 100644
--- a/actionpack/test/controller/api/force_ssl_test.rb
+++ b/actionpack/test/controller/api/force_ssl_test.rb
@@ -3,7 +3,9 @@
require "abstract_unit"
class ForceSSLApiController < ActionController::API
- force_ssl
+ ActiveSupport::Deprecation.silence do
+ force_ssl
+ end
def one; end
def two
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index 9ac82c0d65..d8cea10153 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -107,9 +107,9 @@ class ControllerInstanceTests < ActiveSupport::TestCase
end
def test_performed?
- assert !@empty.performed?
+ assert_not_predicate @empty, :performed?
@empty.response_body = ["sweet"]
- assert @empty.performed?
+ assert_predicate @empty, :performed?
end
def test_action_methods
@@ -138,7 +138,7 @@ class ControllerInstanceTests < ActiveSupport::TestCase
response_headers = SimpleController.action("hello").call(
"REQUEST_METHOD" => "GET",
- "rack.input" => -> {}
+ "rack.input" => -> { }
)[1]
assert response_headers.key?("X-Frame-Options")
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index 3557f9f888..5543f9120f 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -60,14 +60,6 @@ class FragmentCachingTest < ActionController::TestCase
@m2v2 = ModelWithKeyAndVersion.new("model/2", "2")
end
- def test_fragment_cache_key
- assert_deprecated do
- assert_equal "views/what a key", @controller.fragment_cache_key("what a key")
- assert_equal "views/test.host/fragment_caching_test/some_action",
- @controller.fragment_cache_key(controller: "fragment_caching_test", action: "some_action")
- end
- end
-
def test_combined_fragment_cache_key
assert_equal [ :views, "what a key" ], @controller.combined_fragment_cache_key("what a key")
assert_equal [ :views, "test.host/fragment_caching_test/some_action" ],
@@ -94,14 +86,14 @@ class FragmentCachingTest < ActionController::TestCase
def test_fragment_exist_with_caching_enabled
@store.write("views/name", "value")
assert @controller.fragment_exist?("name")
- assert !@controller.fragment_exist?("other_name")
+ assert_not @controller.fragment_exist?("other_name")
end
def test_fragment_exist_with_caching_disabled
@controller.perform_caching = false
@store.write("views/name", "value")
- assert !@controller.fragment_exist?("name")
- assert !@controller.fragment_exist?("other_name")
+ assert_not @controller.fragment_exist?("name")
+ assert_not @controller.fragment_exist?("other_name")
end
def test_write_fragment_with_caching_enabled
@@ -144,7 +136,7 @@ class FragmentCachingTest < ActionController::TestCase
buffer = "generated till now -> ".html_safe
buffer << view_context.send(:fragment_for, "expensive") { fragment_computed = true }
- assert !fragment_computed
+ assert_not fragment_computed
assert_equal "generated till now -> fragment content", buffer
end
@@ -159,7 +151,7 @@ class FragmentCachingTest < ActionController::TestCase
html_safe = @controller.read_fragment("name")
assert_equal content, html_safe
- assert html_safe.html_safe?
+ assert_predicate html_safe, :html_safe?
end
end
@@ -173,6 +165,9 @@ class FunctionalCachingController < CachingController
end
end
+ def xml_fragment_cached_with_html_partial
+ end
+
def formatted_fragment_cached
respond_to do |format|
format.html
@@ -308,6 +303,11 @@ CACHED
@store.read("views/functional_caching/formatted_fragment_cached_with_variant:#{template_digest("functional_caching/formatted_fragment_cached_with_variant")}/fragment")
end
+ def test_fragment_caching_with_html_partials_in_xml
+ get :xml_fragment_cached_with_html_partial, format: "*/*"
+ assert_response :success
+ end
+
private
def template_digest(name)
ActionView::Digestor.digest(name: name, finder: @controller.lookup_context)
@@ -382,7 +382,7 @@ class ViewCacheDependencyTest < ActionController::TestCase
end
def test_view_cache_dependencies_are_empty_by_default
- assert NoDependenciesController.new.view_cache_dependencies.empty?
+ assert_empty NoDependenciesController.new.view_cache_dependencies
end
def test_view_cache_dependencies_are_listed_in_declaration_order
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 9f0a9dec7a..fcee812ee4 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -457,6 +457,7 @@ class FilterTest < ActionController::TestCase
prepend_before_action :before_all
prepend_after_action :after_all
before_action :between_before_all_and_after_all
+ after_action :between_before_all_and_after_all
def before_all
@ran_filter ||= []
@@ -472,6 +473,7 @@ class FilterTest < ActionController::TestCase
@ran_filter ||= []
@ran_filter << "between_before_all_and_after_all"
end
+
def show
render plain: "hello"
end
@@ -765,7 +767,7 @@ class FilterTest < ActionController::TestCase
def test_running_prepended_before_and_after_action
test_process(PrependingBeforeAndAfterController)
- assert_equal %w( before_all between_before_all_and_after_all after_all ), @controller.instance_variable_get(:@ran_filter)
+ assert_equal %w( before_all between_before_all_and_after_all between_before_all_and_after_all after_all ), @controller.instance_variable_get(:@ran_filter)
end
def test_skipping_and_limiting_controller
@@ -787,7 +789,7 @@ class FilterTest < ActionController::TestCase
assert_equal %w( ensure_login find_user ), @controller.instance_variable_get(:@ran_filter)
test_process(ConditionalSkippingController, "login")
- assert !@controller.instance_variable_defined?("@ran_after_action")
+ assert_not @controller.instance_variable_defined?("@ran_after_action")
test_process(ConditionalSkippingController, "change_password")
assert_equal %w( clean_up ), @controller.instance_variable_get("@ran_after_action")
end
@@ -819,7 +821,7 @@ class FilterTest < ActionController::TestCase
response = test_process(RescuedController)
end
- assert response.successful?
+ assert_predicate response, :successful?
assert_equal("I rescued this: #<FilterTest::ErrorToRescue: Something made the bad noise.>", response.body)
end
@@ -886,7 +888,7 @@ class ControllerWithSymbolAsFilter < PostsController
yield
# Do stuff...
- wtf += 1
+ wtf + 1
end
end
@@ -998,16 +1000,12 @@ class YieldingAroundFiltersTest < ActionController::TestCase
def test_nested_actions
controller = ControllerWithNestedFilters
assert_nothing_raised do
- begin
- test_process(controller, "raises_both")
- rescue Before, After
- end
+ test_process(controller, "raises_both")
+ rescue Before, After
end
assert_raise Before do
- begin
- test_process(controller, "raises_both")
- rescue After
- end
+ test_process(controller, "raises_both")
+ rescue After
end
end
diff --git a/actionpack/test/controller/flash_hash_test.rb b/actionpack/test/controller/flash_hash_test.rb
index f31a4d9329..e3ec5bb7fc 100644
--- a/actionpack/test/controller/flash_hash_test.rb
+++ b/actionpack/test/controller/flash_hash_test.rb
@@ -44,7 +44,7 @@ module ActionDispatch
@hash["foo"] = "bar"
@hash.delete "foo"
- assert !@hash.key?("foo")
+ assert_not @hash.key?("foo")
assert_nil @hash["foo"]
end
@@ -53,7 +53,7 @@ module ActionDispatch
assert_equal({ "foo" => "bar" }, @hash.to_hash)
@hash.to_hash["zomg"] = "aaron"
- assert !@hash.key?("zomg")
+ assert_not @hash.key?("zomg")
assert_equal({ "foo" => "bar" }, @hash.to_hash)
end
@@ -92,11 +92,11 @@ module ActionDispatch
end
def test_empty?
- assert @hash.empty?
+ assert_empty @hash
@hash["zomg"] = "bears"
- assert !@hash.empty?
+ assert_not_empty @hash
@hash.clear
- assert @hash.empty?
+ assert_empty @hash
end
def test_each
diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb
index 34bc2c0caa..bf95c633e5 100644
--- a/actionpack/test/controller/flash_test.rb
+++ b/actionpack/test/controller/flash_test.rb
@@ -242,8 +242,11 @@ end
class FlashIntegrationTest < ActionDispatch::IntegrationTest
SessionKey = "_myapp_session"
- Generator = ActiveSupport::LegacyKeyGenerator.new("b3c631c314c0bbca50c1b2843150fe33")
- Rotations = ActiveSupport::Messages::RotationConfiguration.new
+ Generator = ActiveSupport::CachingKeyGenerator.new(
+ ActiveSupport::KeyGenerator.new("b3c631c314c0bbca50c1b2843150fe33", iterations: 1000)
+ )
+ Rotations = ActiveSupport::Messages::RotationConfiguration.new
+ SIGNED_COOKIE_SALT = "signed cookie"
class TestController < ActionController::Base
add_flash_types :bar
@@ -342,6 +345,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
@@ -350,6 +368,7 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest
args[0][:env] ||= {}
args[0][:env]["action_dispatch.key_generator"] ||= Generator
args[0][:env]["action_dispatch.cookies_rotations"] = Rotations
+ args[0][:env]["action_dispatch.signed_cookie_salt"] = SIGNED_COOKIE_SALT
super(path, *args)
end
diff --git a/actionpack/test/controller/force_ssl_test.rb b/actionpack/test/controller/force_ssl_test.rb
index 84ac1fda3c..7f59f6acaf 100644
--- a/actionpack/test/controller/force_ssl_test.rb
+++ b/actionpack/test/controller/force_ssl_test.rb
@@ -13,19 +13,23 @@ class ForceSSLController < ActionController::Base
end
class ForceSSLControllerLevel < ForceSSLController
- force_ssl
+ ActiveSupport::Deprecation.silence do
+ force_ssl
+ end
end
class ForceSSLCustomOptions < ForceSSLController
- force_ssl host: "secure.example.com", only: :redirect_host
- force_ssl port: 8443, only: :redirect_port
- force_ssl subdomain: "secure", only: :redirect_subdomain
- force_ssl domain: "secure.com", only: :redirect_domain
- force_ssl path: "/foo", only: :redirect_path
- force_ssl status: :found, only: :redirect_status
- force_ssl flash: { message: "Foo, Bar!" }, only: :redirect_flash
- force_ssl alert: "Foo, Bar!", only: :redirect_alert
- force_ssl notice: "Foo, Bar!", only: :redirect_notice
+ ActiveSupport::Deprecation.silence do
+ force_ssl host: "secure.example.com", only: :redirect_host
+ force_ssl port: 8443, only: :redirect_port
+ force_ssl subdomain: "secure", only: :redirect_subdomain
+ force_ssl domain: "secure.com", only: :redirect_domain
+ force_ssl path: "/foo", only: :redirect_path
+ force_ssl status: :found, only: :redirect_status
+ force_ssl flash: { message: "Foo, Bar!" }, only: :redirect_flash
+ force_ssl alert: "Foo, Bar!", only: :redirect_alert
+ force_ssl notice: "Foo, Bar!", only: :redirect_notice
+ end
def force_ssl_action
render plain: action_name
@@ -55,15 +59,21 @@ class ForceSSLCustomOptions < ForceSSLController
end
class ForceSSLOnlyAction < ForceSSLController
- force_ssl only: :cheeseburger
+ ActiveSupport::Deprecation.silence do
+ force_ssl only: :cheeseburger
+ end
end
class ForceSSLExceptAction < ForceSSLController
- force_ssl except: :banana
+ ActiveSupport::Deprecation.silence do
+ force_ssl except: :banana
+ end
end
class ForceSSLIfCondition < ForceSSLController
- force_ssl if: :use_force_ssl?
+ ActiveSupport::Deprecation.silence do
+ force_ssl if: :use_force_ssl?
+ end
def use_force_ssl?
action_name == "cheeseburger"
@@ -71,7 +81,9 @@ class ForceSSLIfCondition < ForceSSLController
end
class ForceSSLFlash < ForceSSLController
- force_ssl except: [:banana, :set_flash, :use_flash]
+ ActiveSupport::Deprecation.silence do
+ force_ssl except: [:banana, :set_flash, :use_flash]
+ end
def set_flash
flash["that"] = "hello"
diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb
index 76ff784926..dd4ff85d11 100644
--- a/actionpack/test/controller/http_digest_authentication_test.rb
+++ b/actionpack/test/controller/http_digest_authentication_test.rb
@@ -9,7 +9,7 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
before_action :authenticate_with_request, only: :display
USERS = { "lifo" => "world", "pretty" => "please",
- "dhh" => ::Digest::MD5::hexdigest(["dhh", "SuperSecret", "secret"].join(":")) }
+ "dhh" => ::Digest::MD5.hexdigest(["dhh", "SuperSecret", "secret"].join(":")) }
def index
render plain: "Hello Secret"
@@ -44,7 +44,10 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
setup do
# Used as secret in generating nonce to prevent tampering of timestamp
@secret = "4fb45da9e4ab4ddeb7580d6a35503d99"
- @request.env["action_dispatch.key_generator"] = ActiveSupport::LegacyKeyGenerator.new(@secret)
+ @request.env["action_dispatch.key_generator"] = ActiveSupport::CachingKeyGenerator.new(
+ ActiveSupport::KeyGenerator.new(@secret)
+ )
+ @request.env["action_dispatch.http_auth_salt"] = "http authentication"
end
teardown do
@@ -181,9 +184,10 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
end
test "authentication request with password stored as ha1 digest hash" do
- @request.env["HTTP_AUTHORIZATION"] = encode_credentials(username: "dhh",
- password: ::Digest::MD5::hexdigest(["dhh", "SuperSecret", "secret"].join(":")),
- password_is_ha1: true)
+ @request.env["HTTP_AUTHORIZATION"] = encode_credentials(
+ username: "dhh",
+ password: ::Digest::MD5.hexdigest(["dhh", "SuperSecret", "secret"].join(":")),
+ password_is_ha1: true)
get :display
assert_response :success
@@ -201,7 +205,7 @@ class HttpDigestAuthenticationTest < ActionController::TestCase
test "validate_digest_response should fail with nil returning password_procedure" do
@request.env["HTTP_AUTHORIZATION"] = encode_credentials(username: nil, password: nil)
- assert !ActionController::HttpAuthentication::Digest.validate_digest_response(@request, "SuperSecret") { nil }
+ assert_not ActionController::HttpAuthentication::Digest.validate_digest_response(@request, "SuperSecret") { nil }
end
test "authentication request with request-uri ending in '/'" do
@@ -271,7 +275,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/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb
index 672aa1351c..103123f98c 100644
--- a/actionpack/test/controller/http_token_authentication_test.rb
+++ b/actionpack/test/controller/http_token_authentication_test.rb
@@ -150,7 +150,7 @@ class HttpTokenAuthenticationTest < ActionController::TestCase
end
test "token_and_options returns empty string with empty token" do
- token = "".dup
+ token = +""
actual = ActionController::HttpAuthentication::Token.token_and_options(sample_request(token)).first
expected = token
assert_equal(expected, actual)
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index fd1c5e693f..b5503a9c64 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -14,11 +14,11 @@ class SessionTest < ActiveSupport::TestCase
end
def test_https_bang_works_and_sets_truth_by_default
- assert !@session.https?
+ assert_not_predicate @session, :https?
@session.https!
- assert @session.https?
+ assert_predicate @session, :https?
@session.https! false
- assert !@session.https?
+ assert_not_predicate @session, :https?
end
def test_host!
@@ -135,7 +135,7 @@ class IntegrationTestTest < ActiveSupport::TestCase
session1 = @test.open_session { |sess| }
session2 = @test.open_session # implicit session
- assert !session1.equal?(session2)
+ assert_not session1.equal?(session2)
end
# RSpec mixes Matchers (which has a #method_missing) into
@@ -152,7 +152,7 @@ class IntegrationTestTest < ActiveSupport::TestCase
assert_equal "pass", @test.foo
ensure
# leave other tests as unaffected as possible
- mixin.__send__(:remove_method, :method_missing)
+ mixin.remove_method :method_missing
end
end
end
@@ -345,7 +345,17 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest
follow_redirect!
assert_response :ok
- refute_same previous_html_document, html_document
+ assert_not_same previous_html_document, html_document
+ 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
@@ -375,7 +385,7 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest
a = open_session
b = open_session
- refute_same(a.integration_session, b.integration_session)
+ assert_not_same(a.integration_session, b.integration_session)
end
def test_get_with_query_string
@@ -412,11 +422,11 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest
get "/get_with_params", params: { foo: "bar" }
- assert request.env["rack.input"].string.empty?
+ assert_empty request.env["rack.input"].string
assert_equal "foo=bar", request.env["QUERY_STRING"]
assert_equal "foo=bar", request.query_string
assert_equal "bar", request.parameters["foo"]
- assert request.parameters["leaks"].nil?
+ assert_predicate request.parameters["leaks"], :nil?
end
end
@@ -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/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb
index 431fe90b23..d81c43b87d 100644
--- a/actionpack/test/controller/live_stream_test.rb
+++ b/actionpack/test/controller/live_stream_test.rb
@@ -304,7 +304,7 @@ module ActionController
# Simulate InterlockHook
ActiveSupport::Dependencies.interlock.start_running
res = get :write_sleep_autoload
- res.each {}
+ res.each { }
ActiveSupport::Dependencies.interlock.done_running
end
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/metal_test.rb b/actionpack/test/controller/metal_test.rb
index c3ebcb22b8..7b53092266 100644
--- a/actionpack/test/controller/metal_test.rb
+++ b/actionpack/test/controller/metal_test.rb
@@ -20,12 +20,12 @@ class MetalControllerInstanceTests < ActiveSupport::TestCase
response_headers = SimpleController.action("hello").call(
"REQUEST_METHOD" => "GET",
- "rack.input" => -> {}
+ "rack.input" => -> { }
)[1]
- refute response_headers.key?("X-Frame-Options")
- refute response_headers.key?("X-Content-Type-Options")
- refute response_headers.key?("X-XSS-Protection")
+ assert_not response_headers.key?("X-Frame-Options")
+ assert_not response_headers.key?("X-Content-Type-Options")
+ assert_not response_headers.key?("X-XSS-Protection")
ensure
ActionDispatch::Response.default_headers = original_default_headers
end
diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb
index f9ffd5f54c..00e1d5f3b3 100644
--- a/actionpack/test/controller/mime/respond_to_test.rb
+++ b/actionpack/test/controller/mime/respond_to_test.rb
@@ -78,7 +78,7 @@ class RespondToController < ActionController::Base
def missing_templates
respond_to do |type|
# This test requires a block that is empty
- type.json {}
+ type.json { }
type.xml
end
end
@@ -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"
@@ -658,13 +692,13 @@ class RespondToControllerTest < ActionController::TestCase
end
def test_variant_without_implicit_rendering_from_browser
- assert_raises(ActionController::UnknownFormat) do
+ assert_raises(ActionController::MissingExactTemplate) do
get :variant_without_implicit_template_rendering, params: { v: :does_not_matter }
end
end
def test_variant_variant_not_set_and_without_implicit_rendering_from_browser
- assert_raises(ActionController::UnknownFormat) do
+ assert_raises(ActionController::MissingExactTemplate) do
get :variant_without_implicit_template_rendering
end
end
diff --git a/actionpack/test/controller/new_base/bare_metal_test.rb b/actionpack/test/controller/new_base/bare_metal_test.rb
index b049022a06..7572d514fb 100644
--- a/actionpack/test/controller/new_base/bare_metal_test.rb
+++ b/actionpack/test/controller/new_base/bare_metal_test.rb
@@ -13,7 +13,7 @@ module BareMetalTest
test "response body is a Rack-compatible response" do
status, headers, body = BareController.action(:index).call(Rack::MockRequest.env_for("/"))
assert_equal 200, status
- string = "".dup
+ string = +""
body.each do |part|
assert part.is_a?(String), "Each part of the body must be a String"
diff --git a/actionpack/test/controller/new_base/render_context_test.rb b/actionpack/test/controller/new_base/render_context_test.rb
deleted file mode 100644
index 07fbadae9f..0000000000
--- a/actionpack/test/controller/new_base/render_context_test.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-require "abstract_unit"
-
-# This is testing the decoupling of view renderer and view context
-# by allowing the controller to be used as view context. This is
-# similar to the way sinatra renders templates.
-module RenderContext
- class BasicController < ActionController::Base
- self.view_paths = [ActionView::FixtureResolver.new(
- "render_context/basic/hello_world.html.erb" => "<%= @value %> from <%= self.__controller_method__ %>",
- "layouts/basic.html.erb" => "?<%= yield %>?"
- )]
-
- # 1) Include ActionView::Context to bring the required dependencies
- include ActionView::Context
-
- # 2) Call _prepare_context that will do the required initialization
- before_action :_prepare_context
-
- def hello_world
- @value = "Hello"
- render action: "hello_world", layout: false
- end
-
- def with_layout
- @value = "Hello"
- render action: "hello_world", layout: "basic"
- end
-
- protected def __controller_method__
- "controller context!"
- end
-
- # 3) Set view_context to self
- private def view_context
- self
- end
- end
-
- class RenderContextTest < Rack::TestCase
- test "rendering using the controller as context" do
- get "/render_context/basic/hello_world"
- assert_body "Hello from controller context!"
- assert_status 200
- end
-
- test "rendering using the controller as context with layout" do
- get "/render_context/basic/with_layout"
- assert_body "?Hello from controller context!?"
- assert_status 200
- end
- end
-end
diff --git a/actionpack/test/controller/output_escaping_test.rb b/actionpack/test/controller/output_escaping_test.rb
index e33a99068f..d683bc73e6 100644
--- a/actionpack/test/controller/output_escaping_test.rb
+++ b/actionpack/test/controller/output_escaping_test.rb
@@ -4,7 +4,7 @@ require "abstract_unit"
class OutputEscapingTest < ActiveSupport::TestCase
test "escape_html shouldn't die when passed nil" do
- assert ERB::Util.h(nil).blank?
+ assert_predicate ERB::Util.h(nil), :blank?
end
test "escapeHTML should escape strings" do
diff --git a/actionpack/test/controller/parameters/accessors_test.rb b/actionpack/test/controller/parameters/accessors_test.rb
index 154430d4b0..7789e654d5 100644
--- a/actionpack/test/controller/parameters/accessors_test.rb
+++ b/actionpack/test/controller/parameters/accessors_test.rb
@@ -2,7 +2,6 @@
require "abstract_unit"
require "action_controller/metal/strong_parameters"
-require "active_support/core_ext/hash/transform_values"
class ParametersAccessorsTest < ActiveSupport::TestCase
setup do
@@ -22,13 +21,13 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
test "[] retains permitted status" do
@params.permit!
- assert @params[:person].permitted?
- assert @params[:person][:name].permitted?
+ assert_predicate @params[:person], :permitted?
+ assert_predicate @params[:person][:name], :permitted?
end
test "[] retains unpermitted status" do
- assert_not @params[:person].permitted?
- assert_not @params[:person][:name].permitted?
+ assert_not_predicate @params[:person], :permitted?
+ assert_not_predicate @params[:person][:name], :permitted?
end
test "as_json returns the JSON representation of the parameters hash" do
@@ -76,35 +75,57 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
end
end
+ test "each_value carries permitted status" do
+ @params.permit!
+ @params.each_value do |value|
+ assert_predicate(value, :permitted?)
+ end
+ end
+
+ test "each_value carries unpermitted status" do
+ @params.each_value do |value|
+ assert_not_predicate(value, :permitted?)
+ end
+ end
+
+ test "each_key converts to hash for permitted" do
+ @params.permit!
+ @params.each_key { |key| assert_kind_of(String, key) if key == "person" }
+ end
+
+ test "each_key converts to hash for unpermitted" do
+ @params.each_key { |key| assert_kind_of(String, key) if key == "person" }
+ end
+
test "empty? returns true when params contains no key/value pairs" do
params = ActionController::Parameters.new
- assert params.empty?
+ assert_empty params
end
test "empty? returns false when any params are present" do
- refute @params.empty?
+ assert_not_empty @params
end
test "except retains permitted status" do
@params.permit!
- assert @params.except(:person).permitted?
- assert @params[:person].except(:name).permitted?
+ assert_predicate @params.except(:person), :permitted?
+ assert_predicate @params[:person].except(:name), :permitted?
end
test "except retains unpermitted status" do
- assert_not @params.except(:person).permitted?
- assert_not @params[:person].except(:name).permitted?
+ assert_not_predicate @params.except(:person), :permitted?
+ assert_not_predicate @params[:person].except(:name), :permitted?
end
test "fetch retains permitted status" do
@params.permit!
- assert @params.fetch(:person).permitted?
- assert @params[:person].fetch(:name).permitted?
+ assert_predicate @params.fetch(:person), :permitted?
+ assert_predicate @params[:person].fetch(:name), :permitted?
end
test "fetch retains unpermitted status" do
- assert_not @params.fetch(:person).permitted?
- assert_not @params[:person].fetch(:name).permitted?
+ assert_not_predicate @params.fetch(:person), :permitted?
+ assert_not_predicate @params[:person].fetch(:name), :permitted?
end
test "has_key? returns true if the given key is present in the params" do
@@ -112,7 +133,7 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
end
test "has_key? returns false if the given key is not present in the params" do
- refute @params.has_key?(:address)
+ assert_not @params.has_key?(:address)
end
test "has_value? returns true if the given value is present in the params" do
@@ -122,7 +143,7 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
test "has_value? returns false if the given value is not present in the params" do
params = ActionController::Parameters.new(city: "Chicago", state: "Illinois")
- refute params.has_value?("New York")
+ assert_not params.has_value?("New York")
end
test "include? returns true if the given key is present in the params" do
@@ -130,7 +151,7 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
end
test "include? returns false if the given key is not present in the params" do
- refute @params.include?(:address)
+ assert_not @params.include?(:address)
end
test "key? returns true if the given key is present in the params" do
@@ -138,7 +159,7 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
end
test "key? returns false if the given key is not present in the params" do
- refute @params.key?(:address)
+ assert_not @params.key?(:address)
end
test "keys returns an array of the keys of the params" do
@@ -147,48 +168,69 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
end
test "reject retains permitted status" do
- assert_not @params.reject { |k| k == "person" }.permitted?
+ assert_not_predicate @params.reject { |k| k == "person" }, :permitted?
end
test "reject retains unpermitted status" do
@params.permit!
- assert @params.reject { |k| k == "person" }.permitted?
+ assert_predicate @params.reject { |k| k == "person" }, :permitted?
end
test "select retains permitted status" do
@params.permit!
- assert @params.select { |k| k == "person" }.permitted?
+ assert_predicate @params.select { |k| k == "person" }, :permitted?
end
test "select retains unpermitted status" do
- assert_not @params.select { |k| k == "person" }.permitted?
+ assert_not_predicate @params.select { |k| k == "person" }, :permitted?
end
test "slice retains permitted status" do
@params.permit!
- assert @params.slice(:person).permitted?
+ assert_predicate @params.slice(:person), :permitted?
end
test "slice retains unpermitted status" do
- assert_not @params.slice(:person).permitted?
+ assert_not_predicate @params.slice(:person), :permitted?
end
test "transform_keys retains permitted status" do
@params.permit!
- assert @params.transform_keys { |k| k }.permitted?
+ assert_predicate @params.transform_keys { |k| k }, :permitted?
end
test "transform_keys retains unpermitted status" do
- assert_not @params.transform_keys { |k| k }.permitted?
+ assert_not_predicate @params.transform_keys { |k| k }, :permitted?
end
test "transform_values retains permitted status" do
@params.permit!
- assert @params.transform_values { |v| v }.permitted?
+ assert_predicate @params.transform_values { |v| v }, :permitted?
end
test "transform_values retains unpermitted status" do
- assert_not @params.transform_values { |v| v }.permitted?
+ 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
@@ -198,7 +240,7 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
test "value? returns false if the given value is not present in the params" do
params = ActionController::Parameters.new(city: "Chicago", state: "Illinois")
- refute params.value?("New York")
+ assert_not params.value?("New York")
end
test "values returns an array of the values of the params" do
@@ -208,13 +250,13 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
test "values_at retains permitted status" do
@params.permit!
- assert @params.values_at(:person).first.permitted?
- assert @params[:person].values_at(:name).first.permitted?
+ assert_predicate @params.values_at(:person).first, :permitted?
+ assert_predicate @params[:person].values_at(:name).first, :permitted?
end
test "values_at retains unpermitted status" do
- assert_not @params.values_at(:person).first.permitted?
- assert_not @params[:person].values_at(:name).first.permitted?
+ assert_not_predicate @params.values_at(:person).first, :permitted?
+ assert_not_predicate @params[:person].values_at(:name).first, :permitted?
end
test "is equal to Parameters instance with same params" do
@@ -273,23 +315,24 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
assert_match(/permitted: true/, @params.inspect)
end
- if Hash.method_defined?(:dig)
- test "#dig delegates the dig method to its values" do
- assert_equal "David", @params.dig(:person, :name, :first)
- assert_equal "Chicago", @params.dig(:person, :addresses, 0, :city)
- end
+ test "#dig delegates the dig method to its values" do
+ assert_equal "David", @params.dig(:person, :name, :first)
+ assert_equal "Chicago", @params.dig(:person, :addresses, 0, :city)
+ end
- test "#dig converts hashes to parameters" do
- assert_kind_of ActionController::Parameters, @params.dig(:person)
- assert_kind_of ActionController::Parameters, @params.dig(:person, :addresses, 0)
- assert @params.dig(:person, :addresses).all? do |value|
- value.is_a?(ActionController::Parameters)
- end
- end
- else
- test "ActionController::Parameters does not respond to #dig on Ruby 2.2" do
- assert_not ActionController::Parameters.method_defined?(:dig)
- assert_not @params.respond_to?(:dig)
+ test "#dig converts hashes to parameters" do
+ assert_kind_of ActionController::Parameters, @params.dig(:person)
+ assert_kind_of ActionController::Parameters, @params.dig(:person, :addresses, 0)
+ assert @params.dig(:person, :addresses).all? do |value|
+ value.is_a?(ActionController::Parameters)
end
end
+
+ test "mutating #dig return value mutates underlying parameters" do
+ @params.dig(:person, :name)[:first] = "Bill"
+ assert_equal "Bill", @params.dig(:person, :name, :first)
+
+ @params.dig(:person, :addresses)[0] = { city: "Boston", state: "Massachusetts" }
+ assert_equal "Boston", @params.dig(:person, :addresses, 0, :city)
+ end
end
diff --git a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb
index 1e8b71d789..974612fb7b 100644
--- a/actionpack/test/controller/parameters/always_permitted_parameters_test.rb
+++ b/actionpack/test/controller/parameters/always_permitted_parameters_test.rb
@@ -20,11 +20,11 @@ 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")
permitted = params.permit book: [:pages]
- assert permitted.permitted?
+ assert_predicate permitted, :permitted?
end
end
diff --git a/actionpack/test/controller/parameters/dup_test.rb b/actionpack/test/controller/parameters/dup_test.rb
index f5833aff46..5403fc6d93 100644
--- a/actionpack/test/controller/parameters/dup_test.rb
+++ b/actionpack/test/controller/parameters/dup_test.rb
@@ -23,7 +23,7 @@ class ParametersDupTest < ActiveSupport::TestCase
test "a duplicate maintains the original's permitted status" do
@params.permit!
dupped_params = @params.dup
- assert dupped_params.permitted?
+ assert_predicate dupped_params, :permitted?
end
test "a duplicate maintains the original's parameters" do
@@ -57,11 +57,11 @@ class ParametersDupTest < ActiveSupport::TestCase
dupped_params = @params.deep_dup
dupped_params.permit!
- assert_not @params.permitted?
+ assert_not_predicate @params, :permitted?
end
test "deep_dup @permitted is being copied" do
@params.permit!
- assert @params.deep_dup.permitted?
+ assert_predicate @params.deep_dup, :permitted?
end
end
diff --git a/actionpack/test/controller/parameters/multi_parameter_attributes_test.rb b/actionpack/test/controller/parameters/multi_parameter_attributes_test.rb
index dcf848a620..c890839727 100644
--- a/actionpack/test/controller/parameters/multi_parameter_attributes_test.rb
+++ b/actionpack/test/controller/parameters/multi_parameter_attributes_test.rb
@@ -21,7 +21,7 @@ class MultiParameterAttributesTest < ActiveSupport::TestCase
permitted = params.permit book: [ :shipped_at, :price ]
- assert permitted.permitted?
+ assert_predicate permitted, :permitted?
assert_equal "2012", permitted[:book]["shipped_at(1i)"]
assert_equal "3", permitted[:book]["shipped_at(2i)"]
diff --git a/actionpack/test/controller/parameters/mutators_test.rb b/actionpack/test/controller/parameters/mutators_test.rb
index 49dede03c2..312b1e5b27 100644
--- a/actionpack/test/controller/parameters/mutators_test.rb
+++ b/actionpack/test/controller/parameters/mutators_test.rb
@@ -2,7 +2,6 @@
require "abstract_unit"
require "action_controller/metal/strong_parameters"
-require "active_support/core_ext/hash/transform_values"
class ParametersMutatorsTest < ActiveSupport::TestCase
setup do
@@ -20,11 +19,11 @@ class ParametersMutatorsTest < ActiveSupport::TestCase
test "delete retains permitted status" do
@params.permit!
- assert @params.delete(:person).permitted?
+ assert_predicate @params.delete(:person), :permitted?
end
test "delete retains unpermitted status" do
- assert_not @params.delete(:person).permitted?
+ assert_not_predicate @params.delete(:person), :permitted?
end
test "delete returns the value when the key is present" do
@@ -50,73 +49,73 @@ class ParametersMutatorsTest < ActiveSupport::TestCase
test "delete_if retains permitted status" do
@params.permit!
- assert @params.delete_if { |k| k == "person" }.permitted?
+ assert_predicate @params.delete_if { |k| k == "person" }, :permitted?
end
test "delete_if retains unpermitted status" do
- assert_not @params.delete_if { |k| k == "person" }.permitted?
+ assert_not_predicate @params.delete_if { |k| k == "person" }, :permitted?
end
test "extract! retains permitted status" do
@params.permit!
- assert @params.extract!(:person).permitted?
+ assert_predicate @params.extract!(:person), :permitted?
end
test "extract! retains unpermitted status" do
- assert_not @params.extract!(:person).permitted?
+ assert_not_predicate @params.extract!(:person), :permitted?
end
test "keep_if retains permitted status" do
@params.permit!
- assert @params.keep_if { |k, v| k == "person" }.permitted?
+ assert_predicate @params.keep_if { |k, v| k == "person" }, :permitted?
end
test "keep_if retains unpermitted status" do
- assert_not @params.keep_if { |k, v| k == "person" }.permitted?
+ assert_not_predicate @params.keep_if { |k, v| k == "person" }, :permitted?
end
test "reject! retains permitted status" do
@params.permit!
- assert @params.reject! { |k| k == "person" }.permitted?
+ assert_predicate @params.reject! { |k| k == "person" }, :permitted?
end
test "reject! retains unpermitted status" do
- assert_not @params.reject! { |k| k == "person" }.permitted?
+ assert_not_predicate @params.reject! { |k| k == "person" }, :permitted?
end
test "select! retains permitted status" do
@params.permit!
- assert @params.select! { |k| k != "person" }.permitted?
+ assert_predicate @params.select! { |k| k != "person" }, :permitted?
end
test "select! retains unpermitted status" do
- assert_not @params.select! { |k| k != "person" }.permitted?
+ assert_not_predicate @params.select! { |k| k != "person" }, :permitted?
end
test "slice! retains permitted status" do
@params.permit!
- assert @params.slice!(:person).permitted?
+ assert_predicate @params.slice!(:person), :permitted?
end
test "slice! retains unpermitted status" do
- assert_not @params.slice!(:person).permitted?
+ assert_not_predicate @params.slice!(:person), :permitted?
end
test "transform_keys! retains permitted status" do
@params.permit!
- assert @params.transform_keys! { |k| k }.permitted?
+ assert_predicate @params.transform_keys! { |k| k }, :permitted?
end
test "transform_keys! retains unpermitted status" do
- assert_not @params.transform_keys! { |k| k }.permitted?
+ assert_not_predicate @params.transform_keys! { |k| k }, :permitted?
end
test "transform_values! retains permitted status" do
@params.permit!
- assert @params.transform_values! { |v| v }.permitted?
+ assert_predicate @params.transform_values! { |v| v }, :permitted?
end
test "transform_values! retains unpermitted status" do
- assert_not @params.transform_values! { |v| v }.permitted?
+ assert_not_predicate @params.transform_values! { |v| v }, :permitted?
end
end
diff --git a/actionpack/test/controller/parameters/nested_parameters_permit_test.rb b/actionpack/test/controller/parameters/nested_parameters_permit_test.rb
index c9fcc483ee..1403e224c0 100644
--- a/actionpack/test/controller/parameters/nested_parameters_permit_test.rb
+++ b/actionpack/test/controller/parameters/nested_parameters_permit_test.rb
@@ -5,7 +5,7 @@ require "action_controller/metal/strong_parameters"
class NestedParametersPermitTest < ActiveSupport::TestCase
def assert_filtered_out(params, key)
- assert !params.has_key?(key), "key #{key.inspect} has not been filtered out"
+ assert_not params.has_key?(key), "key #{key.inspect} has not been filtered out"
end
test "permitted nested parameters" do
@@ -32,7 +32,7 @@ class NestedParametersPermitTest < ActiveSupport::TestCase
permitted = params.permit book: [ :title, { authors: [ :name ] }, { details: :pages }, :id ]
- assert permitted.permitted?
+ assert_predicate permitted, :permitted?
assert_equal "Romeo and Juliet", permitted[:book][:title]
assert_equal "William Shakespeare", permitted[:book][:authors][0][:name]
assert_equal "Christopher Marlowe", permitted[:book][:authors][1][:name]
diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb
index e9b94b056b..fbfe24059b 100644
--- a/actionpack/test/controller/parameters/parameters_permit_test.rb
+++ b/actionpack/test/controller/parameters/parameters_permit_test.rb
@@ -6,7 +6,7 @@ require "action_controller/metal/strong_parameters"
class ParametersPermitTest < ActiveSupport::TestCase
def assert_filtered_out(params, key)
- assert !params.has_key?(key), "key #{key.inspect} has not been filtered out"
+ assert_not params.has_key?(key), "key #{key.inspect} has not been filtered out"
end
setup do
@@ -53,8 +53,8 @@ class ParametersPermitTest < ActiveSupport::TestCase
test "if nothing is permitted, the hash becomes empty" do
params = ActionController::Parameters.new(id: "1234")
permitted = params.permit
- assert permitted.permitted?
- assert permitted.empty?
+ assert_predicate permitted, :permitted?
+ assert_empty permitted
end
test "key: permitted scalar values" do
@@ -136,7 +136,7 @@ class ParametersPermitTest < ActiveSupport::TestCase
test "key: it is not assigned if not present in params" do
params = ActionController::Parameters.new(name: "Joe")
permitted = params.permit(:id)
- assert !permitted.has_key?(:id)
+ assert_not permitted.has_key?(:id)
end
test "key to empty array: empty arrays pass" do
@@ -227,7 +227,7 @@ class ParametersPermitTest < ActiveSupport::TestCase
test "hashes in array values get wrapped" do
params = ActionController::Parameters.new(foo: [{}, {}])
params[:foo].each do |hash|
- assert !hash.permitted?
+ assert_not_predicate hash, :permitted?
end
end
@@ -250,7 +250,7 @@ class ParametersPermitTest < ActiveSupport::TestCase
permitted = params.permit(users: [:id])
permitted[:users] << { injected: 1 }
- assert_not permitted[:users].last.permitted?
+ assert_not_predicate permitted[:users].last, :permitted?
end
test "fetch doesnt raise ParameterMissing exception if there is a default" do
@@ -272,12 +272,12 @@ class ParametersPermitTest < ActiveSupport::TestCase
end
test "not permitted is sticky beyond merges" do
- assert !@params.merge(a: "b").permitted?
+ assert_not_predicate @params.merge(a: "b"), :permitted?
end
test "permitted is sticky beyond merges" do
@params.permit!
- assert @params.merge(a: "b").permitted?
+ assert_predicate @params.merge(a: "b"), :permitted?
end
test "merge with parameters" do
@@ -288,12 +288,12 @@ class ParametersPermitTest < ActiveSupport::TestCase
end
test "not permitted is sticky beyond merge!" do
- assert_not @params.merge!(a: "b").permitted?
+ assert_not_predicate @params.merge!(a: "b"), :permitted?
end
test "permitted is sticky beyond merge!" do
@params.permit!
- assert @params.merge!(a: "b").permitted?
+ assert_predicate @params.merge!(a: "b"), :permitted?
end
test "merge! with parameters" do
@@ -309,7 +309,7 @@ class ParametersPermitTest < ActiveSupport::TestCase
merged_params = @params.reverse_merge(default_params)
assert_equal "1234", merged_params[:id]
- refute_predicate merged_params[:person], :empty?
+ assert_not_predicate merged_params[:person], :empty?
end
test "#with_defaults is an alias of reverse_merge" do
@@ -317,11 +317,11 @@ class ParametersPermitTest < ActiveSupport::TestCase
merged_params = @params.with_defaults(default_params)
assert_equal "1234", merged_params[:id]
- refute_predicate merged_params[:person], :empty?
+ assert_not_predicate merged_params[:person], :empty?
end
test "not permitted is sticky beyond reverse_merge" do
- refute_predicate @params.reverse_merge(a: "b"), :permitted?
+ assert_not_predicate @params.reverse_merge(a: "b"), :permitted?
end
test "permitted is sticky beyond reverse_merge" do
@@ -334,7 +334,7 @@ class ParametersPermitTest < ActiveSupport::TestCase
@params.reverse_merge!(default_params)
assert_equal "1234", @params[:id]
- refute_predicate @params[:person], :empty?
+ assert_not_predicate @params[:person], :empty?
end
test "#with_defaults! is an alias of reverse_merge!" do
@@ -342,7 +342,7 @@ class ParametersPermitTest < ActiveSupport::TestCase
@params.with_defaults!(default_params)
assert_equal "1234", @params[:id]
- refute_predicate @params[:person], :empty?
+ assert_not_predicate @params[:person], :empty?
end
test "modifying the parameters" do
@@ -353,26 +353,27 @@ class ParametersPermitTest < ActiveSupport::TestCase
assert_equal "Jonas", @params[:person][:family][:brother]
end
- test "permit is recursive" do
+ test "permit! is recursive" do
+ @params[:nested_array] = [[{ x: 2, y: 3 }, { x: 21, y: 42 }]]
@params.permit!
- assert @params.permitted?
- assert @params[:person].permitted?
- assert @params[:person][:name].permitted?
- assert @params[:person][:addresses][0].permitted?
+ assert_predicate @params, :permitted?
+ assert_predicate @params[:person], :permitted?
+ assert_predicate @params[:person][:name], :permitted?
+ assert_predicate @params[:person][:addresses][0], :permitted?
+ assert_predicate @params[:nested_array][0][0], :permitted?
+ assert_predicate @params[:nested_array][0][1], :permitted?
end
test "permitted takes a default value when Parameters.permit_all_parameters is set" do
- begin
- ActionController::Parameters.permit_all_parameters = true
- params = ActionController::Parameters.new(person: {
- age: "32", name: { first: "David", last: "Heinemeier Hansson" }
- })
-
- assert params.slice(:person).permitted?
- assert params[:person][:name].permitted?
- ensure
- ActionController::Parameters.permit_all_parameters = false
- end
+ ActionController::Parameters.permit_all_parameters = true
+ params = ActionController::Parameters.new(person: {
+ age: "32", name: { first: "David", last: "Heinemeier Hansson" }
+ })
+
+ assert_predicate params.slice(:person), :permitted?
+ assert_predicate params[:person][:name], :permitted?
+ ensure
+ ActionController::Parameters.permit_all_parameters = false
end
test "permitting parameters as an array" do
@@ -393,16 +394,14 @@ class ParametersPermitTest < ActiveSupport::TestCase
end
test "to_h returns converted hash when .permit_all_parameters is set" do
- begin
- ActionController::Parameters.permit_all_parameters = true
- params = ActionController::Parameters.new(crab: "Senjougahara Hitagi")
-
- assert_instance_of ActiveSupport::HashWithIndifferentAccess, params.to_h
- assert_not_kind_of ActionController::Parameters, params.to_h
- assert_equal({ "crab" => "Senjougahara Hitagi" }, params.to_h)
- ensure
- ActionController::Parameters.permit_all_parameters = false
- end
+ ActionController::Parameters.permit_all_parameters = true
+ params = ActionController::Parameters.new(crab: "Senjougahara Hitagi")
+
+ assert_instance_of ActiveSupport::HashWithIndifferentAccess, params.to_h
+ assert_not_kind_of ActionController::Parameters, params.to_h
+ assert_equal({ "crab" => "Senjougahara Hitagi" }, params.to_h)
+ ensure
+ ActionController::Parameters.permit_all_parameters = false
end
test "to_hash raises UnfilteredParameters on unfiltered params" do
@@ -426,17 +425,15 @@ class ParametersPermitTest < ActiveSupport::TestCase
end
test "to_hash returns converted hash when .permit_all_parameters is set" do
- begin
- ActionController::Parameters.permit_all_parameters = true
- params = ActionController::Parameters.new(crab: "Senjougahara Hitagi")
-
- assert_instance_of Hash, params.to_hash
- assert_not_kind_of ActionController::Parameters, params.to_hash
- assert_equal({ "crab" => "Senjougahara Hitagi" }, params.to_hash)
- assert_equal({ "crab" => "Senjougahara Hitagi" }, params)
- ensure
- ActionController::Parameters.permit_all_parameters = false
- end
+ ActionController::Parameters.permit_all_parameters = true
+ params = ActionController::Parameters.new(crab: "Senjougahara Hitagi")
+
+ assert_instance_of Hash, params.to_hash
+ assert_not_kind_of ActionController::Parameters, params.to_hash
+ assert_equal({ "crab" => "Senjougahara Hitagi" }, params.to_hash)
+ assert_equal({ "crab" => "Senjougahara Hitagi" }, params)
+ ensure
+ ActionController::Parameters.permit_all_parameters = false
end
test "to_unsafe_h returns unfiltered params" do
@@ -500,9 +497,9 @@ class ParametersPermitTest < ActiveSupport::TestCase
params = ActionController::Parameters.new(foo: "bar")
assert params.permit(:foo).has_key?(:foo)
- refute params.permit(foo: []).has_key?(:foo)
- refute params.permit(foo: [:bar]).has_key?(:foo)
- refute params.permit(foo: :bar).has_key?(:foo)
+ assert_not params.permit(foo: []).has_key?(:foo)
+ assert_not params.permit(foo: [:bar]).has_key?(:foo)
+ assert_not params.permit(foo: :bar).has_key?(:foo)
end
test "#permitted? is false by default" do
diff --git a/actionpack/test/controller/parameters/serialization_test.rb b/actionpack/test/controller/parameters/serialization_test.rb
index 823f01d82a..7708c8e4fe 100644
--- a/actionpack/test/controller/parameters/serialization_test.rb
+++ b/actionpack/test/controller/parameters/serialization_test.rb
@@ -2,7 +2,6 @@
require "abstract_unit"
require "action_controller/metal/strong_parameters"
-require "active_support/core_ext/string/strip"
class ParametersSerializationTest < ActiveSupport::TestCase
setup do
@@ -27,21 +26,21 @@ class ParametersSerializationTest < ActiveSupport::TestCase
roundtripped = YAML.load(YAML.dump(params))
assert_equal params, roundtripped
- assert_not roundtripped.permitted?
+ assert_not_predicate roundtripped, :permitted?
end
test "yaml backwardscompatible with psych 2.0.8 format" do
- params = YAML.load <<-end_of_yaml.strip_heredoc
+ params = YAML.load <<~end_of_yaml
--- !ruby/hash:ActionController::Parameters
key: :value
end_of_yaml
assert_equal :value, params[:key]
- assert_not params.permitted?
+ assert_not_predicate params, :permitted?
end
test "yaml backwardscompatible with psych 2.0.9+ format" do
- params = YAML.load(<<-end_of_yaml.strip_heredoc)
+ params = YAML.load(<<~end_of_yaml)
--- !ruby/hash-with-ivars:ActionController::Parameters
elements:
key: :value
@@ -50,6 +49,6 @@ class ParametersSerializationTest < ActiveSupport::TestCase
end_of_yaml
assert_equal :value, params[:key]
- assert_not params.permitted?
+ assert_not_predicate params, :permitted?
end
end
diff --git a/actionpack/test/controller/params_parse_test.rb b/actionpack/test/controller/params_parse_test.rb
new file mode 100644
index 0000000000..440ab06fd7
--- /dev/null
+++ b/actionpack/test/controller/params_parse_test.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+
+class ParamsParseTest < ActionController::TestCase
+ class UsersController < ActionController::Base
+ def create
+ head :ok
+ end
+ end
+
+ tests UsersController
+
+ def test_parse_error_logged_once
+ log_output = capture_log_output do
+ post :create, body: "{", as: :json
+ end
+ assert_equal <<~LOG, log_output
+ Error occurred while parsing request parameters.
+ Contents:
+
+ {
+ LOG
+ end
+
+ private
+
+ def capture_log_output
+ output = StringIO.new
+ request.set_header "action_dispatch.logger", ActiveSupport::Logger.new(output)
+ yield
+ output.string
+ end
+end
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index 2959dc3e4d..7f1c41787a 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)
@@ -62,10 +68,18 @@ class RedirectController < ActionController::Base
redirect_back(fallback_location: "/things/stuff", status: 307)
end
+ def redirect_back_with_status_and_fallback_location_to_another_host
+ redirect_back(fallback_location: "http://www.rubyonrails.org/", status: 307)
+ end
+
def safe_redirect_back_with_status
redirect_back(fallback_location: "/things/stuff", status: 307, allow_other_host: false)
end
+ def safe_redirect_back_with_status_and_fallback_location_to_another_host
+ redirect_back(fallback_location: "http://www.rubyonrails.org/", status: 307, allow_other_host: false)
+ end
+
def host_redirect
redirect_to action: "other_host", only_path: false, host: "other.test.host"
end
@@ -119,6 +133,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
@@ -204,6 +222,13 @@ class RedirectTest < ActionController::TestCase
assert_equal "http://test.host/things/stuff", redirect_to_url
end
+ def test_relative_url_redirect_host_with_port
+ request.host = "test.host:1234"
+ get :relative_url_redirect_with_status
+ assert_response 302
+ assert_equal "http://test.host:1234/things/stuff", redirect_to_url
+ end
+
def test_simple_redirect_using_options
get :host_redirect
assert_response :redirect
@@ -263,6 +288,13 @@ class RedirectTest < ActionController::TestCase
assert_equal "http://test.host/things/stuff", redirect_to_url
end
+ def test_redirect_back_with_no_referer_redirects_to_another_host
+ get :redirect_back_with_status_and_fallback_location_to_another_host
+
+ assert_response 307
+ assert_equal "http://www.rubyonrails.org/", redirect_to_url
+ end
+
def test_safe_redirect_back_from_other_host
@request.env["HTTP_REFERER"] = "http://another.host/coming/from"
get :safe_redirect_back_with_status
@@ -280,6 +312,20 @@ class RedirectTest < ActionController::TestCase
assert_equal referer, redirect_to_url
end
+ def test_safe_redirect_back_with_no_referer
+ get :safe_redirect_back_with_status
+
+ assert_response 307
+ assert_equal "http://test.host/things/stuff", redirect_to_url
+ end
+
+ def test_safe_redirect_back_with_no_referer_redirects_to_another_host
+ get :safe_redirect_back_with_status_and_fallback_location_to_another_host
+
+ assert_response 307
+ assert_equal "http://www.rubyonrails.org/", redirect_to_url
+ end
+
def test_redirect_to_record
with_routing do |set|
set.draw do
@@ -326,6 +372,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 7c5101f993..4750093c5c 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"
@@ -173,6 +183,11 @@ class TestController < ActionController::Base
render action: "hello_world"
end
+ def conditional_hello_without_expires_and_public_header
+ response.headers["Cache-Control"] = "public, no-cache"
+ render action: "hello_world"
+ end
+
def conditional_hello_with_bangs
render action: "hello_world"
end
@@ -240,6 +255,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 +382,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"]
@@ -389,6 +423,11 @@ class ExpiresInRenderTest < ActionController::TestCase
assert_equal "no-cache", @response.headers["Cache-Control"]
end
+ def test_no_expires_now_with_public
+ get :conditional_hello_without_expires_and_public_header
+ assert_equal "public, no-cache", @response.headers["Cache-Control"]
+ end
+
def test_date_header_when_expires_in
time = Time.mktime(2011, 10, 30)
Time.stub :now, time do
@@ -415,7 +454,7 @@ class LastModifiedRenderTest < ActionController::TestCase
@request.if_modified_since = @last_modified
get :conditional_hello
assert_equal 304, @response.status.to_i
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_equal @last_modified, @response.headers["Last-Modified"]
end
@@ -430,7 +469,7 @@ class LastModifiedRenderTest < ActionController::TestCase
@request.if_modified_since = "Thu, 16 Jul 2008 00:00:00 GMT"
get :conditional_hello
assert_equal 200, @response.status.to_i
- assert @response.body.present?
+ assert_predicate @response.body, :present?
assert_equal @last_modified, @response.headers["Last-Modified"]
end
@@ -443,7 +482,7 @@ class LastModifiedRenderTest < ActionController::TestCase
@request.if_modified_since = @last_modified
get :conditional_hello_with_record
assert_equal 304, @response.status.to_i
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_not_nil @response.etag
assert_equal @last_modified, @response.headers["Last-Modified"]
end
@@ -459,7 +498,7 @@ class LastModifiedRenderTest < ActionController::TestCase
@request.if_modified_since = "Thu, 16 Jul 2008 00:00:00 GMT"
get :conditional_hello_with_record
assert_equal 200, @response.status.to_i
- assert @response.body.present?
+ assert_predicate @response.body, :present?
assert_equal @last_modified, @response.headers["Last-Modified"]
end
@@ -472,7 +511,7 @@ class LastModifiedRenderTest < ActionController::TestCase
@request.if_modified_since = @last_modified
get :conditional_hello_with_collection_of_records
assert_equal 304, @response.status.to_i
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_equal @last_modified, @response.headers["Last-Modified"]
end
@@ -487,7 +526,7 @@ class LastModifiedRenderTest < ActionController::TestCase
@request.if_modified_since = "Thu, 16 Jul 2008 00:00:00 GMT"
get :conditional_hello_with_collection_of_records
assert_equal 200, @response.status.to_i
- assert @response.body.present?
+ assert_predicate @response.body, :present?
assert_equal @last_modified, @response.headers["Last-Modified"]
end
@@ -650,7 +689,7 @@ class ImplicitRenderTest < ActionController::TestCase
tests ImplicitRenderTestController
def test_implicit_no_content_response_as_browser
- assert_raises(ActionController::UnknownFormat) do
+ assert_raises(ActionController::MissingExactTemplate) do
get :empty_action
end
end
@@ -682,27 +721,27 @@ class HeadRenderTest < ActionController::TestCase
def test_head_created
post :head_created
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_response :created
end
def test_head_created_with_application_json_content_type
post :head_created_with_application_json_content_type
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_equal "application/json", @response.header["Content-Type"]
assert_response :created
end
def test_head_ok_with_image_png_content_type
post :head_ok_with_image_png_content_type
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_equal "image/png", @response.header["Content-Type"]
assert_response :ok
end
def test_head_with_location_header
get :head_with_location_header
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_equal "/foo", @response.headers["Location"]
assert_response :ok
end
@@ -718,7 +757,7 @@ class HeadRenderTest < ActionController::TestCase
end
get :head_with_location_object
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"]
assert_response :ok
end
@@ -726,14 +765,14 @@ class HeadRenderTest < ActionController::TestCase
def test_head_with_custom_header
get :head_with_custom_header
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_equal "something", @response.headers["X-Custom-Header"]
assert_response :ok
end
def test_head_with_www_authenticate_header
get :head_with_www_authenticate_header
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
assert_equal "something", @response.headers["WWW-Authenticate"]
assert_response :ok
end
@@ -794,6 +833,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
@@ -812,7 +856,7 @@ class HttpCacheForeverTest < ActionController::TestCase
assert_response :ok
assert_equal "max-age=#{100.years}, public", @response.headers["Cache-Control"]
assert_not_nil @response.etag
- assert @response.weak_etag?
+ assert_predicate @response, :weak_etag?
end
def test_cache_with_private
@@ -820,7 +864,7 @@ class HttpCacheForeverTest < ActionController::TestCase
assert_response :ok
assert_equal "max-age=#{100.years}, private", @response.headers["Cache-Control"]
assert_not_nil @response.etag
- assert @response.weak_etag?
+ assert_predicate @response, :weak_etag?
end
def test_cache_response_code_with_if_modified_since
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index 4822d85bcb..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
@@ -746,7 +751,7 @@ class FreeCookieControllerTest < ActionController::TestCase
test "should not emit a csrf-token meta tag" do
SecureRandom.stub :base64, @token do
get :meta
- assert @response.body.blank?
+ assert_predicate @response.body, :blank?
end
end
end
diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb
index 4ed79073e5..089b0b94d4 100644
--- a/actionpack/test/controller/rescue_test.rb
+++ b/actionpack/test/controller/rescue_test.rb
@@ -62,12 +62,8 @@ class RescueController < ActionController::Base
render plain: exception.message
end
- rescue_from ActionView::TemplateError do
- render plain: "action_view templater error"
- end
-
- rescue_from IOError do
- render plain: "io error"
+ rescue_from ActionDispatch::Http::Parameters::ParseError do
+ render plain: "parse error", status: :bad_request
end
before_action(only: :before_action_raises) { raise "umm nice" }
@@ -75,19 +71,6 @@ class RescueController < ActionController::Base
def before_action_raises
end
- def raises
- render plain: "already rendered"
- raise "don't panic!"
- end
-
- def method_not_allowed
- raise ActionController::MethodNotAllowed.new(:get, :head, :put)
- end
-
- def not_implemented
- raise ActionController::NotImplemented.new(:get, :put)
- end
-
def not_authorized
raise NotAuthorized
end
@@ -130,6 +113,11 @@ class RescueController < ActionController::Base
raise ResourceUnavailableToRescueAsString
end
+ def arbitrary_action
+ params
+ render plain: "arbitrary action"
+ end
+
def missing_template
end
@@ -306,6 +294,23 @@ class RescueControllerTest < ActionController::TestCase
get :exception_with_no_handler_for_wrapper
assert_response :unprocessable_entity
end
+
+ test "can rescue a ParseError" do
+ capture_log_output do
+ post :arbitrary_action, body: "{", as: :json
+ end
+ assert_response :bad_request
+ assert_equal "parse error", response.body
+ end
+
+ private
+
+ def capture_log_output
+ output = StringIO.new
+ request.set_header "action_dispatch.logger", ActiveSupport::Logger.new(output)
+ yield
+ output.string
+ end
end
class RescueTest < ActionDispatch::IntegrationTest
@@ -325,10 +330,6 @@ class RescueTest < ActionDispatch::IntegrationTest
raise RecordInvalid
end
- def b00m
- raise "b00m"
- end
-
private
def show_errors(exception)
render plain: exception.message
@@ -356,7 +357,6 @@ class RescueTest < ActionDispatch::IntegrationTest
set.draw do
get "foo", to: ::RescueTest::TestController.action(:foo)
get "invalid", to: ::RescueTest::TestController.action(:invalid)
- get "b00m", to: ::RescueTest::TestController.action(:b00m)
end
yield
end
diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb
index 30bea64c55..d2146f12a5 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
@@ -854,6 +853,28 @@ class ResourcesTest < ActionController::TestCase
end
end
+ def test_resource_has_show_action_but_does_not_have_destroy_action
+ with_routing do |set|
+ set.draw do
+ resources :products, only: [:show, :destroy], except: :destroy
+ end
+
+ assert_resource_allowed_routes("products", {}, { id: "1" }, :show, [:index, :new, :create, :edit, :update, :destroy])
+ assert_resource_allowed_routes("products", { format: "xml" }, { id: "1" }, :show, [:index, :new, :create, :edit, :update, :destroy])
+ end
+ end
+
+ def test_singleton_resource_has_show_action_but_does_not_have_destroy_action
+ with_routing do |set|
+ set.draw do
+ resource :account, only: [:show, :destroy], except: :destroy
+ end
+
+ assert_singleton_resource_allowed_routes("accounts", {}, :show, [:new, :create, :edit, :update, :destroy])
+ assert_singleton_resource_allowed_routes("accounts", { format: "xml" }, :show, [:new, :create, :edit, :update, :destroy])
+ end
+ end
+
def test_resource_has_only_create_action_and_named_route
with_routing do |set|
set.draw do
@@ -1323,7 +1344,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 +1358,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 ec939e946a..b378bb80b8 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -23,10 +23,10 @@ class UriReservedCharactersRoutingTest < ActiveSupport::TestCase
end
safe, unsafe = %w(: @ & = + $ , ;), %w(^ ? # [ ])
- hex = unsafe.map { |char| "%" + char.unpack("H2").first.upcase }
+ hex = unsafe.map { |char| "%" + char.unpack1("H2").upcase }
- @segment = "#{safe.join}#{unsafe.join}".freeze
- @escaped = "#{safe.join}#{hex.join}".freeze
+ @segment = "#{safe.join}#{unsafe.join}"
+ @escaped = "#{safe.join}#{hex.join}"
end
def test_route_generation_escapes_unsafe_path_characters
@@ -309,7 +309,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def test_specific_controller_action_failure
rs.draw do
- mount lambda {} => "/foo"
+ mount lambda { } => "/foo"
end
assert_raises(ActionController::UrlGenerationError) do
@@ -355,10 +355,10 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
rs.draw { ActiveSupport::Deprecation.silence { get "/:controller/:action", action: /auth[-|_].+/ } }
assert_equal({ action: "auth_google", controller: "content" }, rs.recognize_path("/content/auth_google"))
- assert_equal({ action: "auth-facebook", controller: "content" }, rs.recognize_path("/content/auth-facebook"))
+ assert_equal({ action: "auth-twitter", controller: "content" }, rs.recognize_path("/content/auth-twitter"))
assert_equal "/content/auth_google", url_for(rs, controller: "content", action: "auth_google")
- assert_equal "/content/auth-facebook", url_for(rs, controller: "content", action: "auth-facebook")
+ assert_equal "/content/auth-twitter", url_for(rs, controller: "content", action: "auth-twitter")
end
def test_route_with_regexp_for_controller
@@ -674,9 +674,9 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
assert_equal "/page/foo", url_for(rs, controller: "content", action: "show_page", id: "foo")
assert_equal({ controller: "content", action: "show_page", id: "foo" }, rs.recognize_path("/page/foo"))
- token = "\321\202\320\265\320\272\321\201\321\202".dup # 'text' in Russian
+ token = +"\321\202\320\265\320\272\321\201\321\202" # 'text' in Russian
token.force_encoding(Encoding::BINARY)
- escaped_token = CGI::escape(token)
+ escaped_token = CGI.escape(token)
assert_equal "/page/" + escaped_token, url_for(rs, controller: "content", action: "show_page", id: token)
assert_equal({ controller: "content", action: "show_page", id: token }, rs.recognize_path("/page/#{escaped_token}"))
@@ -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
@@ -1288,14 +1287,14 @@ class RouteSetTest < ActiveSupport::TestCase
end
def test_routing_traversal_does_not_load_extra_classes
- assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
+ assert_not Object.const_defined?("Profiler__"), "Profiler should not be loaded"
set.draw do
get "/profile" => "profile#index"
end
request_path_params("/profile") rescue nil
- assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
+ assert_not Object.const_defined?("Profiler__"), "Profiler should not be loaded"
end
def test_recognize_with_conditions_and_format
@@ -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/runner_test.rb b/actionpack/test/controller/runner_test.rb
index a96c9c519b..1709ab5f6d 100644
--- a/actionpack/test/controller/runner_test.rb
+++ b/actionpack/test/controller/runner_test.rb
@@ -17,8 +17,8 @@ module ActionDispatch
def test_respond_to?
runner = MyRunner.new(Class.new { def x; end }.new)
- assert runner.respond_to?(:hi)
- assert runner.respond_to?(:x)
+ assert_respond_to runner, :hi
+ assert_respond_to runner, :x
end
end
end
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 7b1a52b277..c917cdf761 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -144,7 +144,7 @@ class SendFileTest < ActionController::TestCase
get :test_send_file_headers_bang
assert_equal "image/png", response.content_type
- assert_equal 'disposition; filename="filename"', response.get_header("Content-Disposition")
+ assert_equal %(disposition; filename="filename"; filename*=UTF-8''filename), response.get_header("Content-Disposition")
assert_equal "binary", response.get_header("Content-Transfer-Encoding")
assert_equal "private", response.get_header("Cache-Control")
end
@@ -153,7 +153,7 @@ class SendFileTest < ActionController::TestCase
def test_send_file_headers_with_disposition_as_a_symbol
get :test_send_file_headers_with_disposition_as_a_symbol
- assert_equal 'disposition; filename="filename"', response.get_header("Content-Disposition")
+ assert_equal %(disposition; filename="filename"; filename*=UTF-8''filename), response.get_header("Content-Disposition")
end
def test_send_file_headers_with_mime_lookup_with_symbol
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index 536c5ed97a..d1cd190747 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -156,6 +156,10 @@ XML
render html: '<body class="foo"></body>'.html_safe
end
+ def render_json
+ render json: request.raw_post
+ end
+
def boom
raise "boom!"
end
@@ -223,6 +227,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 +405,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
@@ -447,6 +478,18 @@ XML
)
end
+ def test_nil_params
+ get :test_params, params: nil
+ parsed_params = JSON.parse(@response.body)
+ assert_equal(
+ {
+ "action" => "test_params",
+ "controller" => "test_case_test/test"
+ },
+ parsed_params
+ )
+ end
+
def test_query_param_named_action
get :test_query_parameters, params: { action: "foobar" }
parsed_params = JSON.parse(@response.body)
@@ -515,7 +558,7 @@ XML
def test_params_passing_with_frozen_values
assert_nothing_raised do
get :test_params, params: {
- frozen: "icy".freeze, frozens: ["icy".freeze].freeze, deepfreeze: { frozen: "icy".freeze }.freeze
+ frozen: -"icy", frozens: [-"icy"].freeze, deepfreeze: { frozen: -"icy" }.freeze
}
end
parsed_params = ::JSON.parse(@response.body)
@@ -670,7 +713,7 @@ XML
assert_equal "bar", @request.params[:foo]
post :no_op
- assert @request.params[:foo].blank?
+ assert_predicate @request.params[:foo], :blank?
end
def test_filtered_parameters_reset_between_requests
@@ -681,6 +724,22 @@ XML
assert_equal "baz", @request.filtered_parameters[:foo]
end
+ def test_raw_post_reset_between_post_requests
+ post :no_op, params: { foo: "bar" }
+ assert_equal "foo=bar", @request.raw_post
+
+ post :no_op, params: { foo: "baz" }
+ assert_equal "foo=baz", @request.raw_post
+ end
+
+ def test_content_length_reset_after_post_request
+ post :no_op, params: { foo: "bar" }
+ assert_not_equal 0, @request.content_length
+
+ get :no_op
+ assert_equal 0, @request.content_length
+ end
+
def test_path_is_kept_after_the_request
get :test_params, params: { id: "foo" }
assert_equal "/test_case_test/test/test_params/foo", @request.path
@@ -740,6 +799,14 @@ XML
assert_equal "application/json", @response.body
end
+ def test_request_format_kwarg_doesnt_mutate_params
+ params = { foo: "bar" }.freeze
+
+ assert_nothing_raised do
+ get :test_format, format: "json", params: params
+ end
+ end
+
def test_should_have_knowledge_of_client_side_cookie_state_even_if_they_are_not_set
cookies["foo"] = "bar"
get :no_op
@@ -838,7 +905,7 @@ XML
def test_fixture_file_upload_should_be_able_access_to_tempfile
file = fixture_file_upload(FILES_DIR + "/ruby_on_rails.jpg", "image/jpg")
- assert file.respond_to?(:tempfile), "expected tempfile should respond on fixture file object, got nothing"
+ assert_respond_to file, :tempfile
end
def test_fixture_file_upload
@@ -914,6 +981,16 @@ XML
assert_equal "q=test2", @response.body
end
+
+ def test_parsed_body_without_as_option
+ post :render_json, body: { foo: "heyo" }
+ assert_equal({ "foo" => "heyo" }, response.parsed_body)
+ end
+
+ def test_parsed_body_with_as_option
+ post :render_json, body: { foo: "heyo" }.to_json, as: :json
+ assert_equal({ "foo" => "heyo" }, response.parsed_body)
+ end
end
class ResponseDefaultHeadersTest < ActionController::TestCase
diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb
index cf11227897..9222250b9c 100644
--- a/actionpack/test/controller/url_for_test.rb
+++ b/actionpack/test/controller/url_for_test.rb
@@ -288,7 +288,7 @@ module AbstractController
kls = Class.new { include set.url_helpers }
controller = kls.new
- assert controller.respond_to?(:home_url)
+ assert_respond_to controller, :home_url
assert_equal "http://www.basecamphq.com/home/sweet/home/again",
controller.send(:home_url, host: "www.basecamphq.com", user: "again")
@@ -354,6 +354,14 @@ module AbstractController
assert_equal({ p2: "Y2" }.to_query, params[1])
end
+ def test_params_option
+ url = W.new.url_for(only_path: true, controller: "c", action: "a", params: { domain: "foo", id: "1" })
+ params = extract_params(url)
+ assert_equal("/c/a?domain=foo&id=1", url)
+ assert_equal({ domain: "foo" }.to_query, params[0])
+ assert_equal({ id: "1" }.to_query, params[1])
+ end
+
def test_hash_parameter
url = W.new.url_for(only_path: true, controller: "c", action: "a", query: { name: "Bob", category: "prof" })
params = extract_params(url)
diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb
index 4a10637b54..23a46df5cd 100644
--- a/actionpack/test/controller/webservice_test.rb
+++ b/actionpack/test/controller/webservice_test.rb
@@ -14,7 +14,7 @@ class WebServiceTest < ActionDispatch::IntegrationTest
end
def dump_params_keys(hash = params)
- hash.keys.sort.inject("") do |s, k|
+ hash.keys.sort.each_with_object(+"") do |k, s|
value = hash[k]
if value.is_a?(Hash) || value.is_a?(ActionController::Parameters)
@@ -23,8 +23,8 @@ class WebServiceTest < ActionDispatch::IntegrationTest
value = ""
end
- s += ", " unless s.empty?
- s += "#{k}#{value}"
+ s << ", " unless s.empty?
+ s << "#{k}#{value}"
end
end
end
diff --git a/actionpack/test/dispatch/content_disposition_test.rb b/actionpack/test/dispatch/content_disposition_test.rb
new file mode 100644
index 0000000000..3f5959da6e
--- /dev/null
+++ b/actionpack/test/dispatch/content_disposition_test.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+
+module ActionDispatch
+ class ContentDispositionTest < ActiveSupport::TestCase
+ test "encoding a Latin filename" do
+ disposition = Http::ContentDisposition.new(disposition: :inline, filename: "racecar.jpg")
+
+ assert_equal %(filename="racecar.jpg"), disposition.ascii_filename
+ assert_equal "filename*=UTF-8''racecar.jpg", disposition.utf8_filename
+ assert_equal "inline; #{disposition.ascii_filename}; #{disposition.utf8_filename}", disposition.to_s
+ end
+
+ test "encoding a Latin filename with accented characters" do
+ disposition = Http::ContentDisposition.new(disposition: :inline, filename: "råcëçâr.jpg")
+
+ assert_equal %(filename="racecar.jpg"), disposition.ascii_filename
+ assert_equal "filename*=UTF-8''r%C3%A5c%C3%AB%C3%A7%C3%A2r.jpg", disposition.utf8_filename
+ assert_equal "inline; #{disposition.ascii_filename}; #{disposition.utf8_filename}", disposition.to_s
+ end
+
+ test "encoding a non-Latin filename" do
+ disposition = Http::ContentDisposition.new(disposition: :inline, filename: "автомобиль.jpg")
+
+ assert_equal %(filename="%3F%3F%3F%3F%3F%3F%3F%3F%3F%3F.jpg"), disposition.ascii_filename
+ assert_equal "filename*=UTF-8''%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%BE%D0%B1%D0%B8%D0%BB%D1%8C.jpg", disposition.utf8_filename
+ assert_equal "inline; #{disposition.ascii_filename}; #{disposition.utf8_filename}", disposition.to_s
+ end
+
+ test "without filename" do
+ disposition = Http::ContentDisposition.new(disposition: :inline, filename: nil)
+
+ assert_equal "inline", disposition.to_s
+ end
+ end
+end
diff --git a/actionpack/test/dispatch/content_security_policy_test.rb b/actionpack/test/dispatch/content_security_policy_test.rb
index 7c4a65a633..c8c885f35c 100644
--- a/actionpack/test/dispatch/content_security_policy_test.rb
+++ b/actionpack/test/dispatch/content_security_policy_test.rb
@@ -8,10 +8,10 @@ class ContentSecurityPolicyTest < ActiveSupport::TestCase
end
def test_build
- assert_equal ";", @policy.build
+ assert_equal "", @policy.build
@policy.script_src :self
- assert_equal "script-src 'self';", @policy.build
+ assert_equal "script-src 'self'", @policy.build
end
def test_dup
@@ -25,34 +25,40 @@ class ContentSecurityPolicyTest < ActiveSupport::TestCase
def test_mappings
@policy.script_src :data
- assert_equal "script-src data:;", @policy.build
+ assert_equal "script-src data:", @policy.build
@policy.script_src :mediastream
- assert_equal "script-src mediastream:;", @policy.build
+ assert_equal "script-src mediastream:", @policy.build
@policy.script_src :blob
- assert_equal "script-src blob:;", @policy.build
+ assert_equal "script-src blob:", @policy.build
@policy.script_src :filesystem
- assert_equal "script-src filesystem:;", @policy.build
+ assert_equal "script-src filesystem:", @policy.build
@policy.script_src :self
- assert_equal "script-src 'self';", @policy.build
+ assert_equal "script-src 'self'", @policy.build
@policy.script_src :unsafe_inline
- assert_equal "script-src 'unsafe-inline';", @policy.build
+ assert_equal "script-src 'unsafe-inline'", @policy.build
@policy.script_src :unsafe_eval
- assert_equal "script-src 'unsafe-eval';", @policy.build
+ assert_equal "script-src 'unsafe-eval'", @policy.build
@policy.script_src :none
- assert_equal "script-src 'none';", @policy.build
+ assert_equal "script-src 'none'", @policy.build
@policy.script_src :strict_dynamic
- assert_equal "script-src 'strict-dynamic';", @policy.build
+ assert_equal "script-src 'strict-dynamic'", @policy.build
+
+ @policy.script_src :ws
+ assert_equal "script-src ws:", @policy.build
+
+ @policy.script_src :wss
+ assert_equal "script-src wss:", @policy.build
@policy.script_src :none, :report_sample
- assert_equal "script-src 'none' 'report-sample';", @policy.build
+ assert_equal "script-src 'none' 'report-sample'", @policy.build
end
def test_fetch_directives
@@ -110,6 +116,12 @@ class ContentSecurityPolicyTest < ActiveSupport::TestCase
@policy.object_src false
assert_no_match %r{object-src}, @policy.build
+ @policy.prefetch_src :self
+ assert_match %r{prefetch-src 'self'}, @policy.build
+
+ @policy.prefetch_src false
+ assert_no_match %r{prefetch-src}, @policy.build
+
@policy.script_src :self
assert_match %r{script-src 'self'}, @policy.build
@@ -131,16 +143,16 @@ class ContentSecurityPolicyTest < ActiveSupport::TestCase
def test_document_directives
@policy.base_uri "https://example.com"
- assert_match %r{base-uri https://example\.com;}, @policy.build
+ assert_match %r{base-uri https://example\.com}, @policy.build
@policy.plugin_types "application/x-shockwave-flash"
- assert_match %r{plugin-types application/x-shockwave-flash;}, @policy.build
+ assert_match %r{plugin-types application/x-shockwave-flash}, @policy.build
@policy.sandbox
- assert_match %r{sandbox;}, @policy.build
+ assert_match %r{sandbox}, @policy.build
@policy.sandbox "allow-scripts", "allow-modals"
- assert_match %r{sandbox allow-scripts allow-modals;}, @policy.build
+ assert_match %r{sandbox allow-scripts allow-modals}, @policy.build
@policy.sandbox false
assert_no_match %r{sandbox}, @policy.build
@@ -148,35 +160,35 @@ class ContentSecurityPolicyTest < ActiveSupport::TestCase
def test_navigation_directives
@policy.form_action :self
- assert_match %r{form-action 'self';}, @policy.build
+ assert_match %r{form-action 'self'}, @policy.build
@policy.frame_ancestors :self
- assert_match %r{frame-ancestors 'self';}, @policy.build
+ assert_match %r{frame-ancestors 'self'}, @policy.build
end
def test_reporting_directives
@policy.report_uri "/violations"
- assert_match %r{report-uri /violations;}, @policy.build
+ assert_match %r{report-uri /violations}, @policy.build
end
def test_other_directives
@policy.block_all_mixed_content
- assert_match %r{block-all-mixed-content;}, @policy.build
+ assert_match %r{block-all-mixed-content}, @policy.build
@policy.block_all_mixed_content false
assert_no_match %r{block-all-mixed-content}, @policy.build
@policy.require_sri_for :script, :style
- assert_match %r{require-sri-for script style;}, @policy.build
+ assert_match %r{require-sri-for script style}, @policy.build
@policy.require_sri_for "script", "style"
- assert_match %r{require-sri-for script style;}, @policy.build
+ assert_match %r{require-sri-for script style}, @policy.build
@policy.require_sri_for
assert_no_match %r{require-sri-for}, @policy.build
@policy.upgrade_insecure_requests
- assert_match %r{upgrade-insecure-requests;}, @policy.build
+ assert_match %r{upgrade-insecure-requests}, @policy.build
@policy.upgrade_insecure_requests false
assert_no_match %r{upgrade-insecure-requests}, @policy.build
@@ -184,26 +196,28 @@ class ContentSecurityPolicyTest < ActiveSupport::TestCase
def test_multiple_sources
@policy.script_src :self, :https
- assert_equal "script-src 'self' https:;", @policy.build
+ assert_equal "script-src 'self' https:", @policy.build
end
def test_multiple_directives
@policy.script_src :self, :https
@policy.style_src :self, :https
- assert_equal "script-src 'self' https:; style-src 'self' https:;", @policy.build
+ assert_equal "script-src 'self' https:; style-src 'self' https:", @policy.build
end
def test_dynamic_directives
- request = Struct.new(:host).new("www.example.com")
+ request = ActionDispatch::Request.new("HTTP_HOST" => "www.example.com")
controller = Struct.new(:request).new(request)
@policy.script_src -> { request.host }
- assert_equal "script-src www.example.com;", @policy.build(controller)
+ assert_equal "script-src www.example.com", @policy.build(controller)
end
def test_mixed_static_and_dynamic_directives
@policy.script_src :self, -> { "foo.com" }, "bar.com"
- assert_equal "script-src 'self' foo.com bar.com;", @policy.build(Object.new)
+ request = ActionDispatch::Request.new({})
+ controller = Struct.new(:request).new(request)
+ assert_equal "script-src 'self' foo.com bar.com", @policy.build(controller)
end
def test_invalid_directive_source
@@ -235,6 +249,79 @@ class ContentSecurityPolicyTest < ActiveSupport::TestCase
end
end
+class DefaultContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
+ class PolicyController < ActionController::Base
+ def index
+ head :ok
+ end
+ end
+
+ ROUTES = ActionDispatch::Routing::RouteSet.new
+ ROUTES.draw do
+ scope module: "default_content_security_policy_integration_test" do
+ get "/", to: "policy#index"
+ get "/redirect", to: redirect("/")
+ end
+ end
+
+ POLICY = ActionDispatch::ContentSecurityPolicy.new do |p|
+ p.default_src -> { :self }
+ p.script_src -> { :https }
+ end
+
+ class PolicyConfigMiddleware
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ env["action_dispatch.content_security_policy"] = POLICY
+ env["action_dispatch.content_security_policy_nonce_generator"] = proc { "iyhD0Yc0W+c=" }
+ env["action_dispatch.content_security_policy_report_only"] = false
+ env["action_dispatch.show_exceptions"] = false
+
+ @app.call(env)
+ end
+ end
+
+ APP = build_app(ROUTES) do |middleware|
+ middleware.use PolicyConfigMiddleware
+ middleware.use ActionDispatch::ContentSecurityPolicy::Middleware
+ end
+
+ def app
+ APP
+ end
+
+ def test_adds_nonce_to_script_src_content_security_policy_only_once
+ get "/"
+ get "/"
+ assert_response :success
+ assert_policy "default-src 'self'; script-src https: 'nonce-iyhD0Yc0W+c='"
+ end
+
+ def test_redirect_works_with_dynamic_sources
+ get "/redirect"
+ assert_response :redirect
+ assert_policy "default-src 'self'; script-src https: 'nonce-iyhD0Yc0W+c='"
+ end
+
+ private
+
+ def assert_policy(expected, report_only: false)
+ if report_only
+ expected_header = "Content-Security-Policy-Report-Only"
+ unexpected_header = "Content-Security-Policy"
+ else
+ expected_header = "Content-Security-Policy"
+ unexpected_header = "Content-Security-Policy-Report-Only"
+ end
+
+ assert_nil response.headers[unexpected_header]
+ assert_equal expected, response.headers[expected_header]
+ end
+end
+
class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
class PolicyController < ActionController::Base
content_security_policy only: :inline do |p|
@@ -253,6 +340,18 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
p.report_uri "/violations"
end
+ content_security_policy only: :script_src do |p|
+ p.default_src false
+ p.script_src :self
+ end
+
+ content_security_policy only: :style_src do |p|
+ p.default_src false
+ p.style_src :self
+ end
+
+ content_security_policy(false, only: :no_policy)
+
content_security_policy_report_only only: :report_only
def index
@@ -271,6 +370,18 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
head :ok
end
+ def script_src
+ head :ok
+ end
+
+ def style_src
+ head :ok
+ end
+
+ def no_policy
+ head :ok
+ end
+
private
def condition?
params[:condition] == "true"
@@ -284,6 +395,9 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
get "/inline", to: "policy#inline"
get "/conditional", to: "policy#conditional"
get "/report-only", to: "policy#report_only"
+ get "/script-src", to: "policy#script_src"
+ get "/style-src", to: "policy#style_src"
+ get "/no-policy", to: "policy#no_policy"
end
end
@@ -298,6 +412,7 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
def call(env)
env["action_dispatch.content_security_policy"] = POLICY
+ env["action_dispatch.content_security_policy_nonce_generator"] = proc { "iyhD0Yc0W+c=" }
env["action_dispatch.content_security_policy_report_only"] = false
env["action_dispatch.show_exceptions"] = false
@@ -316,40 +431,45 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
def test_generates_content_security_policy_header
get "/"
- assert_policy "default-src 'self';"
+ assert_policy "default-src 'self'"
end
def test_generates_inline_content_security_policy
get "/inline"
- assert_policy "default-src https://example.com;"
+ assert_policy "default-src https://example.com"
end
def test_generates_conditional_content_security_policy
get "/conditional", params: { condition: "true" }
- assert_policy "default-src https://true.example.com;"
+ assert_policy "default-src https://true.example.com"
get "/conditional", params: { condition: "false" }
- assert_policy "default-src https://false.example.com;"
+ assert_policy "default-src https://false.example.com"
end
def test_generates_report_only_content_security_policy
get "/report-only"
- assert_policy "default-src 'self'; report-uri /violations;", report_only: true
+ assert_policy "default-src 'self'; report-uri /violations", report_only: true
end
- private
+ def test_adds_nonce_to_script_src_content_security_policy
+ get "/script-src"
+ assert_policy "script-src 'self' 'nonce-iyhD0Yc0W+c='"
+ end
- def env_config
- Rails.application.env_config
- end
+ def test_adds_nonce_to_style_src_content_security_policy
+ get "/style-src"
+ assert_policy "style-src 'self' 'nonce-iyhD0Yc0W+c='"
+ end
- def content_security_policy
- env_config["action_dispatch.content_security_policy"]
- end
+ def test_generates_no_content_security_policy
+ get "/no-policy"
- def content_security_policy=(policy)
- env_config["action_dispatch.content_security_policy"] = policy
- end
+ assert_nil response.headers["Content-Security-Policy"]
+ assert_nil response.headers["Content-Security-Policy-Report-Only"]
+ end
+
+ private
def assert_policy(expected, report_only: false)
assert_response :success
@@ -366,3 +486,61 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
assert_equal expected, response.headers[expected_header]
end
end
+
+class DisabledContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
+ class PolicyController < ActionController::Base
+ content_security_policy only: :inline do |p|
+ p.default_src "https://example.com"
+ end
+
+ def index
+ head :ok
+ end
+
+ def inline
+ head :ok
+ end
+ end
+
+ ROUTES = ActionDispatch::Routing::RouteSet.new
+ ROUTES.draw do
+ scope module: "disabled_content_security_policy_integration_test" do
+ get "/", to: "policy#index"
+ get "/inline", to: "policy#inline"
+ end
+ end
+
+ class PolicyConfigMiddleware
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ env["action_dispatch.content_security_policy"] = nil
+ env["action_dispatch.content_security_policy_nonce_generator"] = nil
+ env["action_dispatch.content_security_policy_report_only"] = false
+ env["action_dispatch.show_exceptions"] = false
+
+ @app.call(env)
+ end
+ end
+
+ APP = build_app(ROUTES) do |middleware|
+ middleware.use PolicyConfigMiddleware
+ middleware.use ActionDispatch::ContentSecurityPolicy::Middleware
+ end
+
+ def app
+ APP
+ end
+
+ def test_generates_no_content_security_policy_by_default
+ get "/"
+ assert_nil response.headers["Content-Security-Policy"]
+ end
+
+ def test_generates_content_security_policy_header_when_globally_disabled
+ get "/inline"
+ assert_equal "default-src https://example.com", response.headers["Content-Security-Policy"]
+ end
+end
diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb
index 40cbad3b0d..4aaac1320e 100644
--- a/actionpack/test/dispatch/cookies_test.rb
+++ b/actionpack/test/dispatch/cookies_test.rb
@@ -36,6 +36,12 @@ class CookieJarTest < ActiveSupport::TestCase
assert_equal "bar", request.cookie_jar.fetch(:foo)
end
+ def test_to_hash
+ request.cookie_jar["foo"] = "bar"
+ assert_equal({ "foo" => "bar" }, request.cookie_jar.to_hash)
+ assert_equal({ "foo" => "bar" }, request.cookie_jar.to_h)
+ end
+
def test_fetch_type_error
assert_raises(KeyError) do
request.cookie_jar.fetch(:omglolwut)
@@ -59,8 +65,8 @@ class CookieJarTest < ActiveSupport::TestCase
end
def test_key_methods
- assert !request.cookie_jar.key?(:foo)
- assert !request.cookie_jar.has_key?("foo")
+ assert_not request.cookie_jar.key?(:foo)
+ assert_not request.cookie_jar.has_key?("foo")
request.cookie_jar[:foo] = :bar
assert request.cookie_jar.key?(:foo)
@@ -283,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
@@ -319,7 +365,7 @@ class CookiesTest < ActionController::TestCase
def test_setting_the_same_value_to_cookie
request.cookies[:user_name] = "david"
get :authenticate
- assert_predicate response.cookies, :empty?
+ assert_empty response.cookies
end
def test_setting_the_same_value_to_permanent_cookie
@@ -401,7 +447,7 @@ class CookiesTest < ActionController::TestCase
def test_delete_unexisting_cookie
request.cookies.clear
get :delete_cookie
- assert_predicate @response.cookies, :empty?
+ assert_empty @response.cookies
end
def test_deleted_cookie_predicate
@@ -479,21 +525,6 @@ class CookiesTest < ActionController::TestCase
assert_equal 45, verifier.verify(@response.cookies["user_id"])
end
- def test_signed_cookie_with_legacy_secret_scheme
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
-
- old_message = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33", digest: "SHA1", serializer: Marshal).generate(45)
-
- @request.headers["Cookie"] = "user_id=#{old_message}"
- get :get_signed_cookie
- assert_equal 45, @controller.send(:cookies).signed[:user_id]
-
- key_generator = @request.env["action_dispatch.key_generator"]
- secret = key_generator.generate_key("signed cookie")
- verifier = ActiveSupport::MessageVerifier.new(secret, digest: "SHA1", serializer: Marshal)
- assert_equal 45, verifier.verify(@response.cookies["user_id"])
- end
-
def test_tampered_with_signed_cookie
key_generator = @request.env["action_dispatch.key_generator"]
secret = key_generator.generate_key(@request.env["action_dispatch.signed_cookie_salt"])
@@ -713,175 +744,7 @@ class CookiesTest < ActionController::TestCase
assert_equal ["user_name", "user_id"], @request.cookie_jar.instance_variable_get(:@cookies).keys
end
- def test_raises_argument_error_if_missing_secret
- assert_raise(ArgumentError, nil.inspect) {
- @request.env["action_dispatch.key_generator"] = ActiveSupport::LegacyKeyGenerator.new(nil)
- get :set_signed_cookie
- }
-
- assert_raise(ArgumentError, "".inspect) {
- @request.env["action_dispatch.key_generator"] = ActiveSupport::LegacyKeyGenerator.new("")
- get :set_signed_cookie
- }
- end
-
- def test_raises_argument_error_if_secret_is_probably_insecure
- assert_raise(ArgumentError, "password".inspect) {
- @request.env["action_dispatch.key_generator"] = ActiveSupport::LegacyKeyGenerator.new("password")
- get :set_signed_cookie
- }
-
- assert_raise(ArgumentError, "secret".inspect) {
- @request.env["action_dispatch.key_generator"] = ActiveSupport::LegacyKeyGenerator.new("secret")
- get :set_signed_cookie
- }
-
- assert_raise(ArgumentError, "12345678901234567890123456789".inspect) {
- @request.env["action_dispatch.key_generator"] = ActiveSupport::LegacyKeyGenerator.new("12345678901234567890123456789")
- get :set_signed_cookie
- }
- end
-
- def test_legacy_signed_cookie_is_read_and_transparently_upgraded_by_signed_cookie_jar_if_both_secret_token_and_secret_key_base_are_set
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
-
- legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33").generate(45)
-
- @request.headers["Cookie"] = "user_id=#{legacy_value}"
- get :get_signed_cookie
-
- assert_equal 45, @controller.send(:cookies).signed[:user_id]
-
- key_generator = @request.env["action_dispatch.key_generator"]
- secret = key_generator.generate_key(@request.env["action_dispatch.signed_cookie_salt"])
- verifier = ActiveSupport::MessageVerifier.new(secret)
- assert_equal 45, verifier.verify(@response.cookies["user_id"])
- end
-
- def test_legacy_signed_cookie_is_read_and_transparently_encrypted_by_encrypted_cookie_jar_if_both_secret_token_and_secret_key_base_are_set
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
-
- legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33").generate("bar")
-
- @request.headers["Cookie"] = "foo=#{legacy_value}"
- get :get_encrypted_cookie
-
- assert_equal "bar", @controller.send(:cookies).encrypted[:foo]
-
- secret = @request.env["action_dispatch.key_generator"].generate_key(@request.env["action_dispatch.authenticated_encrypted_cookie_salt"], 32)
- encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm", serializer: Marshal)
- assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
- end
-
- def test_legacy_json_signed_cookie_is_read_and_transparently_upgraded_by_signed_json_cookie_jar_if_both_secret_token_and_secret_key_base_are_set
- @request.env["action_dispatch.cookies_serializer"] = :json
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
-
- legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33", serializer: JSON).generate(45)
-
- @request.headers["Cookie"] = "user_id=#{legacy_value}"
- get :get_signed_cookie
-
- assert_equal 45, @controller.send(:cookies).signed[:user_id]
-
- key_generator = @request.env["action_dispatch.key_generator"]
- secret = key_generator.generate_key(@request.env["action_dispatch.signed_cookie_salt"])
- verifier = ActiveSupport::MessageVerifier.new(secret, serializer: JSON)
- assert_equal 45, verifier.verify(@response.cookies["user_id"])
- end
-
- def test_legacy_json_signed_cookie_is_read_and_transparently_encrypted_by_encrypted_json_cookie_jar_if_both_secret_token_and_secret_key_base_are_set
- @request.env["action_dispatch.cookies_serializer"] = :json
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
-
- legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33", serializer: JSON).generate("bar")
-
- @request.headers["Cookie"] = "foo=#{legacy_value}"
- get :get_encrypted_cookie
-
- assert_equal "bar", @controller.send(:cookies).encrypted[:foo]
-
- cipher = "aes-256-gcm"
- salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
- secret = @request.env["action_dispatch.key_generator"].generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len(cipher)]
- encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: JSON)
- assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
- end
-
- def test_legacy_json_signed_cookie_is_read_and_transparently_upgraded_by_signed_json_hybrid_jar_if_both_secret_token_and_secret_key_base_are_set
- @request.env["action_dispatch.cookies_serializer"] = :hybrid
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
-
- legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33", serializer: JSON).generate(45)
-
- @request.headers["Cookie"] = "user_id=#{legacy_value}"
- get :get_signed_cookie
-
- assert_equal 45, @controller.send(:cookies).signed[:user_id]
-
- key_generator = @request.env["action_dispatch.key_generator"]
- secret = key_generator.generate_key(@request.env["action_dispatch.signed_cookie_salt"])
- verifier = ActiveSupport::MessageVerifier.new(secret, serializer: JSON)
- assert_equal 45, verifier.verify(@response.cookies["user_id"])
- end
-
- def test_legacy_json_signed_cookie_is_read_and_transparently_encrypted_by_encrypted_hybrid_cookie_jar_if_both_secret_token_and_secret_key_base_are_set
- @request.env["action_dispatch.cookies_serializer"] = :hybrid
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
-
- legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33", serializer: JSON).generate("bar")
-
- @request.headers["Cookie"] = "foo=#{legacy_value}"
- get :get_encrypted_cookie
-
- assert_equal "bar", @controller.send(:cookies).encrypted[:foo]
-
- salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
- secret = @request.env["action_dispatch.key_generator"].generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len("aes-256-gcm")]
- encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm", serializer: JSON)
- assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
- end
-
- def test_legacy_marshal_signed_cookie_is_read_and_transparently_upgraded_by_signed_json_hybrid_jar_if_both_secret_token_and_secret_key_base_are_set
- @request.env["action_dispatch.cookies_serializer"] = :hybrid
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
-
- legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33").generate(45)
-
- @request.headers["Cookie"] = "user_id=#{legacy_value}"
- get :get_signed_cookie
-
- assert_equal 45, @controller.send(:cookies).signed[:user_id]
-
- key_generator = @request.env["action_dispatch.key_generator"]
- secret = key_generator.generate_key(@request.env["action_dispatch.signed_cookie_salt"])
- verifier = ActiveSupport::MessageVerifier.new(secret, serializer: JSON)
- assert_equal 45, verifier.verify(@response.cookies["user_id"])
- end
-
- def test_legacy_marshal_signed_cookie_is_read_and_transparently_encrypted_by_encrypted_hybrid_cookie_jar_if_both_secret_token_and_secret_key_base_are_set
- @request.env["action_dispatch.cookies_serializer"] = :hybrid
-
- @request.env["action_dispatch.use_authenticated_cookie_encryption"] = true
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
- @request.env["action_dispatch.secret_key_base"] = "c3b95688f35581fad38df788add315ff"
-
- legacy_value = ActiveSupport::MessageVerifier.new("b3c631c314c0bbca50c1b2843150fe33").generate("bar")
-
- @request.headers["Cookie"] = "foo=#{legacy_value}"
- get :get_encrypted_cookie
-
- assert_equal "bar", @controller.send(:cookies).encrypted[:foo]
-
- salt = @request.env["action_dispatch.authenticated_encrypted_cookie_salt"]
- secret = @request.env["action_dispatch.key_generator"].generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len("aes-256-gcm")]
- encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: "aes-256-gcm", serializer: JSON)
- assert_equal "bar", encryptor.decrypt_and_verify(@response.cookies["foo"])
- end
-
def test_legacy_signed_cookie_is_treated_as_nil_by_signed_cookie_jar_if_tampered
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
-
@request.headers["Cookie"] = "user_id=45"
get :get_signed_cookie
@@ -890,8 +753,6 @@ class CookiesTest < ActionController::TestCase
end
def test_legacy_signed_cookie_is_treated_as_nil_by_encrypted_cookie_jar_if_tampered
- @request.env["action_dispatch.secret_token"] = "b3c631c314c0bbca50c1b2843150fe33"
-
@request.headers["Cookie"] = "foo=baz"
get :get_encrypted_cookie
@@ -1268,6 +1129,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
@@ -1278,6 +1141,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
@@ -1294,6 +1159,117 @@ 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_nil cookies.signed[:user_id]
+ 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_nil cookies.signed[:user_id]
+ 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 60acba0616..6914fb66f9 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -3,10 +3,12 @@
require "abstract_unit"
class DebugExceptionsTest < ActionDispatch::IntegrationTest
+ InterceptedErrorInstance = StandardError.new
+
class Boomer
attr_accessor :closed
- def initialize(detailed = false)
+ def initialize(detailed = false)
@detailed = detailed
@closed = false
end
@@ -24,61 +26,83 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
raise StandardError.new "error in framework"
end
+ def raise_nested_exceptions
+ raise "First error"
+ rescue
+ begin
+ raise "Second error"
+ rescue
+ raise "Third error"
+ end
+ end
+
def call(env)
env["action_dispatch.show_detailed_exceptions"] = @detailed
req = ActionDispatch::Request.new(env)
+ template = ActionView::Template.new(File.read(__FILE__), __FILE__, ActionView::Template::Handlers::Raw.new, {})
+
case req.path
- when %r{/pass}
+ when "/pass"
[404, { "X-Cascade" => "pass" }, self]
- when %r{/not_found}
+ when "/not_found"
raise AbstractController::ActionNotFound
- when %r{/runtime_error}
+ when "/runtime_error"
raise RuntimeError
- when %r{/method_not_allowed}
+ when "/method_not_allowed"
raise ActionController::MethodNotAllowed
- when %r{/unknown_http_method}
+ when "/intercepted_error"
+ raise InterceptedErrorInstance
+ when "/unknown_http_method"
raise ActionController::UnknownHttpMethod
- when %r{/not_implemented}
+ when "/not_implemented"
raise ActionController::NotImplemented
- when %r{/unprocessable_entity}
+ when "/unprocessable_entity"
raise ActionController::InvalidAuthenticityToken
- when %r{/not_found_original_exception}
+ when "/not_found_original_exception"
begin
raise AbstractController::ActionNotFound.new
rescue
- raise ActionView::Template::Error.new("template")
+ raise ActionView::Template::Error.new(template)
end
- when %r{/missing_template}
+ when "/cause_mapped_to_rescue_responses"
+ begin
+ raise ActionController::ParameterMissing, :missing_param_key
+ rescue
+ raise NameError.new("uninitialized constant Userr")
+ end
+ when "/missing_template"
raise ActionView::MissingTemplate.new(%w(foo), "foo/index", %w(foo), false, "mailer")
- when %r{/bad_request}
+ when "/bad_request"
raise ActionController::BadRequest
- when %r{/missing_keys}
+ when "/missing_keys"
raise ActionController::UrlGenerationError, "No route matches"
- when %r{/parameter_missing}
+ when "/parameter_missing"
raise ActionController::ParameterMissing, :missing_param_key
- when %r{/original_syntax_error}
+ when "/original_syntax_error"
eval "broke_syntax =" # `eval` need for raise native SyntaxError at runtime
- when %r{/syntax_error_into_view}
+ when "/syntax_error_into_view"
begin
eval "broke_syntax ="
rescue Exception
- template = ActionView::Template.new(File.read(__FILE__),
- __FILE__,
- ActionView::Template::Handlers::Raw.new,
- {})
raise ActionView::Template::Error.new(template)
end
- when %r{/framework_raises}
+ when "/framework_raises"
method_that_raises
+ when "/nested_exceptions"
+ raise_nested_exceptions
else
raise "puke!"
end
end
end
+ Interceptor = proc { |request, exception| request.set_header("int", exception) }
+ BadInterceptor = proc { |request, exception| raise "bad" }
RoutesApp = Struct.new(:routes).new(SharedTestRoutes)
ProductionApp = ActionDispatch::DebugExceptions.new(Boomer.new(false), RoutesApp)
DevelopmentApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp)
+ InterceptedApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :default, [Interceptor])
+ BadInterceptedApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :default, [BadInterceptor])
test "skip diagnosis if not showing detailed exceptions" do
@app = ProductionApp
@@ -268,22 +292,20 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
end
test "rescue with JSON format as fallback if API request format is not supported" do
- begin
- Mime::Type.register "text/wibble", :wibble
+ Mime::Type.register "text/wibble", :wibble
- ActionDispatch::IntegrationTest.register_encoder(:wibble,
- param_encoder: -> params { params })
+ ActionDispatch::IntegrationTest.register_encoder(:wibble,
+ param_encoder: -> params { params })
- @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
+ @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
- get "/index", headers: { "action_dispatch.show_exceptions" => true }, as: :wibble
- assert_response 500
- assert_equal "application/json", response.content_type
- assert_match(/RuntimeError: puke/, body)
+ get "/index", headers: { "action_dispatch.show_exceptions" => true }, as: :wibble
+ assert_response 500
+ assert_equal "application/json", response.content_type
+ assert_match(/RuntimeError: puke/, body)
- ensure
- Mime::Type.unregister :wibble
- end
+ ensure
+ Mime::Type.unregister :wibble
end
test "does not show filtered parameters" do
@@ -295,12 +317,22 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
assert_match("&quot;foo&quot;=&gt;&quot;[FILTERED]&quot;", body)
end
- test "show registered original exception for wrapped exceptions" do
+ test "show registered original exception if the last exception is TemplateError" do
@app = DevelopmentApp
get "/not_found_original_exception", headers: { "action_dispatch.show_exceptions" => true }
assert_response 404
- assert_match(/AbstractController::ActionNotFound/, body)
+ assert_match %r{AbstractController::ActionNotFound}, body
+ assert_match %r{Showing <i>.*test/dispatch/debug_exceptions_test.rb</i>}, body
+ end
+
+ test "show the last exception and cause even when the cause is mapped to resque_responses" do
+ @app = DevelopmentApp
+
+ get "/cause_mapped_to_rescue_responses", headers: { "action_dispatch.show_exceptions" => true }
+ assert_response 500
+ assert_match %r{ActionController::ParameterMissing}, body
+ assert_match %r{NameError}, body
end
test "named urls missing keys raise 500 level error" do
@@ -346,7 +378,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
})
assert_response 500
- assert_includes(body, CGI.escapeHTML(PP.pp(params, "".dup, 200)))
+ assert_includes(body, CGI.escapeHTML(PP.pp(params, +"", 200)))
end
test "sets the HTTP charset parameter" do
@@ -432,8 +464,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
@@ -446,9 +478,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
@@ -459,9 +491,10 @@ 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
+ assert_match %r{Showing <i>.*test/dispatch/debug_exceptions_test.rb</i>}, body
end
test "debug exceptions app shows user code that caused the error in source view" do
@@ -489,13 +522,64 @@ 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
+
+ test "invoke interceptors before rendering" do
+ @app = InterceptedApp
+ get "/intercepted_error", headers: { "action_dispatch.show_exceptions" => true }
+
+ assert_equal InterceptedErrorInstance, request.get_header("int")
+ end
+
+ test "bad interceptors doesn't debug exceptions" do
+ @app = BadInterceptedApp
+
+ get "/puke", headers: { "action_dispatch.show_exceptions" => true }
+
+ 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
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/executor_test.rb b/actionpack/test/dispatch/executor_test.rb
index 8eb6450385..5b8be39b6d 100644
--- a/actionpack/test/dispatch/executor_test.rb
+++ b/actionpack/test/dispatch/executor_test.rb
@@ -81,7 +81,7 @@ class ExecutorTest < ActiveSupport::TestCase
running = false
body.close
- assert !running
+ assert_not running
end
def test_complete_callbacks_are_called_on_close
@@ -89,7 +89,7 @@ class ExecutorTest < ActiveSupport::TestCase
executor.to_complete { completed = true }
body = call_and_return_body
- assert !completed
+ assert_not completed
body.close
assert completed
@@ -116,7 +116,7 @@ class ExecutorTest < ActiveSupport::TestCase
call_and_return_body.close
assert result
- assert !defined?(@in_shared_context) # it's not in the test itself
+ assert_not defined?(@in_shared_context) # it's not in the test itself
end
private
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/host_authorization_test.rb b/actionpack/test/dispatch/host_authorization_test.rb
new file mode 100644
index 0000000000..5263dd2597
--- /dev/null
+++ b/actionpack/test/dispatch/host_authorization_test.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+require "ipaddr"
+
+class HostAuthorizationTest < ActionDispatch::IntegrationTest
+ App = -> env { [200, {}, %w(Success)] }
+
+ test "blocks requests to unallowed host" do
+ @app = ActionDispatch::HostAuthorization.new(App, %w(only.com))
+
+ get "/"
+
+ assert_response :forbidden
+ assert_match "Blocked host: www.example.com", response.body
+ end
+
+ test "allows all requests if hosts is empty" do
+ @app = ActionDispatch::HostAuthorization.new(App, nil)
+
+ get "/"
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+
+ test "hosts can be a single element array" do
+ @app = ActionDispatch::HostAuthorization.new(App, %w(www.example.com))
+
+ get "/"
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+
+ test "hosts can be a string" do
+ @app = ActionDispatch::HostAuthorization.new(App, "www.example.com")
+
+ get "/"
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+
+ test "passes requests to allowed hosts with domain name notation" do
+ @app = ActionDispatch::HostAuthorization.new(App, ".example.com")
+
+ get "/"
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+
+ test "does not allow domain name notation in the HOST header itself" do
+ @app = ActionDispatch::HostAuthorization.new(App, ".example.com")
+
+ get "/", env: {
+ "HOST" => ".example.com",
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: .example.com", response.body
+ end
+
+ test "checks for requests with #=== to support wider range of host checks" do
+ @app = ActionDispatch::HostAuthorization.new(App, [-> input { input == "www.example.com" }])
+
+ get "/"
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+
+ test "mark the host when authorized" do
+ @app = ActionDispatch::HostAuthorization.new(App, ".example.com")
+
+ get "/"
+
+ assert_equal "www.example.com", request.get_header("action_dispatch.authorized_host")
+ end
+
+ test "sanitizes regular expressions to prevent accidental matches" do
+ @app = ActionDispatch::HostAuthorization.new(App, [/w.example.co/])
+
+ get "/"
+
+ assert_response :forbidden
+ assert_match "Blocked host: www.example.com", response.body
+ end
+
+ test "blocks requests to unallowed host supporting custom responses" do
+ @app = ActionDispatch::HostAuthorization.new(App, ["w.example.co"], -> env do
+ [401, {}, %w(Custom)]
+ end)
+
+ get "/"
+
+ assert_response :unauthorized
+ assert_equal "Custom", body
+ end
+
+ test "blocks requests with spoofed X-FORWARDED-HOST" do
+ @app = ActionDispatch::HostAuthorization.new(App, [IPAddr.new("127.0.0.1")])
+
+ get "/", env: {
+ "HTTP_X_FORWARDED_HOST" => "127.0.0.1",
+ "HOST" => "www.example.com",
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: 127.0.0.1", response.body
+ end
+
+ test "does not consider IP addresses in X-FORWARDED-HOST spoofed when disabled" do
+ @app = ActionDispatch::HostAuthorization.new(App, nil)
+
+ get "/", env: {
+ "HTTP_X_FORWARDED_HOST" => "127.0.0.1",
+ "HOST" => "www.example.com",
+ }
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+
+ test "detects localhost domain spoofing" do
+ @app = ActionDispatch::HostAuthorization.new(App, "localhost")
+
+ get "/", env: {
+ "HTTP_X_FORWARDED_HOST" => "localhost",
+ "HOST" => "www.example.com",
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: localhost", response.body
+ end
+
+ test "forwarded hosts should be permitted" do
+ @app = ActionDispatch::HostAuthorization.new(App, "domain.com")
+
+ get "/", env: {
+ "HTTP_X_FORWARDED_HOST" => "sub.domain.com",
+ "HOST" => "domain.com",
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: sub.domain.com", response.body
+ end
+
+ test "forwarded hosts are allowed when permitted" do
+ @app = ActionDispatch::HostAuthorization.new(App, ".domain.com")
+
+ get "/", env: {
+ "HTTP_X_FORWARDED_HOST" => "sub.domain.com",
+ "HOST" => "domain.com",
+ }
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+end
diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb
index 2901148a9e..b673fd3805 100644
--- a/actionpack/test/dispatch/live_response_test.rb
+++ b/actionpack/test/dispatch/live_response_test.rb
@@ -62,7 +62,7 @@ module ActionController
assert_nil @response.headers["Content-Length"]
end
- def test_headers_cannot_be_written_after_webserver_reads
+ def test_headers_cannot_be_written_after_web_server_reads
@response.stream.write "omg"
latch = Concurrent::CountDownLatch.new
@@ -73,7 +73,7 @@ module ActionController
}
latch.wait
- assert @response.headers.frozen?
+ assert_predicate @response.headers, :frozen?
e = assert_raises(ActionDispatch::IllegalStateError) do
@response.headers["Content-Length"] = "zomg"
end
diff --git a/actionpack/test/dispatch/middleware_stack_test.rb b/actionpack/test/dispatch/middleware_stack_test.rb
index e9f7ad41dd..5f43e5a3c5 100644
--- a/actionpack/test/dispatch/middleware_stack_test.rb
+++ b/actionpack/test/dispatch/middleware_stack_test.rb
@@ -42,7 +42,7 @@ class MiddlewareStackTest < ActiveSupport::TestCase
end
test "use should push middleware class with block arguments onto the stack" do
- proc = Proc.new {}
+ proc = Proc.new { }
assert_difference "@stack.size" do
@stack.use(BlockMiddleware, &proc)
end
diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb
index 6854783386..45d91883c0 100644
--- a/actionpack/test/dispatch/mime_type_test.rb
+++ b/actionpack/test/dispatch/mime_type_test.rb
@@ -96,57 +96,47 @@ class MimeTypeTest < ActiveSupport::TestCase
end
test "custom type" do
- begin
- type = Mime::Type.register("image/foo", :foo)
- assert_equal type, Mime[:foo]
- ensure
- Mime::Type.unregister(:foo)
- end
+ type = Mime::Type.register("image/foo", :foo)
+ assert_equal type, Mime[:foo]
+ ensure
+ Mime::Type.unregister(:foo)
end
test "custom type with type aliases" do
- begin
- Mime::Type.register "text/foobar", :foobar, ["text/foo", "text/bar"]
- %w[text/foobar text/foo text/bar].each do |type|
- assert_equal Mime[:foobar], type
- end
- ensure
- Mime::Type.unregister(:foobar)
+ Mime::Type.register "text/foobar", :foobar, ["text/foo", "text/bar"]
+ %w[text/foobar text/foo text/bar].each do |type|
+ assert_equal Mime[:foobar], type
end
+ ensure
+ Mime::Type.unregister(:foobar)
end
test "register callbacks" do
- begin
- registered_mimes = []
- Mime::Type.register_callback do |mime|
- registered_mimes << mime
- end
-
- mime = Mime::Type.register("text/foo", :foo)
- assert_equal [mime], registered_mimes
- ensure
- Mime::Type.unregister(:foo)
+ registered_mimes = []
+ Mime::Type.register_callback do |mime|
+ registered_mimes << mime
end
+
+ mime = Mime::Type.register("text/foo", :foo)
+ assert_equal [mime], registered_mimes
+ ensure
+ Mime::Type.unregister(:foo)
end
test "custom type with extension aliases" do
- begin
- Mime::Type.register "text/foobar", :foobar, [], [:foo, "bar"]
- %w[foobar foo bar].each do |extension|
- assert_equal Mime[:foobar], Mime::EXTENSION_LOOKUP[extension]
- end
- ensure
- Mime::Type.unregister(:foobar)
+ Mime::Type.register "text/foobar", :foobar, [], [:foo, "bar"]
+ %w[foobar foo bar].each do |extension|
+ assert_equal Mime[:foobar], Mime::EXTENSION_LOOKUP[extension]
end
+ ensure
+ Mime::Type.unregister(:foobar)
end
test "register alias" do
- begin
- Mime::Type.register_alias "application/xhtml+xml", :foobar
- assert_equal Mime[:html], Mime::EXTENSION_LOOKUP["foobar"]
- ensure
- Mime::Type.unregister(:foobar)
- end
+ Mime::Type.register_alias "application/xhtml+xml", :foobar
+ assert_equal Mime[:html], Mime::EXTENSION_LOOKUP["foobar"]
+ ensure
+ Mime::Type.unregister(:foobar)
end
test "type should be equal to symbol" do
@@ -159,7 +149,7 @@ class MimeTypeTest < ActiveSupport::TestCase
types.each do |type|
mime = Mime[type]
- assert mime.respond_to?("#{type}?"), "#{mime.inspect} does not respond to #{type}?"
+ assert_respond_to mime, "#{type}?"
assert_equal type, mime.symbol, "#{mime.inspect} is not #{type}?"
invalid_types = types - [type]
invalid_types.delete(:html)
@@ -180,8 +170,8 @@ class MimeTypeTest < ActiveSupport::TestCase
assert Mime[:js] =~ "text/javascript"
assert Mime[:js] =~ "application/javascript"
assert Mime[:js] !~ "text/html"
- assert !(Mime[:js] !~ "text/javascript")
- assert !(Mime[:js] !~ "application/javascript")
+ assert_not (Mime[:js] !~ "text/javascript")
+ assert_not (Mime[:js] !~ "application/javascript")
assert Mime[:html] =~ "application/xhtml+xml"
end
end
diff --git a/actionpack/test/dispatch/mount_test.rb b/actionpack/test/dispatch/mount_test.rb
index f6cf653980..e42ea89f6f 100644
--- a/actionpack/test/dispatch/mount_test.rb
+++ b/actionpack/test/dispatch/mount_test.rb
@@ -80,6 +80,12 @@ class TestRoutingMount < ActionDispatch::IntegrationTest
assert_equal "/shorthand -- /omg", response.body
end
+ def test_mounting_does_not_match_similar_paths
+ get "/shorthandomg"
+ assert_not_equal "/shorthand -- /omg", response.body
+ assert_equal " -- /shorthandomg", response.body
+ end
+
def test_mounting_works_with_via
get "/getfake"
assert_equal "OK", response.body
diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb
index 85ea04356a..7a7a201b11 100644
--- a/actionpack/test/dispatch/prefix_generation_test.rb
+++ b/actionpack/test/dispatch/prefix_generation_test.rb
@@ -13,7 +13,7 @@ module TestGenerationPrefix
end
def self.model_name
- klass = "Post".dup
+ klass = +"Post"
def klass.name; self end
ActiveModel::Name.new(klass)
diff --git a/actionpack/test/dispatch/reloader_test.rb b/actionpack/test/dispatch/reloader_test.rb
index e529229fae..edc4cd62a3 100644
--- a/actionpack/test/dispatch/reloader_test.rb
+++ b/actionpack/test/dispatch/reloader_test.rb
@@ -115,7 +115,7 @@ class ReloaderTest < ActiveSupport::TestCase
reloader.to_complete { completed = true }
body = call_and_return_body
- assert !completed
+ assert_not completed
body.close
assert completed
@@ -129,7 +129,7 @@ class ReloaderTest < ActiveSupport::TestCase
prepared = false
body.close
- assert !prepared
+ assert_not prepared
end
def test_complete_callbacks_are_called_on_exceptions
diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb
index beab8e78b5..2a48a12497 100644
--- a/actionpack/test/dispatch/request/json_params_parsing_test.rb
+++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb
@@ -74,17 +74,15 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest
test "occurring a parse error if parsing unsuccessful" do
with_test_routing do
- begin
- $stderr = StringIO.new # suppress the log
- json = "[\"person]\": {\"name\": \"David\"}}"
- exception = assert_raise(ActionDispatch::Http::Parameters::ParseError) do
- post "/parse", params: json, headers: { "CONTENT_TYPE" => "application/json", "action_dispatch.show_exceptions" => false }
- end
- assert_equal JSON::ParserError, exception.cause.class
- assert_equal exception.cause.message, exception.message
- ensure
- $stderr = STDERR
+ $stderr = StringIO.new # suppress the log
+ json = "[\"person]\": {\"name\": \"David\"}}"
+ exception = assert_raise(ActionDispatch::Http::Parameters::ParseError) do
+ post "/parse", params: json, headers: { "CONTENT_TYPE" => "application/json", "action_dispatch.show_exceptions" => false }
end
+ assert_equal JSON::ParserError, exception.cause.class
+ assert_equal exception.cause.message, exception.message
+ ensure
+ $stderr = STDERR
end
end
@@ -157,31 +155,27 @@ class RootLessJSONParamsParsingTest < ActionDispatch::IntegrationTest
end
test "parses json params after custom json mime type registered" do
- begin
- Mime::Type.unregister :json
- Mime::Type.register "application/json", :json, %w(application/vnd.rails+json)
- assert_parses(
- { "user" => { "username" => "meinac" }, "username" => "meinac" },
- "{\"username\": \"meinac\"}", "CONTENT_TYPE" => "application/json"
- )
- ensure
- Mime::Type.unregister :json
- Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
- end
+ Mime::Type.unregister :json
+ Mime::Type.register "application/json", :json, %w(application/vnd.rails+json)
+ assert_parses(
+ { "user" => { "username" => "meinac" }, "username" => "meinac" },
+ "{\"username\": \"meinac\"}", "CONTENT_TYPE" => "application/json"
+ )
+ ensure
+ Mime::Type.unregister :json
+ Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
end
test "parses json params after custom json mime type registered with synonym" do
- begin
- Mime::Type.unregister :json
- Mime::Type.register "application/json", :json, %w(application/vnd.rails+json)
- assert_parses(
- { "user" => { "username" => "meinac" }, "username" => "meinac" },
- "{\"username\": \"meinac\"}", "CONTENT_TYPE" => "application/vnd.rails+json"
- )
- ensure
- Mime::Type.unregister :json
- Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
- end
+ Mime::Type.unregister :json
+ Mime::Type.register "application/json", :json, %w(application/vnd.rails+json)
+ assert_parses(
+ { "user" => { "username" => "meinac" }, "username" => "meinac" },
+ "{\"username\": \"meinac\"}", "CONTENT_TYPE" => "application/vnd.rails+json"
+ )
+ ensure
+ Mime::Type.unregister :json
+ Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
end
private
diff --git a/actionpack/test/dispatch/request/session_test.rb b/actionpack/test/dispatch/request/session_test.rb
index 7b6ce31f29..74da2fe7d3 100644
--- a/actionpack/test/dispatch/request/session_test.rb
+++ b/actionpack/test/dispatch/request/session_test.rb
@@ -22,6 +22,7 @@ module ActionDispatch
s["foo"] = "bar"
assert_equal "bar", s["foo"]
assert_equal({ "foo" => "bar" }, s.to_hash)
+ assert_equal({ "foo" => "bar" }, s.to_h)
end
def test_create_merges_old
@@ -117,6 +118,18 @@ module ActionDispatch
end
end
+ def test_dig
+ session = Session.create(store, req, {})
+ session["one"] = { "two" => "3" }
+
+ assert_equal "3", session.dig("one", "two")
+ assert_equal "3", session.dig(:one, "two")
+
+ assert_nil session.dig("three", "two")
+ assert_nil session.dig("one", "three")
+ assert_nil session.dig("one", :two)
+ end
+
private
def store
Class.new {
diff --git a/actionpack/test/dispatch/request_id_test.rb b/actionpack/test/dispatch/request_id_test.rb
index aa3175c986..9df4712dab 100644
--- a/actionpack/test/dispatch/request_id_test.rb
+++ b/actionpack/test/dispatch/request_id_test.rb
@@ -11,6 +11,11 @@ class RequestIdTest < ActiveSupport::TestCase
assert_equal "X-Hacked-HeaderStuff", stub_request("HTTP_X_REQUEST_ID" => "; X-Hacked-Header: Stuff").request_id
end
+ test "accept Apache mod_unique_id format" do
+ mod_unique_id = "abcxyz@ABCXYZ-0123456789"
+ assert_equal mod_unique_id, stub_request("HTTP_X_REQUEST_ID" => mod_unique_id).request_id
+ end
+
test "ensure that 255 char limit on the request id is being enforced" do
assert_equal "X" * 255, stub_request("HTTP_X_REQUEST_ID" => "X" * 500).request_id
end
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index 8661dc56d6..2a4d59affe 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -24,7 +24,7 @@ class BaseRequestTest < ActiveSupport::TestCase
def stub_request(env = {})
ip_spoofing_check = env.key?(:ip_spoofing_check) ? env.delete(:ip_spoofing_check) : true
@trusted_proxies ||= nil
- ip_app = ActionDispatch::RemoteIp.new(Proc.new {}, ip_spoofing_check, @trusted_proxies)
+ ip_app = ActionDispatch::RemoteIp.new(Proc.new { }, ip_spoofing_check, @trusted_proxies)
ActionDispatch::Http::URL.tld_length = env.delete(:tld_length) if env.key?(:tld_length)
ip_app.call(env)
@@ -329,20 +329,20 @@ class RequestPort < BaseRequestTest
test "standard_port?" do
request = stub_request
- assert !request.ssl?
- assert request.standard_port?
+ assert_not_predicate request, :ssl?
+ assert_predicate request, :standard_port?
request = stub_request "HTTPS" => "on"
- assert request.ssl?
- assert request.standard_port?
+ assert_predicate request, :ssl?
+ assert_predicate request, :standard_port?
request = stub_request "HTTP_HOST" => "www.example.org:8080"
- assert !request.ssl?
- assert !request.standard_port?
+ assert_not_predicate request, :ssl?
+ assert_not_predicate request, :standard_port?
request = stub_request "HTTP_HOST" => "www.example.org:8443", "HTTPS" => "on"
- assert request.ssl?
- assert !request.standard_port?
+ assert_predicate request, :ssl?
+ assert_not_predicate request, :standard_port?
end
test "optional port" do
@@ -571,7 +571,7 @@ end
class LocalhostTest < BaseRequestTest
test "IPs that match localhost" do
request = stub_request("REMOTE_IP" => "127.1.1.1", "REMOTE_ADDR" => "127.1.1.1")
- assert request.local?
+ assert_predicate request, :local?
end
end
@@ -643,37 +643,37 @@ class RequestProtocol < BaseRequestTest
test "xml http request" do
request = stub_request
- assert !request.xml_http_request?
- assert !request.xhr?
+ assert_not_predicate request, :xml_http_request?
+ assert_not_predicate request, :xhr?
request = stub_request "HTTP_X_REQUESTED_WITH" => "DefinitelyNotAjax1.0"
- assert !request.xml_http_request?
- assert !request.xhr?
+ assert_not_predicate request, :xml_http_request?
+ assert_not_predicate request, :xhr?
request = stub_request "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"
- assert request.xml_http_request?
- assert request.xhr?
+ assert_predicate request, :xml_http_request?
+ assert_predicate request, :xhr?
end
test "reports ssl" do
- assert !stub_request.ssl?
- assert stub_request("HTTPS" => "on").ssl?
+ assert_not_predicate stub_request, :ssl?
+ assert_predicate stub_request("HTTPS" => "on"), :ssl?
end
test "reports ssl when proxied via lighttpd" do
- assert stub_request("HTTP_X_FORWARDED_PROTO" => "https").ssl?
+ assert_predicate stub_request("HTTP_X_FORWARDED_PROTO" => "https"), :ssl?
end
test "scheme returns https when proxied" do
request = stub_request "rack.url_scheme" => "http"
- assert !request.ssl?
+ assert_not_predicate request, :ssl?
assert_equal "http", request.scheme
request = stub_request(
"rack.url_scheme" => "http",
"HTTP_X_FORWARDED_PROTO" => "https"
)
- assert request.ssl?
+ assert_predicate request, :ssl?
assert_equal "https", request.scheme
end
end
@@ -700,7 +700,7 @@ class RequestMethod < BaseRequestTest
assert_equal "GET", request.request_method
assert_equal "GET", request.env["REQUEST_METHOD"]
- assert request.get?
+ assert_predicate request, :get?
end
test "invalid http method raises exception" do
@@ -748,7 +748,7 @@ class RequestMethod < BaseRequestTest
assert_equal "POST", request.method
assert_equal "PATCH", request.request_method
- assert request.patch?
+ assert_predicate request, :patch?
end
test "post masquerading as put" do
@@ -758,12 +758,11 @@ class RequestMethod < BaseRequestTest
)
assert_equal "POST", request.method
assert_equal "PUT", request.request_method
- assert request.put?
+ assert_predicate request, :put?
end
test "post uneffected by local inflections" do
existing_acronyms = ActiveSupport::Inflector.inflections.acronyms.dup
- assert_deprecated { ActiveSupport::Inflector.inflections.acronym_regex.dup }
begin
ActiveSupport::Inflector.inflections do |inflect|
inflect.acronym "POS"
@@ -772,7 +771,7 @@ class RequestMethod < BaseRequestTest
request = stub_request "REQUEST_METHOD" => "POST"
assert_equal :post, ActionDispatch::Request::HTTP_METHOD_LOOKUP["POST"]
assert_equal :post, request.method_symbol
- assert request.post?
+ assert_predicate request, :post?
ensure
# Reset original acronym set
ActiveSupport::Inflector.inflections do |inflect|
@@ -785,50 +784,44 @@ end
class RequestFormat < BaseRequestTest
test "xml format" do
- request = stub_request
- assert_called(request, :parameters, times: 2, returns: { format: :xml }) do
- assert_equal Mime[:xml], request.format
- end
+ request = stub_request "QUERY_STRING" => "format=xml"
+
+ assert_equal Mime[:xml], request.format
end
test "xhtml format" do
- request = stub_request
- assert_called(request, :parameters, times: 2, returns: { format: :xhtml }) do
- assert_equal Mime[:html], request.format
- end
+ request = stub_request "QUERY_STRING" => "format=xhtml"
+
+ assert_equal Mime[:html], request.format
end
test "txt format" do
- request = stub_request
- assert_called(request, :parameters, times: 2, returns: { format: :txt }) do
- assert_equal Mime[:text], request.format
- end
+ request = stub_request "QUERY_STRING" => "format=txt"
+
+ assert_equal Mime[:text], request.format
end
test "XMLHttpRequest" do
request = stub_request(
"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
- "HTTP_ACCEPT" => [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(",")
+ "HTTP_ACCEPT" => [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(","),
+ "QUERY_STRING" => ""
)
- assert_called(request, :parameters, times: 1, returns: {}) do
- assert request.xhr?
- assert_equal Mime[:js], request.format
- end
+ assert_predicate request, :xhr?
+ assert_equal Mime[:js], request.format
end
test "can override format with parameter negative" do
- request = stub_request
- assert_called(request, :parameters, times: 2, returns: { format: :txt }) do
- assert !request.format.xml?
- end
+ request = stub_request("QUERY_STRING" => "format=txt")
+
+ assert_not_predicate request.format, :xml?
end
test "can override format with parameter positive" do
- request = stub_request
- assert_called(request, :parameters, times: 2, returns: { format: :xml }) do
- assert request.format.xml?
- end
+ request = stub_request("QUERY_STRING" => "format=xml")
+
+ assert_predicate request.format, :xml?
end
test "formats text/html with accept header" do
@@ -853,40 +846,37 @@ class RequestFormat < BaseRequestTest
end
test "formats format:text with accept header" do
- request = stub_request
- assert_called(request, :parameters, times: 2, returns: { format: :txt }) do
- assert_equal [Mime[:text]], request.formats
- end
+ request = stub_request("QUERY_STRING" => "format=txt")
+
+ assert_equal [Mime[:text]], request.formats
end
test "formats format:unknown with accept header" do
- request = stub_request
- assert_called(request, :parameters, times: 2, returns: { format: :unknown }) do
- assert_instance_of Mime::NullType, request.format
- end
+ request = stub_request("QUERY_STRING" => "format=unknown")
+
+ assert_instance_of Mime::NullType, request.format
end
test "format is not nil with unknown format" do
- request = stub_request
- assert_called(request, :parameters, times: 2, returns: { format: :hello }) do
- assert request.format.nil?
- assert_not request.format.html?
- assert_not request.format.xml?
- assert_not request.format.json?
- end
+ request = stub_request("QUERY_STRING" => "format=hello")
+
+ assert_nil request.format
+ assert_not_predicate request.format, :html?
+ assert_not_predicate request.format, :xml?
+ assert_not_predicate request.format, :json?
end
test "format does not throw exceptions when malformed parameters" do
request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2")
assert request.formats
- assert request.format.html?
+ assert_predicate request.format, :html?
end
test "formats with xhr request" do
- request = stub_request "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"
- assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [Mime[:js]], request.formats
- end
+ request = stub_request "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
+ "QUERY_STRING" => ""
+
+ assert_equal [Mime[:js]], request.formats
end
test "ignore_accept_header" do
@@ -894,62 +884,58 @@ class RequestFormat < BaseRequestTest
ActionDispatch::Request.ignore_accept_header = true
begin
- request = stub_request "HTTP_ACCEPT" => "application/xml"
- assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [ Mime[:html] ], request.formats
- end
+ request = stub_request "HTTP_ACCEPT" => "application/xml",
+ "QUERY_STRING" => ""
- request = stub_request "HTTP_ACCEPT" => "koz-asked/something-crazy"
- assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [ Mime[:html] ], request.formats
- end
+ assert_equal [ Mime[:html] ], request.formats
- request = stub_request "HTTP_ACCEPT" => "*/*;q=0.1"
- assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [ Mime[:html] ], request.formats
- end
+ request = stub_request "HTTP_ACCEPT" => "koz-asked/something-crazy",
+ "QUERY_STRING" => ""
- request = stub_request "HTTP_ACCEPT" => "application/jxw"
- assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [ Mime[:html] ], request.formats
- end
+ assert_equal [ Mime[:html] ], request.formats
+
+ request = stub_request "HTTP_ACCEPT" => "*/*;q=0.1",
+ "QUERY_STRING" => ""
+
+ assert_equal [ Mime[:html] ], request.formats
+
+ request = stub_request "HTTP_ACCEPT" => "application/jxw",
+ "QUERY_STRING" => ""
+
+ assert_equal [ Mime[:html] ], request.formats
request = stub_request "HTTP_ACCEPT" => "application/xml",
- "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"
+ "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
+ "QUERY_STRING" => ""
- assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [ Mime[:js] ], request.formats
- end
+ assert_equal [ Mime[:js] ], request.formats
request = stub_request "HTTP_ACCEPT" => "application/xml",
- "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"
- assert_called(request, :parameters, times: 2, returns: { format: :json }) do
- assert_equal [ Mime[:json] ], request.formats
- end
+ "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
+ "QUERY_STRING" => "format=json"
+
+ assert_equal [ Mime[:json] ], request.formats
ensure
ActionDispatch::Request.ignore_accept_header = old_ignore_accept_header
end
end
test "format taken from the path extension" do
- request = stub_request "PATH_INFO" => "/foo.xml"
- assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [Mime[:xml]], request.formats
- end
+ request = stub_request "PATH_INFO" => "/foo.xml", "QUERY_STRING" => ""
- request = stub_request "PATH_INFO" => "/foo.123"
- assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [Mime[:html]], request.formats
- end
+ assert_equal [Mime[:xml]], request.formats
+
+ request = stub_request "PATH_INFO" => "/foo.123", "QUERY_STRING" => ""
+
+ assert_equal [Mime[:html]], request.formats
end
test "formats from accept headers have higher precedence than path extension" do
request = stub_request "HTTP_ACCEPT" => "application/json",
- "PATH_INFO" => "/foo.xml"
+ "PATH_INFO" => "/foo.xml",
+ "QUERY_STRING" => ""
- assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [Mime[:json]], request.formats
- end
+ assert_equal [Mime[:json]], request.formats
end
end
@@ -997,15 +983,14 @@ end
class RequestParameters < BaseRequestTest
test "parameters" do
- request = stub_request
+ request = stub_request "CONTENT_TYPE" => "application/json",
+ "CONTENT_LENGTH" => 9,
+ "RAW_POST_DATA" => '{"foo":1}',
+ "QUERY_STRING" => "bar=2"
- assert_called(request, :request_parameters, times: 2, returns: { "foo" => 1 }) do
- assert_called(request, :query_parameters, times: 2, returns: { "bar" => 2 }) do
- assert_equal({ "foo" => 1, "bar" => 2 }, request.parameters)
- assert_equal({ "foo" => 1 }, request.request_parameters)
- assert_equal({ "bar" => 2 }, request.query_parameters)
- end
- end
+ assert_equal({ "foo" => 1, "bar" => "2" }, request.parameters)
+ assert_equal({ "foo" => 1 }, request.request_parameters)
+ assert_equal({ "bar" => "2" }, request.query_parameters)
end
test "parameters not accessible after rack parse error" do
@@ -1073,44 +1058,9 @@ class RequestParameters < BaseRequestTest
end
class RequestParameterFilter < BaseRequestTest
- test "process parameter filter" do
- test_hashes = [
- [{ "foo" => "bar" }, { "foo" => "bar" }, %w'food'],
- [{ "foo" => "bar" }, { "foo" => "[FILTERED]" }, %w'foo'],
- [{ "foo" => "bar", "bar" => "foo" }, { "foo" => "[FILTERED]", "bar" => "foo" }, %w'foo baz'],
- [{ "foo" => "bar", "baz" => "foo" }, { "foo" => "[FILTERED]", "baz" => "[FILTERED]" }, %w'foo baz'],
- [{ "bar" => { "foo" => "bar", "bar" => "foo" } }, { "bar" => { "foo" => "[FILTERED]", "bar" => "foo" } }, %w'fo'],
- [{ "foo" => { "foo" => "bar", "bar" => "foo" } }, { "foo" => "[FILTERED]" }, %w'f banana'],
- [{ "deep" => { "cc" => { "code" => "bar", "bar" => "foo" }, "ss" => { "code" => "bar" } } }, { "deep" => { "cc" => { "code" => "[FILTERED]", "bar" => "foo" }, "ss" => { "code" => "bar" } } }, %w'deep.cc.code'],
- [{ "baz" => [{ "foo" => "baz" }, "1"] }, { "baz" => [{ "foo" => "[FILTERED]" }, "1"] }, [/foo/]]]
-
- test_hashes.each do |before_filter, after_filter, filter_words|
- parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words)
- assert_equal after_filter, parameter_filter.filter(before_filter)
-
- filter_words << "blah"
- filter_words << lambda { |key, value|
- value.reverse! if key =~ /bargain/
- }
-
- 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]" } } }
-
- assert_equal after_filter, parameter_filter.filter(before_filter)
- end
- end
-
- test "parameter filter should maintain hash with indifferent access" do
- test_hashes = [
- [{ "foo" => "bar" }.with_indifferent_access, ["blah"]],
- [{ "foo" => "bar" }.with_indifferent_access, []]
- ]
-
- test_hashes.each do |before_filter, filter_words|
- parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words)
- assert_instance_of ActiveSupport::HashWithIndifferentAccess,
- parameter_filter.filter(before_filter)
+ test "parameter filter is deprecated" do
+ assert_deprecated do
+ ActionDispatch::Http::ParameterFilter.new(["blah"])
end
end
@@ -1248,8 +1198,8 @@ class RequestVariant < BaseRequestTest
test "setting variant to a symbol" do
@request.variant = :phone
- assert @request.variant.phone?
- assert_not @request.variant.tablet?
+ assert_predicate @request.variant, :phone?
+ assert_not_predicate @request.variant, :tablet?
assert @request.variant.any?(:phone, :tablet)
assert_not @request.variant.any?(:tablet, :desktop)
end
@@ -1257,9 +1207,9 @@ class RequestVariant < BaseRequestTest
test "setting variant to an array of symbols" do
@request.variant = [:phone, :tablet]
- assert @request.variant.phone?
- assert @request.variant.tablet?
- assert_not @request.variant.desktop?
+ assert_predicate @request.variant, :phone?
+ assert_predicate @request.variant, :tablet?
+ assert_not_predicate @request.variant, :desktop?
assert @request.variant.any?(:tablet, :desktop)
assert_not @request.variant.any?(:desktop, :watch)
end
@@ -1267,8 +1217,8 @@ class RequestVariant < BaseRequestTest
test "clearing variant" do
@request.variant = nil
- assert @request.variant.empty?
- assert_not @request.variant.phone?
+ assert_empty @request.variant
+ assert_not_predicate @request.variant, :phone?
assert_not @request.variant.any?(:phone, :tablet)
end
@@ -1287,13 +1237,13 @@ end
class RequestFormData < BaseRequestTest
test "media_type is from the FORM_DATA_MEDIA_TYPES array" do
- assert stub_request("CONTENT_TYPE" => "application/x-www-form-urlencoded").form_data?
- assert stub_request("CONTENT_TYPE" => "multipart/form-data").form_data?
+ assert_predicate stub_request("CONTENT_TYPE" => "application/x-www-form-urlencoded"), :form_data?
+ assert_predicate stub_request("CONTENT_TYPE" => "multipart/form-data"), :form_data?
end
test "media_type is not from the FORM_DATA_MEDIA_TYPES array" do
- assert !stub_request("CONTENT_TYPE" => "application/xml").form_data?
- assert !stub_request("CONTENT_TYPE" => "multipart/related").form_data?
+ assert_not_predicate stub_request("CONTENT_TYPE" => "application/xml"), :form_data?
+ assert_not_predicate stub_request("CONTENT_TYPE" => "multipart/related"), :form_data?
end
test "no Content-Type header is provided and the request_method is POST" do
@@ -1301,7 +1251,7 @@ class RequestFormData < BaseRequestTest
assert_equal "", request.media_type
assert_equal "POST", request.request_method
- assert !request.form_data?
+ assert_not_predicate request, :form_data?
end
end
diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb
index 4e350162c9..60817c1c4d 100644
--- a/actionpack/test/dispatch/response_test.rb
+++ b/actionpack/test/dispatch/response_test.rb
@@ -15,13 +15,13 @@ class ResponseTest < ActiveSupport::TestCase
@response.await_commit
}
@response.commit!
- assert @response.committed?
+ assert_predicate @response, :committed?
assert t.join(0.5)
end
def test_stream_close
@response.stream.close
- assert @response.stream.closed?
+ assert_predicate @response.stream, :closed?
end
def test_stream_write
@@ -42,7 +42,7 @@ class ResponseTest < ActiveSupport::TestCase
def test_each_isnt_called_if_str_body_is_written
# Controller writes and reads response body
each_counter = 0
- @response.body = Object.new.tap { |o| o.singleton_class.send(:define_method, :each) { |&block| each_counter += 1; block.call "foo" } }
+ @response.body = Object.new.tap { |o| o.singleton_class.define_method(:each) { |&block| each_counter += 1; block.call "foo" } }
@response["X-Foo"] = @response.body
assert_equal 1, each_counter, "#each was not called once"
@@ -158,7 +158,7 @@ class ResponseTest < ActiveSupport::TestCase
@response.status = c.to_s
@response.set_header "Content-Length", "0"
_, headers, _ = @response.to_a
- assert !headers.has_key?("Content-Length"), "#{c} must not have a Content-Length header field"
+ assert_not headers.has_key?("Content-Length"), "#{c} must not have a Content-Length header field"
end
end
@@ -177,7 +177,7 @@ class ResponseTest < ActiveSupport::TestCase
@response = ActionDispatch::Response.new
@response.status = c.to_s
_, headers, _ = @response.to_a
- assert !headers.has_key?("Content-Type"), "#{c} should not have Content-Type header"
+ assert_not headers.has_key?("Content-Type"), "#{c} should not have Content-Type header"
end
[200, 302, 404, 500].each do |c|
@@ -191,7 +191,7 @@ class ResponseTest < ActiveSupport::TestCase
test "does not include Status header" do
@response.status = "200 OK"
_, headers, _ = @response.to_a
- assert !headers.has_key?("Status")
+ assert_not headers.has_key?("Status")
end
test "response code" do
@@ -257,9 +257,9 @@ class ResponseTest < ActiveSupport::TestCase
}
resp.to_a
- assert resp.etag?
- assert resp.weak_etag?
- assert_not resp.strong_etag?
+ assert_predicate resp, :etag?
+ assert_predicate resp, :weak_etag?
+ assert_not_predicate resp, :strong_etag?
assert_equal('W/"202cb962ac59075b964b07152d234b70"', resp.etag)
assert_equal({ public: true }, resp.cache_control)
@@ -275,9 +275,9 @@ class ResponseTest < ActiveSupport::TestCase
}
resp.to_a
- assert resp.etag?
- assert_not resp.weak_etag?
- assert resp.strong_etag?
+ assert_predicate resp, :etag?
+ assert_not_predicate resp, :weak_etag?
+ assert_predicate resp, :strong_etag?
assert_equal('"202cb962ac59075b964b07152d234b70"', resp.etag)
end
@@ -311,7 +311,7 @@ class ResponseTest < ActiveSupport::TestCase
end
end
- test "read x_frame_options, x_content_type_options, x_xss_protection, x_download_options and x_permitted_cross_domain_policies" do
+ test "read x_frame_options, x_content_type_options, x_xss_protection, x_download_options and x_permitted_cross_domain_policies, referrer_policy" do
original_default_headers = ActionDispatch::Response.default_headers
begin
ActionDispatch::Response.default_headers = {
@@ -319,7 +319,8 @@ class ResponseTest < ActiveSupport::TestCase
"X-Content-Type-Options" => "nosniff",
"X-XSS-Protection" => "1;",
"X-Download-Options" => "noopen",
- "X-Permitted-Cross-Domain-Policies" => "none"
+ "X-Permitted-Cross-Domain-Policies" => "none",
+ "Referrer-Policy" => "strict-origin-when-cross-origin"
}
resp = ActionDispatch::Response.create.tap { |response|
response.body = "Hello"
@@ -331,6 +332,7 @@ class ResponseTest < ActiveSupport::TestCase
assert_equal("1;", resp.headers["X-XSS-Protection"])
assert_equal("noopen", resp.headers["X-Download-Options"])
assert_equal("none", resp.headers["X-Permitted-Cross-Domain-Policies"])
+ assert_equal("strict-origin-when-cross-origin", resp.headers["Referrer-Policy"])
ensure
ActionDispatch::Response.default_headers = original_default_headers
end
@@ -354,7 +356,7 @@ class ResponseTest < ActiveSupport::TestCase
end
test "respond_to? accepts include_private" do
- assert_not @response.respond_to?(:method_missing)
+ assert_not_respond_to @response, :method_missing
assert @response.respond_to?(:method_missing, true)
end
diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb
index 438a918567..fe1f1995d8 100644
--- a/actionpack/test/dispatch/routing/inspector_test.rb
+++ b/actionpack/test/dispatch/routing/inspector_test.rb
@@ -3,6 +3,7 @@
require "abstract_unit"
require "rails/engine"
require "action_dispatch/routing/inspector"
+require "io/console/size"
class MountedRackApp
def self.call(env)
@@ -15,16 +16,10 @@ end
module ActionDispatch
module Routing
class RoutesInspectorTest < ActiveSupport::TestCase
- def setup
+ setup do
@set = ActionDispatch::Routing::RouteSet.new
end
- def draw(options = nil, &block)
- @set.draw(&block)
- inspector = ActionDispatch::Routing::RoutesInspector.new(@set.routes)
- inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, options).split("\n")
- end
-
def test_displaying_routes_for_engines
engine = Class.new(Rails::Engine) do
def self.inspect
@@ -305,7 +300,7 @@ module ActionDispatch
end
def test_routes_can_be_filtered
- output = draw("posts") do
+ output = draw(grep: "posts") do
resources :articles
resources :posts
end
@@ -321,8 +316,76 @@ module ActionDispatch
" DELETE /posts/:id(.:format) posts#destroy"], output
end
+ def test_routes_when_expanded
+ previous_console_winsize = IO.console.winsize
+ IO.console.winsize = [0, 23]
+
+ engine = Class.new(Rails::Engine) do
+ def self.inspect
+ "Blog::Engine"
+ end
+ end
+ engine.routes.draw do
+ get "/cart", to: "cart#show"
+ end
+
+ output = draw(formatter: ActionDispatch::Routing::ConsoleFormatter::Expanded.new) do
+ get "/custom/assets", to: "custom_assets#show"
+ get "/custom/furnitures", to: "custom_furnitures#show"
+ mount engine => "/blog", :as => "blog"
+ end
+
+ assert_equal ["--[ Route 1 ]----------",
+ "Prefix | custom_assets",
+ "Verb | GET",
+ "URI | /custom/assets(.:format)",
+ "Controller#Action | custom_assets#show",
+ "--[ Route 2 ]----------",
+ "Prefix | custom_furnitures",
+ "Verb | GET",
+ "URI | /custom/furnitures(.:format)",
+ "Controller#Action | custom_furnitures#show",
+ "--[ Route 3 ]----------",
+ "Prefix | blog",
+ "Verb | ",
+ "URI | /blog",
+ "Controller#Action | Blog::Engine",
+ "",
+ "[ Routes for Blog::Engine ]",
+ "--[ Route 1 ]----------",
+ "Prefix | cart",
+ "Verb | GET",
+ "URI | /cart(.:format)",
+ "Controller#Action | cart#show"], output
+ ensure
+ IO.console.winsize = previous_console_winsize
+ end
+
+ def test_no_routes_matched_filter_when_expanded
+ output = draw(grep: "rails/dummy", formatter: ActionDispatch::Routing::ConsoleFormatter::Expanded.new) do
+ get "photos/:id" => "photos#show", :id => /[A-Z]\d{5}/
+ end
+
+ assert_equal [
+ "No routes were found for this grep pattern.",
+ "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html."
+ ], output
+ end
+
+ def test_not_routes_when_expanded
+ output = draw(grep: "rails/dummy", formatter: ActionDispatch::Routing::ConsoleFormatter::Expanded.new) { }
+
+ assert_equal [
+ "You don't have any routes defined!",
+ "",
+ "Please add some routes in config/routes.rb.",
+ "",
+ "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html."
+ ], output
+ end
+
def test_routes_can_be_filtered_with_namespaced_controllers
- output = draw("admin/posts") do
+ output = draw(grep: "admin/posts") do
resources :articles
namespace :admin do
resources :posts
@@ -370,31 +433,31 @@ module ActionDispatch
end
assert_equal [
- "No routes were found for this controller",
- "For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html."
+ "No routes were found for this controller.",
+ "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html."
], output
end
def test_no_routes_matched_filter
- output = draw("rails/dummy") do
+ output = draw(grep: "rails/dummy") do
get "photos/:id" => "photos#show", :id => /[A-Z]\d{5}/
end
assert_equal [
- "No routes were found for this controller",
- "For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html."
+ "No routes were found for this grep pattern.",
+ "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html."
], output
end
def test_no_routes_were_defined
- output = draw("Rails::DummyController") {}
+ output = draw(grep: "Rails::DummyController") { }
assert_equal [
"You don't have any routes defined!",
"",
"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
@@ -420,6 +483,13 @@ module ActionDispatch
"custom_assets GET /custom/assets(.:format) custom_assets#show",
], output
end
+
+ private
+ def draw(formatter: ActionDispatch::Routing::ConsoleFormatter::Sheet.new, **options, &block)
+ @set.draw(&block)
+ inspector = ActionDispatch::Routing::RoutesInspector.new(@set.routes)
+ inspector.format(formatter, options).split("\n")
+ end
end
end
end
diff --git a/actionpack/test/dispatch/routing/non_dispatch_routed_app_test.rb b/actionpack/test/dispatch/routing/non_dispatch_routed_app_test.rb
new file mode 100644
index 0000000000..676a8c38d4
--- /dev/null
+++ b/actionpack/test/dispatch/routing/non_dispatch_routed_app_test.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+
+module ActionDispatch
+ module Routing
+ class NonDispatchRoutedAppTest < ActionDispatch::IntegrationTest
+ # For example, Grape::API
+ class SimpleApp
+ def self.call(env)
+ [ 200, { "Content-Type" => "text/plain" }, [] ]
+ end
+
+ def self.routes
+ []
+ end
+ end
+
+ setup { @app = SimpleApp }
+
+ test "does not except" do
+ get "/foo"
+ assert_response :success
+ end
+ end
+ end
+end
diff --git a/actionpack/test/dispatch/routing_assertions_test.rb b/actionpack/test/dispatch/routing_assertions_test.rb
index a5198f2f13..009b6d9bc3 100644
--- a/actionpack/test/dispatch/routing_assertions_test.rb
+++ b/actionpack/test/dispatch/routing_assertions_test.rb
@@ -52,6 +52,8 @@ class RoutingAssertionsTest < ActionController::TestCase
end
mount engine => "/shelf"
+
+ get "/shelf/foo", controller: "query_articles", action: "index"
end
end
@@ -154,6 +156,10 @@ class RoutingAssertionsTest < ActionController::TestCase
assert_match err.message, "This is a really bad msg"
end
+ def test_assert_recognizes_continue_to_recoginize_after_it_tried_engines
+ assert_recognizes({ controller: "query_articles", action: "index" }, "/shelf/foo")
+ end
+
def test_assert_routing
assert_routing("/articles", controller: "articles", action: "index")
end
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 8f4e7c96a9..897d17885e 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -115,6 +115,21 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal 301, status
end
+ def test_accepts_a_constraint_object_responding_to_call
+ constraint = Class.new do
+ def call(*); true; end
+ def matches?(*); false; end
+ end
+
+ draw do
+ get "/", to: "home#show", constraints: constraint.new
+ end
+
+ assert_nothing_raised do
+ get "/"
+ end
+ end
+
def test_namespace_with_controller_segment
assert_raise(ArgumentError) do
draw do
@@ -1367,6 +1382,22 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal "projects#index", @response.body
end
+ def test_optionally_scoped_root_unscoped_access
+ draw do
+ scope "(:locale)" do
+ scope "(:platform)" do
+ scope "(:browser)" do
+ root to: "projects#index"
+ end
+ end
+ end
+ end
+
+ assert_equal "/", root_path
+ get "/"
+ assert_equal "projects#index", @response.body
+ end
+
def test_scope_with_format_option
draw do
get "direct/index", as: :no_format_direct, format: false
@@ -3153,7 +3184,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
after = has_named_route?(:hello)
end
- assert !before, "expected to not have named route :hello before route definition"
+ assert_not before, "expected to not have named route :hello before route definition"
assert after, "expected to have named route :hello after route definition"
end
@@ -3166,7 +3197,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
- assert !respond_to?(:routes_no_collision_path)
+ assert_not respond_to?(:routes_no_collision_path)
end
def test_controller_name_with_leading_slash_raise_error
@@ -3313,7 +3344,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
get "/search"
- assert !@request.params[:action].frozen?
+ assert_not_predicate @request.params[:action], :frozen?
end
def test_multiple_positional_args_with_the_same_name
@@ -3667,15 +3698,25 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
- def test_multiple_roots
+ def test_multiple_roots_raises_error
+ ex = assert_raises(ArgumentError) {
+ draw do
+ root "pages#index", constraints: { host: "www.example.com" }
+ root "admin/pages#index", constraints: { host: "admin.example.com" }
+ end
+ }
+ assert_match(/Invalid route name, already in use: 'root'/, ex.message)
+ end
+
+ def test_multiple_named_roots
draw do
namespace :foo do
root "pages#index", constraints: { host: "www.example.com" }
- root "admin/pages#index", constraints: { host: "admin.example.com" }
+ root "admin/pages#index", constraints: { host: "admin.example.com" }, as: :admin_root
end
root "pages#index", constraints: { host: "www.example.com" }
- root "admin/pages#index", constraints: { host: "admin.example.com" }
+ root "admin/pages#index", constraints: { host: "admin.example.com" }, as: :admin_root
end
get "http://www.example.com/foo"
@@ -4267,7 +4308,7 @@ class TestOptimizedNamedRoutes < ActionDispatch::IntegrationTest
def app; APP end
test "enabled when not mounted and default_url_options is empty" do
- assert Routes.url_helpers.optimize_routes_generation?
+ assert_predicate Routes.url_helpers, :optimize_routes_generation?
end
test "named route called as singleton method" do
@@ -4500,7 +4541,7 @@ class TestPortConstraints < ActionDispatch::IntegrationTest
get "/integer", to: ok, constraints: { port: 8080 }
get "/string", to: ok, constraints: { port: "8080" }
- get "/array", to: ok, constraints: { port: [8080] }
+ get "/array/:idx", to: ok, constraints: { port: [8080], idx: %w[first last] }
get "/regexp", to: ok, constraints: { port: /8080/ }
end
end
@@ -4529,7 +4570,10 @@ class TestPortConstraints < ActionDispatch::IntegrationTest
get "http://www.example.com/array"
assert_response :not_found
- get "http://www.example.com:8080/array"
+ get "http://www.example.com:8080/array/middle"
+ assert_response :not_found
+
+ get "http://www.example.com:8080/array/first"
assert_response :success
end
@@ -4947,8 +4991,12 @@ end
class FlashRedirectTest < ActionDispatch::IntegrationTest
SessionKey = "_myapp_session"
- Generator = ActiveSupport::LegacyKeyGenerator.new("b3c631c314c0bbca50c1b2843150fe33")
- Rotations = ActiveSupport::Messages::RotationConfiguration.new
+ Generator = ActiveSupport::CachingKeyGenerator.new(
+ ActiveSupport::KeyGenerator.new("b3c631c314c0bbca50c1b2843150fe33", iterations: 1000)
+ )
+ Rotations = ActiveSupport::Messages::RotationConfiguration.new
+ SIGNED_COOKIE_SALT = "signed cookie"
+ ENCRYPTED_SIGNED_COOKIE_SALT = "sigend encrypted cookie"
class KeyGeneratorMiddleware
def initialize(app)
@@ -4958,6 +5006,8 @@ class FlashRedirectTest < ActionDispatch::IntegrationTest
def call(env)
env["action_dispatch.key_generator"] ||= Generator
env["action_dispatch.cookies_rotations"] ||= Rotations
+ env["action_dispatch.signed_cookie_salt"] = SIGNED_COOKIE_SALT
+ env["action_dispatch.encrypted_signed_cookie_salt"] = ENCRYPTED_SIGNED_COOKIE_SALT
@app.call(env)
end
diff --git a/actionpack/test/dispatch/session/mem_cache_store_test.rb b/actionpack/test/dispatch/session/mem_cache_store_test.rb
index 9b51ee1cad..ac685a7dca 100644
--- a/actionpack/test/dispatch/session/mem_cache_store_test.rb
+++ b/actionpack/test/dispatch/session/mem_cache_store_test.rb
@@ -38,8 +38,9 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest
begin
require "dalli"
- ss = Dalli::Client.new("localhost:11211").stats
- raise Dalli::DalliError unless ss["localhost:11211"]
+ servers = ENV["MEMCACHE_SERVERS"] || "localhost:11211"
+ ss = Dalli::Client.new(servers).stats
+ raise Dalli::DalliError unless ss[servers]
def test_setting_and_getting_session_value
with_test_route_set do
@@ -195,7 +196,9 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest
end
@app = self.class.build_app(set) do |middleware|
- middleware.use ActionDispatch::Session::MemCacheStore, key: "_session_id", namespace: "mem_cache_store_test:#{SecureRandom.hex(10)}"
+ middleware.use ActionDispatch::Session::MemCacheStore,
+ key: "_session_id", namespace: "mem_cache_store_test:#{SecureRandom.hex(10)}",
+ memcache_server: ENV["MEMCACHE_SERVERS"] || "localhost:11211"
middleware.delete ActionDispatch::ShowExceptions
end
diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb
index b69071b44b..f802abc653 100644
--- a/actionpack/test/dispatch/show_exceptions_test.rb
+++ b/actionpack/test/dispatch/show_exceptions_test.rb
@@ -36,30 +36,30 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
test "skip exceptions app if not showing exceptions" do
@app = ProductionApp
assert_raise RuntimeError do
- get "/", headers: { "action_dispatch.show_exceptions" => false }
+ get "/", env: { "action_dispatch.show_exceptions" => false }
end
end
test "rescue with error page" do
@app = ProductionApp
- get "/", headers: { "action_dispatch.show_exceptions" => true }
+ get "/", env: { "action_dispatch.show_exceptions" => true }
assert_response 500
assert_equal "500 error fixture\n", body
- get "/bad_params", headers: { "action_dispatch.show_exceptions" => true }
+ get "/bad_params", env: { "action_dispatch.show_exceptions" => true }
assert_response 400
assert_equal "400 error fixture\n", body
- get "/not_found", headers: { "action_dispatch.show_exceptions" => true }
+ get "/not_found", env: { "action_dispatch.show_exceptions" => true }
assert_response 404
assert_equal "404 error fixture\n", body
- get "/method_not_allowed", headers: { "action_dispatch.show_exceptions" => true }
+ get "/method_not_allowed", env: { "action_dispatch.show_exceptions" => true }
assert_response 405
assert_equal "", body
- get "/unknown_http_method", headers: { "action_dispatch.show_exceptions" => true }
+ get "/unknown_http_method", env: { "action_dispatch.show_exceptions" => true }
assert_response 405
assert_equal "", body
end
@@ -70,11 +70,11 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
begin
@app = ProductionApp
- get "/", headers: { "action_dispatch.show_exceptions" => true }
+ get "/", env: { "action_dispatch.show_exceptions" => true }
assert_response 500
assert_equal "500 localized error fixture\n", body
- get "/not_found", headers: { "action_dispatch.show_exceptions" => true }
+ get "/not_found", env: { "action_dispatch.show_exceptions" => true }
assert_response 404
assert_equal "404 error fixture\n", body
ensure
@@ -85,14 +85,14 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
test "sets the HTTP charset parameter" do
@app = ProductionApp
- get "/", headers: { "action_dispatch.show_exceptions" => true }
+ get "/", env: { "action_dispatch.show_exceptions" => true }
assert_equal "text/html; charset=utf-8", response.headers["Content-Type"]
end
test "show registered original exception for wrapped exceptions" do
@app = ProductionApp
- get "/not_found_original_exception", headers: { "action_dispatch.show_exceptions" => true }
+ get "/not_found_original_exception", env: { "action_dispatch.show_exceptions" => true }
assert_response 404
assert_match(/404 error/, body)
end
@@ -106,7 +106,7 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
end
@app = ActionDispatch::ShowExceptions.new(Boomer.new, exceptions_app)
- get "/not_found_original_exception", headers: { "action_dispatch.show_exceptions" => true }
+ get "/not_found_original_exception", env: { "action_dispatch.show_exceptions" => true }
assert_response 404
assert_equal "YOU FAILED", body
end
@@ -117,7 +117,7 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
end
@app = ActionDispatch::ShowExceptions.new(Boomer.new, exceptions_app)
- get "/method_not_allowed", headers: { "action_dispatch.show_exceptions" => true }
+ get "/method_not_allowed", env: { "action_dispatch.show_exceptions" => true }
assert_response 405
assert_equal "", body
end
@@ -125,12 +125,12 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest
test "bad params exception is returned in the correct format" do
@app = ProductionApp
- get "/bad_params", headers: { "action_dispatch.show_exceptions" => true }
+ get "/bad_params", env: { "action_dispatch.show_exceptions" => true }
assert_equal "text/html; charset=utf-8", response.headers["Content-Type"]
assert_response 400
assert_match(/400 error/, body)
- get "/bad_params.json", headers: { "action_dispatch.show_exceptions" => true }
+ get "/bad_params.json", env: { "action_dispatch.show_exceptions" => true }
assert_equal "application/json; charset=utf-8", response.headers["Content-Type"]
assert_response 400
assert_equal("{\"status\":400,\"error\":\"Bad Request\"}", body)
diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb
index 8ac9502af9..baf46e7c7e 100644
--- a/actionpack/test/dispatch/ssl_test.rb
+++ b/actionpack/test/dispatch/ssl_test.rb
@@ -98,8 +98,8 @@ class RedirectSSLTest < SSLTest
end
class StrictTransportSecurityTest < SSLTest
- EXPECTED = "max-age=15552000"
- EXPECTED_WITH_SUBDOMAINS = "max-age=15552000; includeSubDomains"
+ EXPECTED = "max-age=31536000"
+ EXPECTED_WITH_SUBDOMAINS = "max-age=31536000; includeSubDomains"
def assert_hsts(expected, url: "https://example.org", hsts: { subdomains: true }, headers: {})
self.app = build_app ssl_options: { hsts: hsts }, headers: headers
@@ -208,6 +208,14 @@ class SecureCookiesTest < SSLTest
assert_cookies(*DEFAULT.split("\n"))
end
+ def test_cookies_as_not_secure_with_exclude
+ excluding = { exclude: -> request { request.domain =~ /example/ } }
+ get headers: { "Set-Cookie" => DEFAULT }, ssl_options: { redirect: excluding }
+
+ assert_cookies(*DEFAULT.split("\n"))
+ assert_response :ok
+ end
+
def test_no_cookies
get
assert_nil response.headers["Set-Cookie"]
diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb
index 0bdff68692..d44aa00122 100644
--- a/actionpack/test/dispatch/static_test.rb
+++ b/actionpack/test/dispatch/static_test.rb
@@ -31,7 +31,7 @@ module StaticTests
end
def test_handles_urls_with_ascii_8bit
- assert_equal "Hello, World!", get("/doorkeeper%E3E4".dup.force_encoding("ASCII-8BIT")).body
+ assert_equal "Hello, World!", get((+"/doorkeeper%E3E4").force_encoding("ASCII-8BIT")).body
end
def test_handles_urls_with_ascii_8bit_on_win_31j
@@ -39,7 +39,7 @@ module StaticTests
Encoding.default_internal = "Windows-31J"
Encoding.default_external = "Windows-31J"
end
- assert_equal "Hello, World!", get("/doorkeeper%E3E4".dup.force_encoding("ASCII-8BIT")).body
+ assert_equal "Hello, World!", get((+"/doorkeeper%E3E4").force_encoding("ASCII-8BIT")).body
end
def test_handles_urls_with_null_byte
@@ -71,7 +71,16 @@ module StaticTests
end
def test_served_static_file_with_non_english_filename
- assert_html "means hello in Japanese\n", get("/foo/#{Rack::Utils.escape("こんにちは.html")}")
+ assert_html "means hello in Japanese\n", get("/foo/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF.html")
+ end
+
+ def test_served_gzipped_static_file_with_non_english_filename
+ response = get("/foo/%E3%81%95%E3%82%88%E3%81%86%E3%81%AA%E3%82%89.html", "HTTP_ACCEPT_ENCODING" => "gzip")
+
+ assert_gzip "/foo/さようなら.html", response
+ assert_equal "text/html", response.headers["Content-Type"]
+ assert_equal "Accept-Encoding", response.headers["Vary"]
+ assert_equal "gzip", response.headers["Content-Encoding"]
end
def test_serves_static_file_with_exclamation_mark_in_filename
diff --git a/actionpack/test/dispatch/system_testing/driver_test.rb b/actionpack/test/dispatch/system_testing/driver_test.rb
index fcdaf7fb4c..0d08f17af3 100644
--- a/actionpack/test/dispatch/system_testing/driver_test.rb
+++ b/actionpack/test/dispatch/system_testing/driver_test.rb
@@ -2,6 +2,7 @@
require "abstract_unit"
require "action_dispatch/system_testing/driver"
+require "selenium/webdriver"
class DriverTest < ActiveSupport::TestCase
test "initializing the driver" do
@@ -12,7 +13,8 @@ class DriverTest < ActiveSupport::TestCase
test "initializing the driver with a browser" do
driver = ActionDispatch::SystemTesting::Driver.new(:selenium, using: :chrome, screen_size: [1400, 1400], options: { url: "http://example.com/wd/hub" })
assert_equal :selenium, driver.instance_variable_get(:@name)
- assert_equal :chrome, driver.instance_variable_get(:@browser)
+ assert_equal :chrome, driver.instance_variable_get(:@browser).name
+ assert_nil driver.instance_variable_get(:@browser).options
assert_equal [1400, 1400], driver.instance_variable_get(:@screen_size)
assert_equal ({ url: "http://example.com/wd/hub" }), driver.instance_variable_get(:@options)
end
@@ -20,7 +22,8 @@ class DriverTest < ActiveSupport::TestCase
test "initializing the driver with a headless chrome" do
driver = ActionDispatch::SystemTesting::Driver.new(:selenium, using: :headless_chrome, screen_size: [1400, 1400], options: { url: "http://example.com/wd/hub" })
assert_equal :selenium, driver.instance_variable_get(:@name)
- assert_equal :headless_chrome, driver.instance_variable_get(:@browser)
+ assert_equal :headless_chrome, driver.instance_variable_get(:@browser).name
+ assert_instance_of Selenium::WebDriver::Chrome::Options, driver.instance_variable_get(:@browser).options
assert_equal [1400, 1400], driver.instance_variable_get(:@screen_size)
assert_equal ({ url: "http://example.com/wd/hub" }), driver.instance_variable_get(:@options)
end
@@ -28,7 +31,8 @@ class DriverTest < ActiveSupport::TestCase
test "initializing the driver with a headless firefox" do
driver = ActionDispatch::SystemTesting::Driver.new(:selenium, using: :headless_firefox, screen_size: [1400, 1400], options: { url: "http://example.com/wd/hub" })
assert_equal :selenium, driver.instance_variable_get(:@name)
- assert_equal :headless_firefox, driver.instance_variable_get(:@browser)
+ assert_equal :headless_firefox, driver.instance_variable_get(:@browser).name
+ assert_instance_of Selenium::WebDriver::Firefox::Options, driver.instance_variable_get(:@browser).options
assert_equal [1400, 1400], driver.instance_variable_get(:@screen_size)
assert_equal ({ url: "http://example.com/wd/hub" }), driver.instance_variable_get(:@options)
end
@@ -50,4 +54,70 @@ class DriverTest < ActiveSupport::TestCase
test "registerable? returns false if driver is rack_test" do
assert_not ActionDispatch::SystemTesting::Driver.new(:rack_test).send(:registerable?)
end
+
+ test "define extra capabilities using chrome" do
+ driver_option = nil
+ driver = ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :chrome) do |option|
+ option.add_argument("start-maximized")
+ option.add_emulation(device_name: "iphone 6")
+ option.add_preference(:detach, true)
+
+ driver_option = option
+ end
+ driver.use
+
+ expected = { args: ["start-maximized"], mobileEmulation: { deviceName: "iphone 6" }, prefs: { detach: true } }
+ assert_equal expected, driver_option.as_json
+ end
+
+ test "define extra capabilities using headless_chrome" do
+ driver_option = nil
+ driver = ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :headless_chrome) do |option|
+ option.add_argument("start-maximized")
+ option.add_emulation(device_name: "iphone 6")
+ option.add_preference(:detach, true)
+
+ driver_option = option
+ end
+ driver.use
+
+ expected = { args: ["start-maximized"], mobileEmulation: { deviceName: "iphone 6" }, prefs: { detach: true } }
+ assert_equal expected, driver_option.as_json
+ end
+
+ test "define extra capabilities using firefox" do
+ driver_option = nil
+ driver = ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :firefox) do |option|
+ option.add_preference("browser.startup.homepage", "http://www.seleniumhq.com/")
+ option.add_argument("--host=127.0.0.1")
+
+ driver_option = option
+ end
+ driver.use
+
+ expected = { "moz:firefoxOptions" => { args: ["--host=127.0.0.1"], prefs: { "browser.startup.homepage" => "http://www.seleniumhq.com/" } } }
+ assert_equal expected, driver_option.as_json
+ end
+
+ test "define extra capabilities using headless_firefox" do
+ driver_option = nil
+ driver = ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :headless_firefox) do |option|
+ option.add_preference("browser.startup.homepage", "http://www.seleniumhq.com/")
+ option.add_argument("--host=127.0.0.1")
+
+ driver_option = option
+ end
+ driver.use
+
+ expected = { "moz:firefoxOptions" => { args: ["--host=127.0.0.1"], prefs: { "browser.startup.homepage" => "http://www.seleniumhq.com/" } } }
+ assert_equal expected, driver_option.as_json
+ end
+
+ test "does not define extra capabilities" do
+ driver = ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :firefox)
+
+ assert_nothing_raised do
+ driver.use
+ end
+ end
end
diff --git a/actionpack/test/dispatch/system_testing/screenshot_helper_test.rb b/actionpack/test/dispatch/system_testing/screenshot_helper_test.rb
index 264844fc7d..b756b91379 100644
--- a/actionpack/test/dispatch/system_testing/screenshot_helper_test.rb
+++ b/actionpack/test/dispatch/system_testing/screenshot_helper_test.rb
@@ -3,13 +3,14 @@
require "abstract_unit"
require "action_dispatch/system_testing/test_helpers/screenshot_helper"
require "capybara/dsl"
+require "selenium/webdriver"
class ScreenshotHelperTest < ActiveSupport::TestCase
test "image path is saved in tmp directory" do
new_test = DrivenBySeleniumWithChrome.new("x")
Rails.stub :root, Pathname.getwd do
- assert_equal "tmp/screenshots/x.png", new_test.send(:image_path)
+ assert_equal Rails.root.join("tmp/screenshots/x.png").to_s, new_test.send(:image_path)
end
end
@@ -18,7 +19,7 @@ class ScreenshotHelperTest < ActiveSupport::TestCase
Rails.stub :root, Pathname.getwd do
new_test.stub :passed?, false do
- assert_equal "tmp/screenshots/failures_x.png", new_test.send(:image_path)
+ assert_equal Rails.root.join("tmp/screenshots/failures_x.png").to_s, new_test.send(:image_path)
end
end
end
@@ -29,7 +30,7 @@ class ScreenshotHelperTest < ActiveSupport::TestCase
Rails.stub :root, Pathname.getwd do
new_test.stub :passed?, false do
new_test.stub :skipped?, true do
- assert_equal "tmp/screenshots/x.png", new_test.send(:image_path)
+ assert_equal Rails.root.join("tmp/screenshots/x.png").to_s, new_test.send(:image_path)
end
end
end
@@ -41,29 +42,27 @@ class ScreenshotHelperTest < ActiveSupport::TestCase
end
test "display_image return artifact format when specify RAILS_SYSTEM_TESTING_SCREENSHOT environment" do
- begin
- original_output_type = ENV["RAILS_SYSTEM_TESTING_SCREENSHOT"]
- ENV["RAILS_SYSTEM_TESTING_SCREENSHOT"] = "artifact"
+ original_output_type = ENV["RAILS_SYSTEM_TESTING_SCREENSHOT"]
+ ENV["RAILS_SYSTEM_TESTING_SCREENSHOT"] = "artifact"
- new_test = DrivenBySeleniumWithChrome.new("x")
+ new_test = DrivenBySeleniumWithChrome.new("x")
- assert_equal "artifact", new_test.send(:output_type)
+ assert_equal "artifact", new_test.send(:output_type)
- Rails.stub :root, Pathname.getwd do
- new_test.stub :passed?, false do
- assert_match %r|url=artifact://.+?tmp/screenshots/failures_x\.png|, new_test.send(:display_image)
- end
+ Rails.stub :root, Pathname.getwd do
+ new_test.stub :passed?, false do
+ assert_match %r|url=artifact://.+?tmp/screenshots/failures_x\.png|, new_test.send(:display_image)
end
- ensure
- ENV["RAILS_SYSTEM_TESTING_SCREENSHOT"] = original_output_type
end
+ ensure
+ ENV["RAILS_SYSTEM_TESTING_SCREENSHOT"] = original_output_type
end
- test "image path returns the relative path from current directory" do
+ test "image path returns the absolute path from root" do
new_test = DrivenBySeleniumWithChrome.new("x")
Rails.stub :root, Pathname.getwd.join("..") do
- assert_equal "../tmp/screenshots/x.png", new_test.send(:image_path)
+ assert_equal Rails.root.join("tmp/screenshots/x.png").to_s, new_test.send(:image_path)
end
end
end
diff --git a/actionpack/test/dispatch/system_testing/server_test.rb b/actionpack/test/dispatch/system_testing/server_test.rb
index 95e411faf4..740e90a4da 100644
--- a/actionpack/test/dispatch/system_testing/server_test.rb
+++ b/actionpack/test/dispatch/system_testing/server_test.rb
@@ -17,7 +17,7 @@ class ServerTest < ActiveSupport::TestCase
test "server is changed from `default` to `puma`" do
Capybara.server = :default
ActionDispatch::SystemTesting::Server.new.run
- refute_equal Capybara.server, Capybara.servers[:default]
+ assert_not_equal Capybara.server, Capybara.servers[:default]
end
test "server is not changed to `puma` when is different than default" do
diff --git a/actionpack/test/dispatch/system_testing/system_test_case_test.rb b/actionpack/test/dispatch/system_testing/system_test_case_test.rb
index b078a5abc5..847b09dcfe 100644
--- a/actionpack/test/dispatch/system_testing/system_test_case_test.rb
+++ b/actionpack/test/dispatch/system_testing/system_test_case_test.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require "abstract_unit"
+require "selenium/webdriver"
class SetDriverToRackTestTest < DrivenByRackTest
test "uses rack_test" do
diff --git a/actionpack/test/dispatch/test_response_test.rb b/actionpack/test/dispatch/test_response_test.rb
index f0b8f7785d..2629a61057 100644
--- a/actionpack/test/dispatch/test_response_test.rb
+++ b/actionpack/test/dispatch/test_response_test.rb
@@ -27,11 +27,4 @@ class TestResponseTest < ActiveSupport::TestCase
response = ActionDispatch::TestResponse.create(200, { "Content-Type" => "application/json" }, '{ "foo": "fighters" }')
assert_equal({ "foo" => "fighters" }, response.parsed_body)
end
-
- test "response status aliases deprecated" do
- response = ActionDispatch::TestResponse.create
- assert_deprecated { response.success? }
- assert_deprecated { response.missing? }
- assert_deprecated { response.error? }
- end
end
diff --git a/actionpack/test/dispatch/uploaded_file_test.rb b/actionpack/test/dispatch/uploaded_file_test.rb
index 24c7135c7e..21169fcb5c 100644
--- a/actionpack/test/dispatch/uploaded_file_test.rb
+++ b/actionpack/test/dispatch/uploaded_file_test.rb
@@ -100,14 +100,20 @@ module ActionDispatch
def test_delegate_eof_to_tempfile
tf = Class.new { def eof?; true end; }
uf = Http::UploadedFile.new(tempfile: tf.new)
- assert uf.eof?
+ 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)
- assert uf.respond_to?(:headers), "responds to headers"
- assert uf.respond_to?(:read), "responds to read"
+ assert_respond_to uf, :headers
+ assert_respond_to uf, :read
end
end
end
diff --git a/actionpack/test/fixtures/alternate_helpers/foo_helper.rb b/actionpack/test/fixtures/alternate_helpers/foo_helper.rb
index 3aadb6145e..c1a995af5f 100644
--- a/actionpack/test/fixtures/alternate_helpers/foo_helper.rb
+++ b/actionpack/test/fixtures/alternate_helpers/foo_helper.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module FooHelper
- redefine_method(:baz) {}
+ redefine_method(:baz) { }
end
diff --git a/actionpack/test/fixtures/functional_caching/_formatted_partial.html.erb b/actionpack/test/fixtures/functional_caching/_formatted_partial.html.erb
new file mode 100644
index 0000000000..aad73c0d6b
--- /dev/null
+++ b/actionpack/test/fixtures/functional_caching/_formatted_partial.html.erb
@@ -0,0 +1 @@
+<p>Hello!</p>
diff --git a/actionpack/test/fixtures/functional_caching/xml_fragment_cached_with_html_partial.xml.builder b/actionpack/test/fixtures/functional_caching/xml_fragment_cached_with_html_partial.xml.builder
new file mode 100644
index 0000000000..2bdda3af18
--- /dev/null
+++ b/actionpack/test/fixtures/functional_caching/xml_fragment_cached_with_html_partial.xml.builder
@@ -0,0 +1,5 @@
+cache do
+ xml.title "Hello!"
+end
+
+xml.body cdata_section(render("formatted_partial"))
diff --git a/actionpack/test/fixtures/public/foo/さようなら.html b/actionpack/test/fixtures/public/foo/さようなら.html
new file mode 100644
index 0000000000..627bb2469f
--- /dev/null
+++ b/actionpack/test/fixtures/public/foo/さようなら.html
@@ -0,0 +1 @@
+means goodbye in Japanese
diff --git a/actionpack/test/fixtures/public/foo/さようなら.html.gz b/actionpack/test/fixtures/public/foo/さようなら.html.gz
new file mode 100644
index 0000000000..4f484cfe86
--- /dev/null
+++ b/actionpack/test/fixtures/public/foo/さようなら.html.gz
Binary files differ
diff --git a/actionpack/test/fixtures/公共/foo/さようなら.html b/actionpack/test/fixtures/公共/foo/さようなら.html
new file mode 100644
index 0000000000..627bb2469f
--- /dev/null
+++ b/actionpack/test/fixtures/公共/foo/さようなら.html
@@ -0,0 +1 @@
+means goodbye in Japanese
diff --git a/actionpack/test/fixtures/公共/foo/さようなら.html.gz b/actionpack/test/fixtures/公共/foo/さようなら.html.gz
new file mode 100644
index 0000000000..4f484cfe86
--- /dev/null
+++ b/actionpack/test/fixtures/公共/foo/さようなら.html.gz
Binary files differ
diff --git a/actionpack/test/journey/nodes/symbol_test.rb b/actionpack/test/journey/nodes/symbol_test.rb
index 1e687acef2..b0622ac71a 100644
--- a/actionpack/test/journey/nodes/symbol_test.rb
+++ b/actionpack/test/journey/nodes/symbol_test.rb
@@ -8,10 +8,10 @@ module ActionDispatch
class TestSymbol < ActiveSupport::TestCase
def test_default_regexp?
sym = Symbol.new "foo"
- assert sym.default_regexp?
+ assert_predicate sym, :default_regexp?
sym.regexp = nil
- assert_not sym.default_regexp?
+ assert_not_predicate sym, :default_regexp?
end
end
end
diff --git a/actionpack/test/journey/path/pattern_test.rb b/actionpack/test/journey/path/pattern_test.rb
index 3e7aea57f1..fcfaba96b0 100644
--- a/actionpack/test/journey/path/pattern_test.rb
+++ b/actionpack/test/journey/path/pattern_test.rb
@@ -34,17 +34,17 @@ module ActionDispatch
end
{
- "/:controller(/:action)" => %r{\A/(#{x})(?:/([^/.?]+))?},
- "/:controller/foo" => %r{\A/(#{x})/foo},
- "/:controller/:action" => %r{\A/(#{x})/([^/.?]+)},
- "/:controller" => %r{\A/(#{x})},
- "/:controller(/:action(/:id))" => %r{\A/(#{x})(?:/([^/.?]+)(?:/([^/.?]+))?)?},
- "/:controller/:action.xml" => %r{\A/(#{x})/([^/.?]+)\.xml},
- "/:controller.:format" => %r{\A/(#{x})\.([^/.?]+)},
- "/:controller(.:format)" => %r{\A/(#{x})(?:\.([^/.?]+))?},
- "/:controller/*foo" => %r{\A/(#{x})/(.+)},
- "/:controller/*foo/bar" => %r{\A/(#{x})/(.+)/bar},
- "/:foo|*bar" => %r{\A/(?:([^/.?]+)|(.+))},
+ "/:controller(/:action)" => %r{\A/(#{x})(?:/([^/.?]+))?(?:\b|\Z)},
+ "/:controller/foo" => %r{\A/(#{x})/foo(?:\b|\Z)},
+ "/:controller/:action" => %r{\A/(#{x})/([^/.?]+)(?:\b|\Z)},
+ "/:controller" => %r{\A/(#{x})(?:\b|\Z)},
+ "/:controller(/:action(/:id))" => %r{\A/(#{x})(?:/([^/.?]+)(?:/([^/.?]+))?)?(?:\b|\Z)},
+ "/:controller/:action.xml" => %r{\A/(#{x})/([^/.?]+)\.xml(?:\b|\Z)},
+ "/:controller.:format" => %r{\A/(#{x})\.([^/.?]+)(?:\b|\Z)},
+ "/:controller(.:format)" => %r{\A/(#{x})(?:\.([^/.?]+))?(?:\b|\Z)},
+ "/:controller/*foo" => %r{\A/(#{x})/(.+)(?:\b|\Z)},
+ "/:controller/*foo/bar" => %r{\A/(#{x})/(.+)/bar(?:\b|\Z)},
+ "/:foo|*bar" => %r{\A/(?:([^/.?]+)|(.+))(?:\b|\Z)},
}.each do |path, expected|
define_method(:"test_to_non_anchored_regexp_#{Regexp.escape(path)}") do
path = Pattern.build(
diff --git a/actionpack/test/journey/route/definition/scanner_test.rb b/actionpack/test/journey/route/definition/scanner_test.rb
index 070886c7df..092177d315 100644
--- a/actionpack/test/journey/route/definition/scanner_test.rb
+++ b/actionpack/test/journey/route/definition/scanner_test.rb
@@ -10,61 +10,70 @@ module ActionDispatch
@scanner = Scanner.new
end
- # /page/:id(/:action)(.:format)
- def test_tokens
- [
- ["/", [[:SLASH, "/"]]],
- ["*omg", [[:STAR, "*omg"]]],
- ["/page", [[:SLASH, "/"], [:LITERAL, "page"]]],
- ["/page!", [[:SLASH, "/"], [:LITERAL, "page!"]]],
- ["/page$", [[:SLASH, "/"], [:LITERAL, "page$"]]],
- ["/page&", [[:SLASH, "/"], [:LITERAL, "page&"]]],
- ["/page'", [[:SLASH, "/"], [:LITERAL, "page'"]]],
- ["/page*", [[:SLASH, "/"], [:LITERAL, "page*"]]],
- ["/page+", [[:SLASH, "/"], [:LITERAL, "page+"]]],
- ["/page,", [[:SLASH, "/"], [:LITERAL, "page,"]]],
- ["/page;", [[:SLASH, "/"], [:LITERAL, "page;"]]],
- ["/page=", [[:SLASH, "/"], [:LITERAL, "page="]]],
- ["/page@", [[:SLASH, "/"], [:LITERAL, "page@"]]],
- ['/page\:', [[:SLASH, "/"], [:LITERAL, "page:"]]],
- ['/page\(', [[:SLASH, "/"], [:LITERAL, "page("]]],
- ['/page\)', [[:SLASH, "/"], [:LITERAL, "page)"]]],
- ["/~page", [[:SLASH, "/"], [:LITERAL, "~page"]]],
- ["/pa-ge", [[:SLASH, "/"], [:LITERAL, "pa-ge"]]],
- ["/:page", [[:SLASH, "/"], [:SYMBOL, ":page"]]],
- ["/(:page)", [
+ CASES = [
+ ["/", [[:SLASH, "/"]]],
+ ["*omg", [[:STAR, "*omg"]]],
+ ["/page", [[:SLASH, "/"], [:LITERAL, "page"]]],
+ ["/page!", [[:SLASH, "/"], [:LITERAL, "page!"]]],
+ ["/page$", [[:SLASH, "/"], [:LITERAL, "page$"]]],
+ ["/page&", [[:SLASH, "/"], [:LITERAL, "page&"]]],
+ ["/page'", [[:SLASH, "/"], [:LITERAL, "page'"]]],
+ ["/page*", [[:SLASH, "/"], [:LITERAL, "page*"]]],
+ ["/page+", [[:SLASH, "/"], [:LITERAL, "page+"]]],
+ ["/page,", [[:SLASH, "/"], [:LITERAL, "page,"]]],
+ ["/page;", [[:SLASH, "/"], [:LITERAL, "page;"]]],
+ ["/page=", [[:SLASH, "/"], [:LITERAL, "page="]]],
+ ["/page@", [[:SLASH, "/"], [:LITERAL, "page@"]]],
+ ['/page\:', [[:SLASH, "/"], [:LITERAL, "page:"]]],
+ ['/page\(', [[:SLASH, "/"], [:LITERAL, "page("]]],
+ ['/page\)', [[:SLASH, "/"], [:LITERAL, "page)"]]],
+ ["/~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, "("],
+ [:SYMBOL, ":page"],
+ [:RPAREN, ")"],
+ ]],
+ ["(/:action)", [
+ [:LPAREN, "("],
[:SLASH, "/"],
+ [:SYMBOL, ":action"],
+ [:RPAREN, ")"],
+ ]],
+ ["(())", [[:LPAREN, "("],
+ [:LPAREN, "("], [:RPAREN, ")"], [:RPAREN, ")"]]],
+ ["(.:format)", [
[:LPAREN, "("],
- [:SYMBOL, ":page"],
+ [:DOT, "."],
+ [:SYMBOL, ":format"],
[:RPAREN, ")"],
]],
- ["(/:action)", [
- [:LPAREN, "("],
- [:SLASH, "/"],
- [:SYMBOL, ":action"],
- [:RPAREN, ")"],
- ]],
- ["(())", [[:LPAREN, "("],
- [:LPAREN, "("], [:RPAREN, ")"], [:RPAREN, ")"]]],
- ["(.:format)", [
- [:LPAREN, "("],
- [:DOT, "."],
- [:SYMBOL, ":format"],
- [:RPAREN, ")"],
- ]],
- ].each do |str, expected|
- @scanner.scan_setup str
- assert_tokens expected, @scanner
+ ]
+
+ CASES.each do |pattern, expected_tokens|
+ test "Scanning `#{pattern}`" do
+ @scanner.scan_setup pattern
+ assert_tokens expected_tokens, @scanner, pattern
end
end
- def assert_tokens(tokens, scanner)
- toks = []
- while tok = scanner.next_token
- toks << tok
+ private
+
+ def assert_tokens(expected_tokens, scanner, pattern)
+ actual_tokens = []
+ while token = scanner.next_token
+ actual_tokens << token
+ end
+ assert_equal expected_tokens, actual_tokens, "Wrong tokens for `#{pattern}`"
end
- assert_equal tokens, toks
- end
end
end
end
diff --git a/actionpack/test/journey/router/utils_test.rb b/actionpack/test/journey/router/utils_test.rb
index 2d09098f11..472f1bf35e 100644
--- a/actionpack/test/journey/router/utils_test.rb
+++ b/actionpack/test/journey/router/utils_test.rb
@@ -23,7 +23,7 @@ module ActionDispatch
end
def test_uri_unescape_with_utf8_string
- assert_equal "Šašinková", Utils.unescape_uri("%C5%A0a%C5%A1inkov%C3%A1".dup.force_encoding(Encoding::US_ASCII))
+ assert_equal "Šašinková", Utils.unescape_uri((+"%C5%A0a%C5%A1inkov%C3%A1").force_encoding(Encoding::US_ASCII))
end
def test_normalize_path_not_greedy
diff --git a/actionpack/test/journey/router_test.rb b/actionpack/test/journey/router_test.rb
index 183f421bcf..f8d89def6a 100644
--- a/actionpack/test/journey/router_test.rb
+++ b/actionpack/test/journey/router_test.rb
@@ -284,7 +284,7 @@ module ActionDispatch
def test_generate_missing_keys_no_matches_different_format_keys
get "/:controller/:action/:name", to: "foo#bar"
- primarty_parameters = {
+ primary_parameters = {
id: 1,
controller: "tasks",
action: "show",
@@ -297,9 +297,9 @@ module ActionDispatch
missing_parameters = {
missing_key => "task_1"
}
- request_parameters = primarty_parameters.merge(redirection_parameters).merge(missing_parameters)
+ request_parameters = primary_parameters.merge(redirection_parameters).merge(missing_parameters)
- message = "No route matches #{Hash[request_parameters.sort_by { |k, v|k.to_s }].inspect}, missing required keys: #{[missing_key.to_sym].inspect}"
+ message = "No route matches #{Hash[request_parameters.sort_by { |k, _|k.to_s }].inspect}, missing required keys: #{[missing_key.to_sym].inspect}"
error = assert_raises(ActionController::UrlGenerationError) do
@formatter.generate(
@@ -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)
diff --git a/actionpack/test/journey/routes_test.rb b/actionpack/test/journey/routes_test.rb
index 81ce07526f..d5c81a8421 100644
--- a/actionpack/test/journey/routes_test.rb
+++ b/actionpack/test/journey/routes_test.rb
@@ -17,11 +17,11 @@ module ActionDispatch
def test_clear
mapper.get "/foo(/:id)", to: "foo#bar", as: "aaron"
- assert_not_predicate routes, :empty?
+ assert_not_empty routes
assert_equal 1, routes.length
routes.clear
- assert routes.empty?
+ assert_empty routes
assert_equal 0, routes.length
end
@@ -43,7 +43,7 @@ module ActionDispatch
mapper.get "/foo(/:id)", to: "foo#bar", as: "aaron"
assert_equal 1, @routes.anchored_routes.length
- assert_predicate @routes.custom_routes, :empty?
+ assert_empty @routes.custom_routes
mapper.get "/hello/:who", to: "foo#bar", as: "bar", who: /\d/
diff --git a/actionpack/test/tmp/.gitignore b/actionpack/test/tmp/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/actionpack/test/tmp/.gitignore
+++ /dev/null