actionpack 6.1.7.5 → 7.1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +355 -435
- data/MIT-LICENSE +2 -1
- data/README.rdoc +6 -7
- data/lib/abstract_controller/asset_paths.rb +1 -1
- data/lib/abstract_controller/base.rb +33 -37
- data/lib/abstract_controller/caching/fragments.rb +4 -2
- data/lib/abstract_controller/caching.rb +1 -1
- data/lib/abstract_controller/callbacks.rb +50 -11
- data/lib/abstract_controller/collector.rb +2 -2
- data/lib/abstract_controller/deprecator.rb +7 -0
- data/lib/abstract_controller/error.rb +1 -1
- data/lib/abstract_controller/helpers.rb +78 -30
- data/lib/abstract_controller/logger.rb +1 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +3 -16
- data/lib/abstract_controller/rendering.rb +12 -14
- data/lib/abstract_controller/translation.rb +26 -7
- data/lib/abstract_controller/url_for.rb +6 -6
- data/lib/abstract_controller.rb +6 -0
- data/lib/action_controller/api.rb +12 -10
- data/lib/action_controller/base.rb +8 -21
- data/lib/action_controller/caching.rb +2 -0
- data/lib/action_controller/deprecator.rb +7 -0
- data/lib/action_controller/form_builder.rb +4 -2
- data/lib/action_controller/log_subscriber.rb +20 -7
- data/lib/action_controller/metal/basic_implicit_render.rb +3 -1
- data/lib/action_controller/metal/conditional_get.rb +137 -102
- data/lib/action_controller/metal/content_security_policy.rb +37 -3
- data/lib/action_controller/metal/cookies.rb +1 -1
- data/lib/action_controller/metal/data_streaming.rb +25 -31
- data/lib/action_controller/metal/default_headers.rb +2 -0
- data/lib/action_controller/metal/etag_with_flash.rb +3 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
- data/lib/action_controller/metal/exceptions.rb +27 -30
- data/lib/action_controller/metal/flash.rb +6 -2
- data/lib/action_controller/metal/head.rb +9 -7
- data/lib/action_controller/metal/helpers.rb +5 -16
- data/lib/action_controller/metal/http_authentication.rb +78 -42
- data/lib/action_controller/metal/implicit_render.rb +5 -3
- data/lib/action_controller/metal/instrumentation.rb +62 -50
- data/lib/action_controller/metal/live.rb +67 -2
- data/lib/action_controller/metal/mime_responds.rb +5 -5
- data/lib/action_controller/metal/params_wrapper.rb +24 -13
- data/lib/action_controller/metal/permissions_policy.rb +20 -29
- data/lib/action_controller/metal/redirecting.rb +96 -23
- data/lib/action_controller/metal/renderers.rb +14 -15
- data/lib/action_controller/metal/rendering.rb +121 -16
- data/lib/action_controller/metal/request_forgery_protection.rb +208 -68
- data/lib/action_controller/metal/rescue.rb +7 -4
- data/lib/action_controller/metal/streaming.rb +74 -36
- data/lib/action_controller/metal/strong_parameters.rb +254 -151
- data/lib/action_controller/metal/testing.rb +9 -2
- data/lib/action_controller/metal/url_for.rb +10 -5
- data/lib/action_controller/metal.rb +89 -34
- data/lib/action_controller/railtie.rb +66 -9
- data/lib/action_controller/renderer.rb +99 -85
- data/lib/action_controller/test_case.rb +42 -11
- data/lib/action_controller.rb +10 -6
- data/lib/action_dispatch/constants.rb +32 -0
- data/lib/action_dispatch/deprecator.rb +7 -0
- data/lib/action_dispatch/http/cache.rb +21 -16
- data/lib/action_dispatch/http/content_security_policy.rb +122 -44
- data/lib/action_dispatch/http/filter_parameters.rb +14 -23
- data/lib/action_dispatch/http/headers.rb +3 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +25 -15
- data/lib/action_dispatch/http/mime_type.rb +43 -22
- data/lib/action_dispatch/http/mime_types.rb +3 -1
- data/lib/action_dispatch/http/parameters.rb +6 -6
- data/lib/action_dispatch/http/permissions_policy.rb +57 -19
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +75 -51
- data/lib/action_dispatch/http/response.rb +81 -77
- data/lib/action_dispatch/http/upload.rb +15 -2
- data/lib/action_dispatch/http/url.rb +11 -19
- data/lib/action_dispatch/journey/formatter.rb +8 -2
- data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
- data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
- data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
- data/lib/action_dispatch/journey/nodes/node.rb +70 -5
- data/lib/action_dispatch/journey/path/pattern.rb +36 -27
- data/lib/action_dispatch/journey/route.rb +8 -14
- data/lib/action_dispatch/journey/router/utils.rb +2 -2
- data/lib/action_dispatch/journey/router.rb +10 -9
- data/lib/action_dispatch/journey/routes.rb +5 -5
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/log_subscriber.rb +23 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -7
- data/lib/action_dispatch/middleware/assume_ssl.rb +24 -0
- data/lib/action_dispatch/middleware/callbacks.rb +2 -0
- data/lib/action_dispatch/middleware/cookies.rb +97 -107
- data/lib/action_dispatch/middleware/debug_exceptions.rb +31 -28
- data/lib/action_dispatch/middleware/debug_locks.rb +7 -4
- data/lib/action_dispatch/middleware/debug_view.rb +7 -2
- data/lib/action_dispatch/middleware/exception_wrapper.rb +190 -27
- data/lib/action_dispatch/middleware/executor.rb +3 -0
- data/lib/action_dispatch/middleware/flash.rb +24 -18
- data/lib/action_dispatch/middleware/host_authorization.rb +19 -20
- data/lib/action_dispatch/middleware/public_exceptions.rb +5 -3
- data/lib/action_dispatch/middleware/reloader.rb +7 -5
- data/lib/action_dispatch/middleware/remote_ip.rb +32 -19
- data/lib/action_dispatch/middleware/request_id.rb +5 -3
- data/lib/action_dispatch/middleware/server_timing.rb +76 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +6 -1
- data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +19 -13
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
- data/lib/action_dispatch/middleware/show_exceptions.rb +30 -25
- data/lib/action_dispatch/middleware/ssl.rb +18 -6
- data/lib/action_dispatch/middleware/stack.rb +34 -11
- data/lib/action_dispatch/middleware/static.rb +16 -16
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +5 -5
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +10 -5
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +7 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +9 -9
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +45 -18
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +6 -6
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +64 -55
- data/lib/action_dispatch/railtie.rb +20 -4
- data/lib/action_dispatch/request/session.rb +59 -19
- data/lib/action_dispatch/request/utils.rb +8 -3
- data/lib/action_dispatch/routing/inspector.rb +55 -7
- data/lib/action_dispatch/routing/mapper.rb +117 -107
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
- data/lib/action_dispatch/routing/redirection.rb +20 -8
- data/lib/action_dispatch/routing/route_set.rb +67 -27
- data/lib/action_dispatch/routing/routes_proxy.rb +11 -16
- data/lib/action_dispatch/routing/url_for.rb +29 -26
- data/lib/action_dispatch/routing.rb +12 -13
- data/lib/action_dispatch/system_test_case.rb +8 -8
- data/lib/action_dispatch/system_testing/browser.rb +20 -29
- data/lib/action_dispatch/system_testing/driver.rb +34 -18
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +35 -20
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
- data/lib/action_dispatch/testing/assertion_response.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +14 -7
- data/lib/action_dispatch/testing/assertions/routing.rb +70 -30
- data/lib/action_dispatch/testing/assertions.rb +3 -4
- data/lib/action_dispatch/testing/integration.rb +33 -25
- data/lib/action_dispatch/testing/request_encoder.rb +4 -1
- data/lib/action_dispatch/testing/test_process.rb +5 -30
- data/lib/action_dispatch/testing/test_request.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +34 -2
- data/lib/action_dispatch.rb +38 -4
- data/lib/action_pack/gem_version.rb +4 -4
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_pack.rb +1 -1
- metadata +67 -30
@@ -6,7 +6,6 @@ require "active_support/core_ext/module/redefine_method"
|
|
6
6
|
require "active_support/core_ext/module/remove_method"
|
7
7
|
require "active_support/core_ext/array/extract_options"
|
8
8
|
require "action_controller/metal/exceptions"
|
9
|
-
require "action_dispatch/http/request"
|
10
9
|
require "action_dispatch/routing/endpoint"
|
11
10
|
|
12
11
|
module ActionDispatch
|
@@ -35,20 +34,20 @@ module ActionDispatch
|
|
35
34
|
if @raise_on_name_error
|
36
35
|
raise
|
37
36
|
else
|
38
|
-
[404, {
|
37
|
+
[404, { Constants::X_CASCADE => "pass" }, []]
|
39
38
|
end
|
40
39
|
end
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
private
|
42
|
+
def controller(req)
|
43
|
+
req.controller_class
|
44
|
+
rescue NameError => e
|
45
|
+
raise ActionController::RoutingError, e.message, e.backtrace
|
46
|
+
end
|
48
47
|
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
def dispatch(controller, action, req, res)
|
49
|
+
controller.dispatch(action, req, res)
|
50
|
+
end
|
52
51
|
end
|
53
52
|
|
54
53
|
class StaticDispatcher < Dispatcher
|
@@ -132,8 +131,8 @@ module ActionDispatch
|
|
132
131
|
alias [] get
|
133
132
|
alias clear clear!
|
134
133
|
|
135
|
-
def each
|
136
|
-
routes.each
|
134
|
+
def each(&block)
|
135
|
+
routes.each(&block)
|
137
136
|
self
|
138
137
|
end
|
139
138
|
|
@@ -197,7 +196,9 @@ module ActionDispatch
|
|
197
196
|
def call(t, method_name, args, inner_options, url_strategy)
|
198
197
|
if args.size == arg_size && !inner_options && optimize_routes_generation?(t)
|
199
198
|
options = t.url_options.merge @options
|
200
|
-
|
199
|
+
path = optimized_helper(args)
|
200
|
+
path << "/" if options[:trailing_slash] && !path.end_with?("/")
|
201
|
+
options[:path] = path
|
201
202
|
|
202
203
|
original_script_name = options.delete(:original_script_name)
|
203
204
|
script_name = t._routes.find_script_name(options)
|
@@ -281,7 +282,7 @@ module ActionDispatch
|
|
281
282
|
|
282
283
|
if args.size < path_params_size
|
283
284
|
path_params -= controller_options.keys
|
284
|
-
path_params -= result.keys
|
285
|
+
path_params -= (result[:path_params] || {}).merge(result).keys
|
285
286
|
else
|
286
287
|
path_params = path_params.dup
|
287
288
|
end
|
@@ -374,6 +375,7 @@ module ActionDispatch
|
|
374
375
|
@disable_clear_and_finalize = false
|
375
376
|
@finalized = false
|
376
377
|
@env_key = "ROUTES_#{object_id}_SCRIPT_NAME"
|
378
|
+
@default_env = nil
|
377
379
|
|
378
380
|
@set = Journey::Routes.new
|
379
381
|
@router = Journey::Router.new @set
|
@@ -404,6 +406,25 @@ module ActionDispatch
|
|
404
406
|
end
|
405
407
|
private :make_request
|
406
408
|
|
409
|
+
def default_env
|
410
|
+
if default_url_options != @default_env&.[]("action_dispatch.routes.default_url_options")
|
411
|
+
url_options = default_url_options.dup.freeze
|
412
|
+
uri = URI(ActionDispatch::Http::URL.full_url_for(host: "example.org", **url_options))
|
413
|
+
|
414
|
+
@default_env = {
|
415
|
+
"action_dispatch.routes" => self,
|
416
|
+
"action_dispatch.routes.default_url_options" => url_options,
|
417
|
+
"HTTPS" => uri.scheme == "https" ? "on" : "off",
|
418
|
+
"rack.url_scheme" => uri.scheme,
|
419
|
+
"HTTP_HOST" => uri.port == uri.default_port ? uri.host : "#{uri.host}:#{uri.port}",
|
420
|
+
"SCRIPT_NAME" => uri.path.chomp("/"),
|
421
|
+
"rack.input" => "",
|
422
|
+
}.freeze
|
423
|
+
end
|
424
|
+
|
425
|
+
@default_env
|
426
|
+
end
|
427
|
+
|
407
428
|
def draw(&block)
|
408
429
|
clear! unless @disable_clear_and_finalize
|
409
430
|
eval_block(block)
|
@@ -573,6 +594,20 @@ module ActionDispatch
|
|
573
594
|
end
|
574
595
|
|
575
596
|
private :_generate_paths_by_default
|
597
|
+
|
598
|
+
# If the module is included more than once (for example, in a subclass
|
599
|
+
# of an ancestor that includes the module), ensure that the `_routes`
|
600
|
+
# singleton and instance methods return the desired route set by
|
601
|
+
# including a new copy of the module (recursively if necessary). Note
|
602
|
+
# that this method is called for each inclusion, whereas the above
|
603
|
+
# `included` block is run only for the initial inclusion of each copy.
|
604
|
+
def self.included(base)
|
605
|
+
super
|
606
|
+
if base.respond_to?(:_routes) && !base._routes.equal?(@_proxy._routes)
|
607
|
+
@dup_for_reinclude ||= self.dup
|
608
|
+
base.include @dup_for_reinclude
|
609
|
+
end
|
610
|
+
end
|
576
611
|
end
|
577
612
|
end
|
578
613
|
|
@@ -595,16 +630,16 @@ module ActionDispatch
|
|
595
630
|
named_routes[name] = route if name
|
596
631
|
|
597
632
|
if route.segment_keys.include?(:controller)
|
598
|
-
|
633
|
+
ActionDispatch.deprecator.warn(<<-MSG.squish)
|
599
634
|
Using a dynamic :controller segment in a route is deprecated and
|
600
|
-
will be removed in Rails 7.
|
635
|
+
will be removed in Rails 7.2.
|
601
636
|
MSG
|
602
637
|
end
|
603
638
|
|
604
639
|
if route.segment_keys.include?(:action)
|
605
|
-
|
640
|
+
ActionDispatch.deprecator.warn(<<-MSG.squish)
|
606
641
|
Using a dynamic :action segment in a route is deprecated and
|
607
|
-
will be removed in Rails 7.
|
642
|
+
will be removed in Rails 7.2.
|
608
643
|
MSG
|
609
644
|
end
|
610
645
|
|
@@ -778,18 +813,14 @@ module ActionDispatch
|
|
778
813
|
|
779
814
|
RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length,
|
780
815
|
:trailing_slash, :anchor, :params, :only_path, :script_name,
|
781
|
-
:original_script_name
|
816
|
+
:original_script_name]
|
782
817
|
|
783
818
|
def optimize_routes_generation?
|
784
819
|
default_url_options.empty?
|
785
820
|
end
|
786
821
|
|
787
822
|
def find_script_name(options)
|
788
|
-
options.delete(:script_name) ||
|
789
|
-
end
|
790
|
-
|
791
|
-
def find_relative_url_root(options)
|
792
|
-
options.delete(:relative_url_root) || relative_url_root
|
823
|
+
options.delete(:script_name) || relative_url_root || ""
|
793
824
|
end
|
794
825
|
|
795
826
|
def path_for(options, route_name = nil, reserved = RESERVED_OPTIONS)
|
@@ -821,10 +852,19 @@ module ActionDispatch
|
|
821
852
|
|
822
853
|
route_with_params = generate(route_name, path_options, recall)
|
823
854
|
path = route_with_params.path(method_name)
|
855
|
+
|
856
|
+
if options[:trailing_slash] && !options[:format] && !path.end_with?("/")
|
857
|
+
path += "/"
|
858
|
+
end
|
859
|
+
|
824
860
|
params = route_with_params.params
|
825
861
|
|
826
862
|
if options.key? :params
|
827
|
-
|
863
|
+
if options[:params]&.respond_to?(:to_hash)
|
864
|
+
params.merge! options[:params]
|
865
|
+
else
|
866
|
+
params[:params] = options[:params]
|
867
|
+
end
|
828
868
|
end
|
829
869
|
|
830
870
|
options[:path] = path
|
@@ -844,7 +884,7 @@ module ActionDispatch
|
|
844
884
|
|
845
885
|
def recognize_path(path, environment = {})
|
846
886
|
method = (environment[:method] || "GET").to_s.upcase
|
847
|
-
path = Journey::Router::Utils.normalize_path(path) unless
|
887
|
+
path = Journey::Router::Utils.normalize_path(path) unless path&.include?("://")
|
848
888
|
extras = environment[:extras] || {}
|
849
889
|
|
850
890
|
begin
|
@@ -4,7 +4,7 @@ require "active_support/core_ext/array/extract_options"
|
|
4
4
|
|
5
5
|
module ActionDispatch
|
6
6
|
module Routing
|
7
|
-
class RoutesProxy
|
7
|
+
class RoutesProxy # :nodoc:
|
8
8
|
include ActionDispatch::Routing::UrlFor
|
9
9
|
|
10
10
|
attr_accessor :scope, :routes
|
@@ -29,23 +29,18 @@ module ActionDispatch
|
|
29
29
|
|
30
30
|
def method_missing(method, *args)
|
31
31
|
if @helpers.respond_to?(method)
|
32
|
-
|
33
|
-
|
34
|
-
options = args.extract_options!
|
35
|
-
options = url_options.merge((options || {}).symbolize_keys)
|
32
|
+
options = args.extract_options!
|
33
|
+
options = url_options.merge((options || {}).symbolize_keys)
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
35
|
+
if @script_namer
|
36
|
+
options[:script_name] = merge_script_names(
|
37
|
+
options[:script_name],
|
38
|
+
@script_namer.call(options)
|
39
|
+
)
|
40
|
+
end
|
43
41
|
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
-
RUBY
|
48
|
-
public_send(method, *args)
|
42
|
+
args << options
|
43
|
+
@helpers.public_send(method, *args)
|
49
44
|
else
|
50
45
|
super
|
51
46
|
end
|
@@ -2,20 +2,22 @@
|
|
2
2
|
|
3
3
|
module ActionDispatch
|
4
4
|
module Routing
|
5
|
+
# = Action Dispatch Routing \UrlFor
|
6
|
+
#
|
5
7
|
# In <tt>config/routes.rb</tt> you define URL-to-controller mappings, but the reverse
|
6
8
|
# is also possible: a URL can be generated from one of your routing definitions.
|
7
9
|
# URL generation functionality is centralized in this module.
|
8
10
|
#
|
9
|
-
# See ActionDispatch::Routing for general information about routing and routes.rb
|
11
|
+
# See ActionDispatch::Routing for general information about routing and <tt>config/routes.rb</tt>.
|
10
12
|
#
|
11
13
|
# <b>Tip:</b> If you need to generate URLs from your models or some other place,
|
12
|
-
# then
|
14
|
+
# then ActionDispatch::Routing::UrlFor is what you're looking for. Read on for
|
13
15
|
# an introduction. In general, this module should not be included on its own,
|
14
|
-
# as it is usually included by url_helpers (as in Rails.application.routes.url_helpers).
|
16
|
+
# as it is usually included by +url_helpers+ (as in <tt>Rails.application.routes.url_helpers</tt>).
|
15
17
|
#
|
16
18
|
# == URL generation from parameters
|
17
19
|
#
|
18
|
-
# As you may know, some functions, such as ActionController::Base#url_for
|
20
|
+
# As you may know, some functions, such as <tt>ActionController::Base#url_for</tt>
|
19
21
|
# and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set
|
20
22
|
# of parameters. For example, you've probably had the chance to write code
|
21
23
|
# like this in one of your views:
|
@@ -24,12 +26,12 @@ module ActionDispatch
|
|
24
26
|
# action: 'new', message: 'Welcome!') %>
|
25
27
|
# # => <a href="/users/new?message=Welcome%21">Click here</a>
|
26
28
|
#
|
27
|
-
# link_to
|
28
|
-
# actually use
|
29
|
-
# they use the
|
29
|
+
# +link_to+, and all other functions that require URL generation functionality,
|
30
|
+
# actually use ActionDispatch::Routing::UrlFor under the hood. And in particular,
|
31
|
+
# they use the ActionDispatch::Routing::UrlFor#url_for method. One can generate
|
30
32
|
# the same path as the above example by using the following code:
|
31
33
|
#
|
32
|
-
# include UrlFor
|
34
|
+
# include ActionDispatch::Routing::UrlFor
|
33
35
|
# url_for(controller: 'users',
|
34
36
|
# action: 'new',
|
35
37
|
# message: 'Welcome!',
|
@@ -37,7 +39,7 @@ module ActionDispatch
|
|
37
39
|
# # => "/users/new?message=Welcome%21"
|
38
40
|
#
|
39
41
|
# Notice the <tt>only_path: true</tt> part. This is because UrlFor has no
|
40
|
-
# information about the website hostname that your Rails app is serving. So if you
|
42
|
+
# information about the website hostname that your \Rails app is serving. So if you
|
41
43
|
# want to include the hostname as well, then you must also pass the <tt>:host</tt>
|
42
44
|
# argument:
|
43
45
|
#
|
@@ -48,17 +50,17 @@ module ActionDispatch
|
|
48
50
|
# host: 'www.example.com')
|
49
51
|
# # => "http://www.example.com/users/new?message=Welcome%21"
|
50
52
|
#
|
51
|
-
# By default, all controllers and views have access to a special version of url_for
|
52
|
-
# that already knows what the current hostname is. So if you use url_for in your
|
53
|
+
# By default, all controllers and views have access to a special version of +url_for+,
|
54
|
+
# that already knows what the current hostname is. So if you use +url_for+ in your
|
53
55
|
# controllers or your views, then you don't need to explicitly pass the <tt>:host</tt>
|
54
56
|
# argument.
|
55
57
|
#
|
56
|
-
# For convenience
|
57
|
-
#
|
58
|
-
#
|
59
|
-
# the +:host+
|
60
|
-
#
|
61
|
-
#
|
58
|
+
# For convenience, mailers also include ActionDispatch::Routing::UrlFor. So
|
59
|
+
# within mailers, you can use url_for. However, mailers cannot access
|
60
|
+
# incoming web requests in order to derive hostname information, so you have
|
61
|
+
# to provide the +:host+ option or set the default host using
|
62
|
+
# +default_url_options+. For more information on url_for in mailers see the
|
63
|
+
# ActionMailer::Base documentation.
|
62
64
|
#
|
63
65
|
#
|
64
66
|
# == URL generation for named routes
|
@@ -70,9 +72,9 @@ module ActionDispatch
|
|
70
72
|
# resources :users
|
71
73
|
#
|
72
74
|
# This generates, among other things, the method <tt>users_path</tt>. By default,
|
73
|
-
# this method is accessible from your controllers, views and mailers. If you need
|
75
|
+
# this method is accessible from your controllers, views, and mailers. If you need
|
74
76
|
# to access this auto-generated method from other places (such as a model), then
|
75
|
-
# you can do that by including Rails.application.routes.url_helpers in your class:
|
77
|
+
# you can do that by including <tt>Rails.application.routes.url_helpers</tt> in your class:
|
76
78
|
#
|
77
79
|
# class User < ActiveRecord::Base
|
78
80
|
# include Rails.application.routes.url_helpers
|
@@ -103,11 +105,10 @@ module ActionDispatch
|
|
103
105
|
include(*_url_for_modules) if respond_to?(:_url_for_modules)
|
104
106
|
end
|
105
107
|
|
106
|
-
def initialize(
|
108
|
+
def initialize(...)
|
107
109
|
@_routes = nil
|
108
110
|
super
|
109
111
|
end
|
110
|
-
ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
|
111
112
|
|
112
113
|
# Hook overridden in controller to add request information
|
113
114
|
# with +default_url_options+. Application logic should not
|
@@ -116,11 +117,11 @@ module ActionDispatch
|
|
116
117
|
default_url_options
|
117
118
|
end
|
118
119
|
|
119
|
-
# Generate a URL based on the options provided, default_url_options and the
|
120
|
-
# routes defined in routes.rb
|
120
|
+
# Generate a URL based on the options provided, +default_url_options+, and the
|
121
|
+
# routes defined in <tt>config/routes.rb</tt>. The following options are supported:
|
121
122
|
#
|
122
123
|
# * <tt>:only_path</tt> - If true, the relative URL is returned. Defaults to +false+.
|
123
|
-
# * <tt>:protocol</tt> - The protocol to connect to. Defaults to
|
124
|
+
# * <tt>:protocol</tt> - The protocol to connect to. Defaults to <tt>"http"</tt>.
|
124
125
|
# * <tt>:host</tt> - Specifies the host the link should be targeted at.
|
125
126
|
# If <tt>:only_path</tt> is false, this option must be
|
126
127
|
# provided either explicitly, or via +default_url_options+.
|
@@ -135,7 +136,9 @@ module ActionDispatch
|
|
135
136
|
# * <tt>:port</tt> - Optionally specify the port to connect to.
|
136
137
|
# * <tt>:anchor</tt> - An anchor name to be appended to the path.
|
137
138
|
# * <tt>:params</tt> - The query parameters to be appended to the path.
|
138
|
-
# * <tt>:
|
139
|
+
# * <tt>:path_params</tt> - The query parameters that will only be used
|
140
|
+
# for the named dynamic segments of path. If unused, they will be discarded.
|
141
|
+
# * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in <tt>"/archive/2009/"</tt>.
|
139
142
|
# * <tt>:script_name</tt> - Specifies application path relative to domain root. If provided, prepends application path.
|
140
143
|
#
|
141
144
|
# Any other key (<tt>:controller</tt>, <tt>:action</tt>, etc.) given to
|
@@ -155,7 +158,7 @@ module ActionDispatch
|
|
155
158
|
# # => '/myapp/tasks/testing'
|
156
159
|
#
|
157
160
|
# Missing routes keys may be filled in from the current request's parameters
|
158
|
-
# (e.g. +:controller+, +:action+, +:id
|
161
|
+
# (e.g. +:controller+, +:action+, +:id+, and any other parameters that are
|
159
162
|
# placed in the path). Given that the current action has been reached
|
160
163
|
# through <tt>GET /users/1</tt>:
|
161
164
|
#
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/string/filters"
|
4
|
-
|
5
3
|
module ActionDispatch
|
6
4
|
# The routing module provides URL rewriting in native Ruby. It's a way to
|
7
5
|
# redirect incoming requests to controllers and actions. This replaces
|
@@ -28,7 +26,7 @@ module ActionDispatch
|
|
28
26
|
#
|
29
27
|
# Resource routing allows you to quickly declare all of the common routes
|
30
28
|
# for a given resourceful controller. Instead of declaring separate routes
|
31
|
-
# for your +index+, +show+, +new+, +edit+, +create+, +update
|
29
|
+
# for your +index+, +show+, +new+, +edit+, +create+, +update+, and +destroy+
|
32
30
|
# actions, a resourceful route declares them in a single line of code:
|
33
31
|
#
|
34
32
|
# resources :photos
|
@@ -65,9 +63,8 @@ module ActionDispatch
|
|
65
63
|
# resources :posts, :comments
|
66
64
|
# end
|
67
65
|
#
|
68
|
-
# For more, see
|
69
|
-
#
|
70
|
-
# <tt>Routing::Mapper::Scoping#scope</tt>.
|
66
|
+
# For more, see Routing::Mapper::Resources#resources,
|
67
|
+
# Routing::Mapper::Scoping#namespace, and Routing::Mapper::Scoping#scope.
|
71
68
|
#
|
72
69
|
# == Non-resourceful routes
|
73
70
|
#
|
@@ -120,9 +117,9 @@ module ActionDispatch
|
|
120
117
|
#
|
121
118
|
# # In config/routes.rb
|
122
119
|
# controller :blog do
|
123
|
-
# get 'blog/show'
|
124
|
-
# get 'blog/delete'
|
125
|
-
# get 'blog/edit'
|
120
|
+
# get 'blog/show' => :list
|
121
|
+
# get 'blog/delete' => :delete
|
122
|
+
# get 'blog/edit' => :edit
|
126
123
|
# end
|
127
124
|
#
|
128
125
|
# # provides named routes for show, delete, and edit
|
@@ -241,7 +238,7 @@ module ActionDispatch
|
|
241
238
|
#
|
242
239
|
# == View a list of all your routes
|
243
240
|
#
|
244
|
-
# rails routes
|
241
|
+
# $ bin/rails routes
|
245
242
|
#
|
246
243
|
# Target a specific controller with <tt>-c</tt>, or grep routes
|
247
244
|
# using <tt>-g</tt>. Useful in conjunction with <tt>--expanded</tt>
|
@@ -251,11 +248,13 @@ module ActionDispatch
|
|
251
248
|
|
252
249
|
autoload :Mapper
|
253
250
|
autoload :RouteSet
|
254
|
-
|
251
|
+
eager_autoload do
|
252
|
+
autoload :RoutesProxy
|
253
|
+
end
|
255
254
|
autoload :UrlFor
|
256
255
|
autoload :PolymorphicRoutes
|
257
256
|
|
258
|
-
SEPARATORS = %w( / . ? )
|
259
|
-
HTTP_METHODS = [:get, :head, :post, :patch, :put, :delete, :options]
|
257
|
+
SEPARATORS = %w( / . ? ) # :nodoc:
|
258
|
+
HTTP_METHODS = [:get, :head, :post, :patch, :put, :delete, :options] # :nodoc:
|
260
259
|
end
|
261
260
|
end
|
@@ -51,7 +51,7 @@ module ActionDispatch
|
|
51
51
|
# driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
|
52
52
|
# end
|
53
53
|
#
|
54
|
-
# By default,
|
54
|
+
# By default, +ActionDispatch::SystemTestCase+ is driven by the
|
55
55
|
# Selenium driver, with the Chrome browser, and a browser size of 1400x1400.
|
56
56
|
#
|
57
57
|
# Changing the driver configuration options is easy. Let's say you want to use
|
@@ -72,8 +72,8 @@ module ActionDispatch
|
|
72
72
|
# Headless browsers such as headless Chrome and headless Firefox are also supported.
|
73
73
|
# You can use these browsers by setting the +:using+ argument to +:headless_chrome+ or +:headless_firefox+.
|
74
74
|
#
|
75
|
-
# To use a headless driver, like
|
76
|
-
#
|
75
|
+
# To use a headless driver, like Cuprite, update your Gemfile to use
|
76
|
+
# Cuprite instead of Selenium and then declare the driver name in the
|
77
77
|
# +application_system_test_case.rb+ file. In this case, you would leave out
|
78
78
|
# the +:using+ option because the driver is headless, but you can still use
|
79
79
|
# +:screen_size+ to change the size of the browser screen, also you can use
|
@@ -81,10 +81,10 @@ module ActionDispatch
|
|
81
81
|
# driver documentation to learn about supported options.
|
82
82
|
#
|
83
83
|
# require "test_helper"
|
84
|
-
# require "capybara/
|
84
|
+
# require "capybara/cuprite"
|
85
85
|
#
|
86
86
|
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
87
|
-
# driven_by :
|
87
|
+
# driven_by :cuprite, screen_size: [1400, 1400], options:
|
88
88
|
# { js_errors: true }
|
89
89
|
# end
|
90
90
|
#
|
@@ -106,8 +106,8 @@ module ActionDispatch
|
|
106
106
|
# end
|
107
107
|
# end
|
108
108
|
#
|
109
|
-
# Because
|
110
|
-
# and Rails, any driver that is supported by Capybara is supported by system
|
109
|
+
# Because +ActionDispatch::SystemTestCase+ is a shim between Capybara
|
110
|
+
# and \Rails, any driver that is supported by Capybara is supported by system
|
111
111
|
# tests as long as you include the required gems and files.
|
112
112
|
class SystemTestCase < ActiveSupport::TestCase
|
113
113
|
include Capybara::DSL
|
@@ -142,7 +142,7 @@ module ActionDispatch
|
|
142
142
|
#
|
143
143
|
# Examples:
|
144
144
|
#
|
145
|
-
# driven_by :
|
145
|
+
# driven_by :cuprite
|
146
146
|
#
|
147
147
|
# driven_by :selenium, screen_size: [800, 800]
|
148
148
|
#
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module ActionDispatch
|
4
4
|
module SystemTesting
|
5
5
|
class Browser # :nodoc:
|
6
|
-
attr_reader :name
|
6
|
+
attr_reader :name
|
7
7
|
|
8
8
|
def initialize(name)
|
9
9
|
@name = name
|
@@ -21,45 +21,32 @@ module ActionDispatch
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
def options
|
25
|
+
@options ||=
|
26
|
+
case type
|
27
|
+
when :chrome
|
28
|
+
::Selenium::WebDriver::Chrome::Options.new
|
29
|
+
when :firefox
|
30
|
+
::Selenium::WebDriver::Firefox::Options.new
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
24
34
|
def configure
|
25
|
-
|
26
|
-
yield options if block_given? && options
|
35
|
+
yield options if block_given?
|
27
36
|
end
|
28
37
|
|
29
|
-
# driver_path
|
30
|
-
#
|
31
|
-
# update the webdriver once and avoid race conditions when using
|
32
|
-
# parallel tests.
|
38
|
+
# driver_path is lazily initialized by default. Eagerly set it to
|
39
|
+
# avoid race conditions when using parallel tests.
|
33
40
|
def preload
|
34
41
|
case type
|
35
42
|
when :chrome
|
36
|
-
|
37
|
-
::Selenium::WebDriver::Chrome::Service.driver_path&.call
|
38
|
-
else
|
39
|
-
# Selenium <= v3.141.0
|
40
|
-
::Selenium::WebDriver::Chrome.driver_path
|
41
|
-
end
|
43
|
+
resolve_driver_path(::Selenium::WebDriver::Chrome)
|
42
44
|
when :firefox
|
43
|
-
|
44
|
-
::Selenium::WebDriver::Firefox::Service.driver_path&.call
|
45
|
-
else
|
46
|
-
# Selenium <= v3.141.0
|
47
|
-
::Selenium::WebDriver::Firefox.driver_path
|
48
|
-
end
|
45
|
+
resolve_driver_path(::Selenium::WebDriver::Firefox)
|
49
46
|
end
|
50
47
|
end
|
51
48
|
|
52
49
|
private
|
53
|
-
def initialize_options
|
54
|
-
@options ||=
|
55
|
-
case type
|
56
|
-
when :chrome
|
57
|
-
::Selenium::WebDriver::Chrome::Options.new
|
58
|
-
when :firefox
|
59
|
-
::Selenium::WebDriver::Firefox::Options.new
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
50
|
def set_default_options
|
64
51
|
case name
|
65
52
|
when :headless_chrome
|
@@ -81,6 +68,10 @@ module ActionDispatch
|
|
81
68
|
capabilities.add_argument("-headless")
|
82
69
|
end
|
83
70
|
end
|
71
|
+
|
72
|
+
def resolve_driver_path(namespace)
|
73
|
+
namespace::Service.driver_path = ::Selenium::WebDriver::DriverFinder.path(options, namespace::Service)
|
74
|
+
end
|
84
75
|
end
|
85
76
|
end
|
86
77
|
end
|
@@ -3,16 +3,22 @@
|
|
3
3
|
module ActionDispatch
|
4
4
|
module SystemTesting
|
5
5
|
class Driver # :nodoc:
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(driver_type, **options, &capabilities)
|
9
|
+
@driver_type = driver_type
|
9
10
|
@screen_size = options[:screen_size]
|
10
11
|
@options = options[:options] || {}
|
12
|
+
@name = @options.delete(:name) || driver_type
|
11
13
|
@capabilities = capabilities
|
12
14
|
|
13
|
-
if
|
15
|
+
if driver_type == :selenium
|
16
|
+
gem "selenium-webdriver", ">= 4.0.0"
|
14
17
|
require "selenium/webdriver"
|
18
|
+
@browser = Browser.new(options[:using])
|
15
19
|
@browser.preload
|
20
|
+
else
|
21
|
+
@browser = nil
|
16
22
|
end
|
17
23
|
end
|
18
24
|
|
@@ -24,17 +30,18 @@ module ActionDispatch
|
|
24
30
|
|
25
31
|
private
|
26
32
|
def registerable?
|
27
|
-
[:selenium, :
|
33
|
+
[:selenium, :cuprite, :rack_test, :playwright].include?(@driver_type)
|
28
34
|
end
|
29
35
|
|
30
36
|
def register
|
31
|
-
@browser
|
37
|
+
@browser&.configure(&@capabilities)
|
32
38
|
|
33
|
-
Capybara.register_driver
|
34
|
-
case @
|
39
|
+
Capybara.register_driver name do |app|
|
40
|
+
case @driver_type
|
35
41
|
when :selenium then register_selenium(app)
|
36
|
-
when :
|
37
|
-
when :
|
42
|
+
when :cuprite then register_cuprite(app)
|
43
|
+
when :rack_test then register_rack_test(app)
|
44
|
+
when :playwright then register_playwright(app)
|
38
45
|
end
|
39
46
|
end
|
40
47
|
end
|
@@ -44,23 +51,32 @@ module ActionDispatch
|
|
44
51
|
end
|
45
52
|
|
46
53
|
def register_selenium(app)
|
47
|
-
Capybara::Selenium::Driver.new(app,
|
54
|
+
Capybara::Selenium::Driver.new(app, browser: @browser.type, **browser_options).tap do |driver|
|
48
55
|
driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*@screen_size)
|
49
56
|
end
|
50
57
|
end
|
51
58
|
|
52
|
-
def
|
53
|
-
Capybara::
|
59
|
+
def register_cuprite(app)
|
60
|
+
Capybara::Cuprite::Driver.new(app, @options.merge(window_size: @screen_size))
|
54
61
|
end
|
55
62
|
|
56
|
-
def
|
57
|
-
Capybara::
|
58
|
-
|
59
|
-
|
63
|
+
def register_rack_test(app)
|
64
|
+
Capybara::RackTest::Driver.new(app, respect_data_method: true, **@options)
|
65
|
+
end
|
66
|
+
|
67
|
+
def register_playwright(app)
|
68
|
+
screen = { width: @screen_size[0], height: @screen_size[1] } if @screen_size
|
69
|
+
options = {
|
70
|
+
screen: screen,
|
71
|
+
viewport: screen,
|
72
|
+
**@options
|
73
|
+
}.compact
|
74
|
+
|
75
|
+
Capybara::Playwright::Driver.new(app, **options)
|
60
76
|
end
|
61
77
|
|
62
78
|
def setup
|
63
|
-
Capybara.current_driver =
|
79
|
+
Capybara.current_driver = name
|
64
80
|
end
|
65
81
|
end
|
66
82
|
end
|