aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/test
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/test')
-rw-r--r--actionpack/test/controller/parameters/accessors_test.rb8
-rw-r--r--actionpack/test/controller/resources_test.rb3
-rw-r--r--actionpack/test/dispatch/content_security_policy_test.rb78
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb23
-rw-r--r--actionpack/test/dispatch/feature_policy_test.rb142
-rw-r--r--actionpack/test/dispatch/system_testing/driver_test.rb13
6 files changed, 265 insertions, 2 deletions
diff --git a/actionpack/test/controller/parameters/accessors_test.rb b/actionpack/test/controller/parameters/accessors_test.rb
index cb49eeb1b7..3d1538ff64 100644
--- a/actionpack/test/controller/parameters/accessors_test.rb
+++ b/actionpack/test/controller/parameters/accessors_test.rb
@@ -284,12 +284,14 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
params1 = ActionController::Parameters.new(a: 1, b: 2)
params2 = ActionController::Parameters.new(a: 1, b: 2)
assert(params1 == params2)
+ assert(params1.hash == params2.hash)
end
test "is equal to Parameters instance with same permitted params" do
params1 = ActionController::Parameters.new(a: 1, b: 2).permit(:a)
params2 = ActionController::Parameters.new(a: 1, b: 2).permit(:a)
assert(params1 == params2)
+ assert(params1.hash == params2.hash)
end
test "is equal to Parameters instance with same different source params, but same permitted params" do
@@ -297,6 +299,8 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
params2 = ActionController::Parameters.new(a: 1, c: 3).permit(:a)
assert(params1 == params2)
assert(params2 == params1)
+ assert(params1.hash == params2.hash)
+ assert(params2.hash == params1.hash)
end
test "is not equal to an unpermitted Parameters instance with same params" do
@@ -304,6 +308,8 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
params2 = ActionController::Parameters.new(a: 1)
assert(params1 != params2)
assert(params2 != params1)
+ assert(params1.hash != params2.hash)
+ assert(params2.hash != params1.hash)
end
test "is not equal to Parameters instance with different permitted params" do
@@ -311,6 +317,8 @@ class ParametersAccessorsTest < ActiveSupport::TestCase
params2 = ActionController::Parameters.new(a: 1, b: 2).permit(:a)
assert(params1 != params2)
assert(params2 != params1)
+ assert(params1.hash != params2.hash)
+ assert(params2.hash != params1.hash)
end
test "equality with simple types works" do
diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb
index 1e42a3a90d..339025ec52 100644
--- a/actionpack/test/controller/resources_test.rb
+++ b/actionpack/test/controller/resources_test.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require "abstract_unit"
-require "active_support/core_ext/object/try"
require "active_support/core_ext/object/with_options"
require "active_support/core_ext/array/extract_options"
@@ -1249,7 +1248,7 @@ class ResourcesTest < ActionController::TestCase
shallow_path = "/#{options[:shallow] ? options[:namespace] : options[:path_prefix]}#{path}"
full_path = "/#{options[:path_prefix]}#{path}"
name_prefix = options[:name_prefix]
- shallow_prefix = options[:shallow] ? options[:namespace].try(:gsub, /\//, "_") : options[:name_prefix]
+ shallow_prefix = options[:shallow] ? options[:namespace]&.gsub(/\//, "_") : options[:name_prefix]
new_action = "new"
edit_action = "edit"
diff --git a/actionpack/test/dispatch/content_security_policy_test.rb b/actionpack/test/dispatch/content_security_policy_test.rb
index 30c340ae9e..3d60dc1661 100644
--- a/actionpack/test/dispatch/content_security_policy_test.rb
+++ b/actionpack/test/dispatch/content_security_policy_test.rb
@@ -128,12 +128,36 @@ class ContentSecurityPolicyTest < ActiveSupport::TestCase
@policy.script_src false
assert_no_match %r{script-src}, @policy.build
+ @policy.script_src_attr :self
+ assert_match %r{script-src-attr 'self'}, @policy.build
+
+ @policy.script_src_attr false
+ assert_no_match %r{script-src-attr}, @policy.build
+
+ @policy.script_src_elem :self
+ assert_match %r{script-src-elem 'self'}, @policy.build
+
+ @policy.script_src_elem false
+ assert_no_match %r{script-src-elem}, @policy.build
+
@policy.style_src :self
assert_match %r{style-src 'self'}, @policy.build
@policy.style_src false
assert_no_match %r{style-src}, @policy.build
+ @policy.style_src_attr :self
+ assert_match %r{style-src-attr 'self'}, @policy.build
+
+ @policy.style_src_attr false
+ assert_no_match %r{style-src-attr}, @policy.build
+
+ @policy.style_src_elem :self
+ assert_match %r{style-src-elem 'self'}, @policy.build
+
+ @policy.style_src_elem false
+ assert_no_match %r{style-src-elem}, @policy.build
+
@policy.worker_src :self
assert_match %r{worker-src 'self'}, @policy.build
@@ -542,3 +566,57 @@ class DisabledContentSecurityPolicyIntegrationTest < ActionDispatch::Integration
assert_equal "default-src https://example.com", response.headers["Content-Security-Policy"]
end
end
+
+class NonceDirectiveContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
+ class PolicyController < ActionController::Base
+ def index
+ head :ok
+ end
+ end
+
+ ROUTES = ActionDispatch::Routing::RouteSet.new
+ ROUTES.draw do
+ scope module: "nonce_directive_content_security_policy_integration_test" do
+ get "/", to: "policy#index"
+ end
+ end
+
+ POLICY = ActionDispatch::ContentSecurityPolicy.new do |p|
+ p.default_src -> { :self }
+ p.script_src -> { :https }
+ p.style_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.content_security_policy_nonce_directives"] = %w(script-src)
+ 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_generate_nonce_only_specified_in_nonce_directives
+ get "/"
+
+ assert_response :success
+ assert_match "script-src https: 'nonce-iyhD0Yc0W+c='", response.headers["Content-Security-Policy"]
+ assert_no_match "style-src https: 'nonce-iyhD0Yc0W+c='", response.headers["Content-Security-Policy"]
+ end
+end
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index 68817ccdea..fa629bc761 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -466,6 +466,8 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
end
test "logs exception backtrace when all lines silenced" do
+ @app = DevelopmentApp
+
output = StringIO.new
backtrace_cleaner = ActiveSupport::BacktraceCleaner.new
backtrace_cleaner.add_silencer { true }
@@ -478,6 +480,27 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
assert_operator((output.rewind && output.read).lines.count, :>, 10)
end
+ test "doesn't log the framework backtrace when error type is a routing error" do
+ @app = ProductionApp
+
+ output = StringIO.new
+ backtrace_cleaner = ActiveSupport::BacktraceCleaner.new
+ backtrace_cleaner.add_silencer { true }
+
+ env = { "action_dispatch.show_exceptions" => true,
+ "action_dispatch.logger" => Logger.new(output),
+ "action_dispatch.backtrace_cleaner" => backtrace_cleaner }
+
+ assert_raises ActionController::RoutingError do
+ get "/pass", headers: env
+ end
+
+ log = output.rewind && output.read
+
+ assert_includes log, "ActionController::RoutingError (No route matches [GET] \"/pass\")"
+ assert_equal 3, log.lines.count
+ end
+
test "display backtrace when error type is SyntaxError" do
@app = DevelopmentApp
diff --git a/actionpack/test/dispatch/feature_policy_test.rb b/actionpack/test/dispatch/feature_policy_test.rb
new file mode 100644
index 0000000000..ebcc8a8b6d
--- /dev/null
+++ b/actionpack/test/dispatch/feature_policy_test.rb
@@ -0,0 +1,142 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+
+class FeaturePolicyTest < ActiveSupport::TestCase
+ def setup
+ @policy = ActionDispatch::FeaturePolicy.new
+ end
+
+ def test_mappings
+ @policy.midi :self
+ assert_equal "midi 'self'", @policy.build
+
+ @policy.midi :none
+ assert_equal "midi 'none'", @policy.build
+ end
+
+ def test_multiple_sources_for_a_single_directive
+ @policy.geolocation :self, "https://example.com"
+ assert_equal "geolocation 'self' https://example.com", @policy.build
+ end
+
+ def test_single_directive_for_multiple_directives
+ @policy.geolocation :self
+ @policy.usb :none
+ assert_equal "geolocation 'self'; usb 'none'", @policy.build
+ end
+
+ def test_multiple_directives_for_multiple_directives
+ @policy.geolocation :self, "https://example.com"
+ @policy.usb :none, "https://example.com"
+ assert_equal "geolocation 'self' https://example.com; usb 'none' https://example.com", @policy.build
+ end
+
+ def test_invalid_directive_source
+ exception = assert_raises(ArgumentError) do
+ @policy.vr [:non_existent]
+ end
+
+ assert_equal "Invalid HTTP feature policy source: [:non_existent]", exception.message
+ end
+end
+
+class FeaturePolicyIntegrationTest < ActionDispatch::IntegrationTest
+ class PolicyController < ActionController::Base
+ feature_policy only: :index do |f|
+ f.gyroscope :none
+ end
+
+ feature_policy only: :sample_controller do |f|
+ f.gyroscope nil
+ f.usb :self
+ end
+
+ feature_policy only: :multiple_directives do |f|
+ f.gyroscope nil
+ f.usb :self
+ f.autoplay "https://example.com"
+ f.payment "https://secure.example.com"
+ end
+
+ def index
+ head :ok
+ end
+
+ def sample_controller
+ head :ok
+ end
+
+ def multiple_directives
+ head :ok
+ end
+ end
+
+ ROUTES = ActionDispatch::Routing::RouteSet.new
+ ROUTES.draw do
+ scope module: "feature_policy_integration_test" do
+ get "/", to: "policy#index"
+ get "/sample_controller", to: "policy#sample_controller"
+ get "/multiple_directives", to: "policy#multiple_directives"
+ end
+ end
+
+ POLICY = ActionDispatch::FeaturePolicy.new do |p|
+ p.gyroscope :self
+ end
+
+ class PolicyConfigMiddleware
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ env["action_dispatch.feature_policy"] = POLICY
+ env["action_dispatch.show_exceptions"] = false
+
+ @app.call(env)
+ end
+ end
+
+ APP = build_app(ROUTES) do |middleware|
+ middleware.use PolicyConfigMiddleware
+ middleware.use ActionDispatch::FeaturePolicy::Middleware
+ end
+
+ def app
+ APP
+ end
+
+ def test_generates_feature_policy_header
+ get "/"
+ assert_policy "gyroscope 'none'"
+ end
+
+ def test_generates_per_controller_feature_policy_header
+ get "/sample_controller"
+ assert_policy "usb 'self'"
+ end
+
+ def test_generates_multiple_directives_feature_policy_header
+ get "/multiple_directives"
+ assert_policy "usb 'self'; autoplay https://example.com; payment https://secure.example.com"
+ end
+
+ private
+ def env_config
+ Rails.application.env_config
+ end
+
+ def feature_policy
+ env_config["action_dispatch.feature_policy"]
+ end
+
+ def feature_policy=(policy)
+ env_config["action_dispatch.feature_policy"] = policy
+ end
+
+ def assert_policy(expected)
+ assert_response :success
+ assert_equal expected, response.headers["Feature-Policy"]
+ end
+end
diff --git a/actionpack/test/dispatch/system_testing/driver_test.rb b/actionpack/test/dispatch/system_testing/driver_test.rb
index 7ef306d04b..d3b16d0328 100644
--- a/actionpack/test/dispatch/system_testing/driver_test.rb
+++ b/actionpack/test/dispatch/system_testing/driver_test.rb
@@ -120,4 +120,17 @@ class DriverTest < ActiveSupport::TestCase
driver.use
end
end
+
+ test "preloads browser's driver_path" do
+ called = false
+
+ original_driver_path = ::Selenium::WebDriver::Chrome::Service.driver_path
+ ::Selenium::WebDriver::Chrome::Service.driver_path = -> { called = true }
+
+ ActionDispatch::SystemTesting::Driver.new(:selenium, screen_size: [1400, 1400], using: :chrome)
+
+ assert called
+ ensure
+ ::Selenium::WebDriver::Chrome::Service.driver_path = original_driver_path
+ end
end