aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/journey/path/pattern.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb9
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_view.rb8
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb24
-rw-r--r--actionpack/lib/action_dispatch/middleware/host_authorization.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/show_exceptions.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb2
-rw-r--r--actionpack/lib/action_dispatch/routing.rb28
-rw-r--r--actionpack/lib/action_dispatch/system_test_case.rb24
-rw-r--r--actionpack/lib/action_dispatch/system_testing/browser.rb22
-rw-r--r--actionpack/lib/action_dispatch/system_testing/driver.rb9
-rw-r--r--actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb2
16 files changed, 94 insertions, 54 deletions
diff --git a/actionpack/lib/action_dispatch/journey/path/pattern.rb b/actionpack/lib/action_dispatch/journey/path/pattern.rb
index 537f479ee5..697f5b9d8b 100644
--- a/actionpack/lib/action_dispatch/journey/path/pattern.rb
+++ b/actionpack/lib/action_dispatch/journey/path/pattern.rb
@@ -119,7 +119,7 @@ module ActionDispatch
class UnanchoredRegexp < AnchoredRegexp # :nodoc:
def accept(node)
- %r{\A#{visit node}}
+ %r{\A#{visit node}(?:\b|\Z)}
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index cb28baa229..1611a8b3dd 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -488,13 +488,8 @@ module ActionDispatch
end
def cookie_metadata(name, options)
- if request.use_cookies_with_metadata
- metadata = expiry_options(options)
- metadata[:purpose] = "cookie.#{name}"
-
- metadata
- else
- {}
+ expiry_options(options).tap do |metadata|
+ metadata[:purpose] = "cookie.#{name}" if request.use_cookies_with_metadata
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/debug_view.rb b/actionpack/lib/action_dispatch/middleware/debug_view.rb
index ac12dc13a1..f16484d1ea 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_view.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_view.rb
@@ -10,7 +10,13 @@ module ActionDispatch
RESCUES_TEMPLATE_PATH = File.expand_path("templates", __dir__)
def initialize(assigns)
- super([RESCUES_TEMPLATE_PATH], assigns)
+ paths = [RESCUES_TEMPLATE_PATH]
+ renderer = ActionView::Renderer.new ActionView::LookupContext.new(paths)
+ super(renderer, assigns)
+ end
+
+ def compiled_method_container
+ self.class
end
def debug_params(params)
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index fb2b2bd3b0..1fb3e9db00 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -31,22 +31,34 @@ module ActionDispatch
"ActionController::MissingExactTemplate" => "missing_exact_template",
)
+ cattr_accessor :wrapper_exceptions, default: [
+ "ActionView::Template::Error"
+ ]
+
attr_reader :backtrace_cleaner, :exception, :wrapped_causes, :line_number, :file
def initialize(backtrace_cleaner, exception)
@backtrace_cleaner = backtrace_cleaner
- @exception = original_exception(exception)
+ @exception = exception
@wrapped_causes = wrapped_causes_for(exception, backtrace_cleaner)
expand_backtrace if exception.is_a?(SyntaxError) || exception.cause.is_a?(SyntaxError)
end
+ def unwrapped_exception
+ if wrapper_exceptions.include?(exception.class.to_s)
+ exception.cause
+ else
+ exception
+ end
+ end
+
def rescue_template
@@rescue_templates[@exception.class.name]
end
def status_code
- self.class.status_code_for_exception(@exception.class.name)
+ self.class.status_code_for_exception(unwrapped_exception.class.name)
end
def application_trace
@@ -122,14 +134,6 @@ module ActionDispatch
Array(@exception.backtrace)
end
- def original_exception(exception)
- if @@rescue_responses.has_key?(exception.cause.class.name)
- exception.cause
- else
- exception
- end
- end
-
def causes_for(exception)
return enum_for(__method__, exception) unless block_given?
diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb
index 447b70112a..b7dff1df41 100644
--- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb
+++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb
@@ -3,8 +3,8 @@
require "action_dispatch/http/request"
module ActionDispatch
- # This middleware guards from DNS rebinding attacks by white-listing the
- # hosts a request can be sent to.
+ # This middleware guards from DNS rebinding attacks by explicitly permitting
+ # the hosts a request can be sent to.
#
# When a request comes to an unauthorized host, the +response_app+
# application will be executed and rendered. If no +response_app+ is given, a
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
index 3c88afd4d3..767143a368 100644
--- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -45,7 +45,7 @@ module ActionDispatch
backtrace_cleaner = request.get_header "action_dispatch.backtrace_cleaner"
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
status = wrapper.status_code
- request.set_header "action_dispatch.exception", wrapper.exception
+ request.set_header "action_dispatch.exception", wrapper.unwrapped_exception
request.set_header "action_dispatch.original_path", request.path_info
request.path_info = "/#{status}"
response = @exceptions_app.call(request.env)
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb
index 2fa78dd385..1fbc107e28 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb
@@ -2,6 +2,6 @@
<h1>Blocked host: <%= @host %></h1>
</header>
<div id="container">
- <h2>To allow requests to <%= @host %>, add the following configuration:</h2>
- <pre>Rails.application.config.hosts &lt;&lt; "<%= @host %>"</pre>
+ <h2>To allow requests to <%= @host %>, add the following to your environment configuration:</h2>
+ <pre>config.hosts &lt;&lt; "<%= @host %>"</pre>
</div>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb
index 4e2d1d0b08..a94dd982a7 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb
@@ -1,5 +1,5 @@
Blocked host: <%= @host %>
-To allow requests to <%= @host %>, add the following configuration:
+To allow requests to <%= @host %>, add the following to your environment configuration:
- Rails.application.config.hosts << "<%= @host %>"
+ config.hosts << "<%= @host %>"
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb
index e8454acfad..d144fc1cd2 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb
@@ -10,7 +10,7 @@
<div id="container">
<h2>
<%= h @exception.message %>
- <% if @exception.message.match? %r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}} %>
+ <% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
<br />To resolve this issue run: rails active_storage:install
<% end %>
</h2>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb
index e5e3196710..55aaf58713 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb
@@ -4,7 +4,7 @@
<% end %>
<%= @exception.message %>
-<% if @exception.message.match? %r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}} %>
+<% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
To resolve this issue run: rails active_storage:install
<% end %>
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index 5cde677051..f832719f19 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -74,8 +74,8 @@ module ActionDispatch
# For routes that don't fit the <tt>resources</tt> mold, you can use the HTTP helper
# methods <tt>get</tt>, <tt>post</tt>, <tt>patch</tt>, <tt>put</tt> and <tt>delete</tt>.
#
- # get 'post/:id' => 'posts#show'
- # post 'post/:id' => 'posts#create_comment'
+ # get 'post/:id', to: 'posts#show'
+ # post 'post/:id', to: 'posts#create_comment'
#
# Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same
# URL will route to the <tt>show</tt> action.
@@ -83,7 +83,7 @@ module ActionDispatch
# If your route needs to respond to more than one HTTP method (or all methods) then using the
# <tt>:via</tt> option on <tt>match</tt> is preferable.
#
- # match 'post/:id' => 'posts#show', via: [:get, :post]
+ # match 'post/:id', to: 'posts#show', via: [:get, :post]
#
# == Named routes
#
@@ -94,7 +94,7 @@ module ActionDispatch
# Example:
#
# # In config/routes.rb
- # get '/login' => 'accounts#login', as: 'login'
+ # get '/login', to: 'accounts#login', as: 'login'
#
# # With render, redirect_to, tests, etc.
# redirect_to login_url
@@ -120,9 +120,9 @@ module ActionDispatch
#
# # In config/routes.rb
# controller :blog do
- # get 'blog/show' => :list
- # get 'blog/delete' => :delete
- # get 'blog/edit' => :edit
+ # get 'blog/show', to: :list
+ # get 'blog/delete', to: :delete
+ # get 'blog/edit', to: :edit
# end
#
# # provides named routes for show, delete, and edit
@@ -132,7 +132,7 @@ module ActionDispatch
#
# Routes can generate pretty URLs. For example:
#
- # get '/articles/:year/:month/:day' => 'articles#find_by_id', constraints: {
+ # get '/articles/:year/:month/:day', to: 'articles#find_by_id', constraints: {
# year: /\d{4}/,
# month: /\d{1,2}/,
# day: /\d{1,2}/
@@ -147,7 +147,7 @@ module ActionDispatch
# You can specify a regular expression to define a format for a parameter.
#
# controller 'geocode' do
- # get 'geocode/:postalcode' => :show, constraints: {
+ # get 'geocode/:postalcode', to: :show, constraints: {
# postalcode: /\d{5}(-\d{4})?/
# }
# end
@@ -156,13 +156,13 @@ module ActionDispatch
# expression modifiers:
#
# controller 'geocode' do
- # get 'geocode/:postalcode' => :show, constraints: {
+ # get 'geocode/:postalcode', to: :show, constraints: {
# postalcode: /hx\d\d\s\d[a-z]{2}/i
# }
# end
#
# controller 'geocode' do
- # get 'geocode/:postalcode' => :show, constraints: {
+ # get 'geocode/:postalcode', to: :show, constraints: {
# postalcode: /# Postalcode format
# \d{5} #Prefix
# (-\d{4})? #Suffix
@@ -178,13 +178,13 @@ module ActionDispatch
#
# You can redirect any path to another path using the redirect helper in your router:
#
- # get "/stories" => redirect("/posts")
+ # get "/stories", to: redirect("/posts")
#
# == Unicode character routes
#
# You can specify unicode character routes in your router:
#
- # get "こんにちは" => "welcome#index"
+ # get "こんにちは", to: "welcome#index"
#
# == Routing to Rack Applications
#
@@ -192,7 +192,7 @@ module ActionDispatch
# index action in the PostsController, you can specify any Rack application
# as the endpoint for a matcher:
#
- # get "/application.js" => Sprockets
+ # get "/application.js", to: Sprockets
#
# == Reloading routes
#
diff --git a/actionpack/lib/action_dispatch/system_test_case.rb b/actionpack/lib/action_dispatch/system_test_case.rb
index c74c0ccced..066daa4a12 100644
--- a/actionpack/lib/action_dispatch/system_test_case.rb
+++ b/actionpack/lib/action_dispatch/system_test_case.rb
@@ -89,6 +89,24 @@ module ActionDispatch
# { js_errors: true }
# end
#
+ # Some drivers require browser capabilities to be passed as a block instead
+ # of through the +options+ hash.
+ #
+ # As an example, if you want to add mobile emulation on chrome, you'll have to
+ # create an instance of selenium's +Chrome::Options+ object and add
+ # capabilities with a block.
+ #
+ # The block will be passed an instance of <tt><Driver>::Options</tt> where you can
+ # define the capabilities you want. Please refer to your driver documentation
+ # to learn about supported options.
+ #
+ # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+ # driven_by :selenium, using: :chrome, screen_size: [1024, 768] do |driver_option|
+ # driver_option.add_emulation(device_name: 'iPhone 6')
+ # driver_option.add_extension('path/to/chrome_extension.crx')
+ # end
+ # end
+ #
# Because <tt>ActionDispatch::SystemTestCase</tt> is a shim between Capybara
# and Rails, any driver that is supported by Capybara is supported by system
# tests as long as you include the required gems and files.
@@ -134,8 +152,10 @@ module ActionDispatch
# driven_by :selenium, using: :firefox
#
# driven_by :selenium, using: :headless_firefox
- def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {})
- self.driver = SystemTesting::Driver.new(driver, using: using, screen_size: screen_size, options: options)
+ def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {}, &capabilities)
+ driver_options = { using: using, screen_size: screen_size, options: options }
+
+ self.driver = SystemTesting::Driver.new(driver, driver_options, &capabilities)
end
driven_by :selenium
diff --git a/actionpack/lib/action_dispatch/system_testing/browser.rb b/actionpack/lib/action_dispatch/system_testing/browser.rb
index 1b0bce6b9e..c34907b6cb 100644
--- a/actionpack/lib/action_dispatch/system_testing/browser.rb
+++ b/actionpack/lib/action_dispatch/system_testing/browser.rb
@@ -29,20 +29,28 @@ module ActionDispatch
end
end
+ def capabilities
+ @option ||=
+ case type
+ when :chrome
+ ::Selenium::WebDriver::Chrome::Options.new
+ when :firefox
+ ::Selenium::WebDriver::Firefox::Options.new
+ end
+ end
+
private
def headless_chrome_browser_options
- options = Selenium::WebDriver::Chrome::Options.new
- options.args << "--headless"
- options.args << "--disable-gpu" if Gem.win_platform?
+ capabilities.args << "--headless"
+ capabilities.args << "--disable-gpu" if Gem.win_platform?
- options
+ capabilities
end
def headless_firefox_browser_options
- options = Selenium::WebDriver::Firefox::Options.new
- options.args << "-headless"
+ capabilities.args << "-headless"
- options
+ capabilities
end
end
end
diff --git a/actionpack/lib/action_dispatch/system_testing/driver.rb b/actionpack/lib/action_dispatch/system_testing/driver.rb
index 5252ff6746..25a09dd918 100644
--- a/actionpack/lib/action_dispatch/system_testing/driver.rb
+++ b/actionpack/lib/action_dispatch/system_testing/driver.rb
@@ -3,11 +3,12 @@
module ActionDispatch
module SystemTesting
class Driver # :nodoc:
- def initialize(name, **options)
+ def initialize(name, **options, &capabilities)
@name = name
@browser = Browser.new(options[:using])
@screen_size = options[:screen_size]
@options = options[:options]
+ @capabilities = capabilities
end
def use
@@ -22,6 +23,8 @@ module ActionDispatch
end
def register
+ define_browser_capabilities(@browser.capabilities)
+
Capybara.register_driver @name do |app|
case @name
when :selenium then register_selenium(app)
@@ -31,6 +34,10 @@ module ActionDispatch
end
end
+ def define_browser_capabilities(capabilities)
+ @capabilities.call(capabilities) if @capabilities
+ end
+
def browser_options
@options.merge(options: @browser.options).compact
end
diff --git a/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb b/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
index 884fb51d18..79359a0c8b 100644
--- a/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
+++ b/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb
@@ -20,7 +20,7 @@ module ActionDispatch
# * [+inline+] Display the screenshot in the terminal using the
# iTerm image protocol (https://iterm2.com/documentation-images.html).
# * [+artifact+] Display the screenshot in the terminal, using the terminal
- # artifact format (https://buildkite.github.io/terminal/inline-images/).
+ # artifact format (https://buildkite.github.io/terminal-to-html/inline-images/).
def take_screenshot
save_image
puts display_image
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 45439a3bb1..10d85037ae 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -335,7 +335,7 @@ module ActionDispatch
klass = APP_SESSIONS[app] ||= Class.new(Integration::Session) {
# If the app is a Rails app, make url_helpers available on the session.
# This makes app.url_for and app.foo_path available in the console.
- if app.respond_to?(:routes)
+ if app.respond_to?(:routes) && app.routes.is_a?(ActionDispatch::Routing::RouteSet)
include app.routes.url_helpers
include app.routes.mounted_helpers
end