actionpack 7.2.1.1 → 8.0.0.rc1
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 +108 -100
- data/lib/abstract_controller/helpers.rb +2 -0
- data/lib/abstract_controller/rendering.rb +0 -1
- data/lib/action_controller/api.rb +1 -0
- data/lib/action_controller/form_builder.rb +3 -3
- data/lib/action_controller/metal/allow_browser.rb +12 -2
- data/lib/action_controller/metal/conditional_get.rb +6 -3
- data/lib/action_controller/metal/http_authentication.rb +6 -3
- data/lib/action_controller/metal/instrumentation.rb +1 -2
- data/lib/action_controller/metal/live.rb +19 -8
- data/lib/action_controller/metal/rate_limiting.rb +13 -4
- data/lib/action_controller/metal/renderers.rb +2 -3
- data/lib/action_controller/metal/streaming.rb +5 -84
- data/lib/action_controller/metal/strong_parameters.rb +274 -88
- data/lib/action_controller/railtie.rb +1 -7
- data/lib/action_controller/test_case.rb +6 -5
- data/lib/action_dispatch/http/cache.rb +27 -10
- data/lib/action_dispatch/http/content_security_policy.rb +5 -8
- data/lib/action_dispatch/http/filter_parameters.rb +4 -9
- data/lib/action_dispatch/http/filter_redirect.rb +2 -9
- data/lib/action_dispatch/http/param_builder.rb +163 -0
- data/lib/action_dispatch/http/param_error.rb +26 -0
- data/lib/action_dispatch/http/permissions_policy.rb +2 -0
- data/lib/action_dispatch/http/query_parser.rb +31 -0
- data/lib/action_dispatch/http/request.rb +60 -16
- data/lib/action_dispatch/journey/parser.rb +99 -196
- data/lib/action_dispatch/journey/scanner.rb +40 -42
- data/lib/action_dispatch/middleware/cookies.rb +4 -2
- data/lib/action_dispatch/middleware/debug_exceptions.rb +16 -3
- data/lib/action_dispatch/middleware/debug_view.rb +0 -5
- data/lib/action_dispatch/middleware/exception_wrapper.rb +0 -6
- data/lib/action_dispatch/middleware/remote_ip.rb +5 -6
- data/lib/action_dispatch/middleware/request_id.rb +2 -1
- data/lib/action_dispatch/middleware/ssl.rb +14 -4
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +0 -3
- data/lib/action_dispatch/railtie.rb +2 -0
- data/lib/action_dispatch/request/utils.rb +9 -3
- data/lib/action_dispatch/routing/inspector.rb +1 -1
- data/lib/action_dispatch/routing/mapper.rb +91 -62
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -2
- data/lib/action_dispatch/routing/route_set.rb +20 -8
- data/lib/action_dispatch/system_testing/browser.rb +12 -21
- data/lib/action_dispatch/testing/assertions/response.rb +12 -2
- data/lib/action_dispatch/testing/assertions/routing.rb +4 -4
- data/lib/action_dispatch/testing/integration.rb +11 -1
- data/lib/action_dispatch.rb +6 -0
- data/lib/action_pack/gem_version.rb +4 -4
- metadata +15 -34
- data/lib/action_dispatch/journey/parser.y +0 -50
- data/lib/action_dispatch/journey/parser_extras.rb +0 -33
@@ -375,35 +375,18 @@ module ActionDispatch
|
|
375
375
|
Routing::RouteSet::Dispatcher.new raise_on_name_error
|
376
376
|
end
|
377
377
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
next if location.path.start_with?(action_dispatch_dir)
|
378
|
+
def route_source_location
|
379
|
+
if Mapper.route_source_locations
|
380
|
+
action_dispatch_dir = File.expand_path("..", __dir__)
|
381
|
+
Thread.each_caller_location do |location|
|
382
|
+
next if location.path.start_with?(action_dispatch_dir)
|
384
383
|
|
385
|
-
|
386
|
-
|
384
|
+
cleaned_path = Mapper.backtrace_cleaner.clean_frame(location.path)
|
385
|
+
next if cleaned_path.nil?
|
387
386
|
|
388
|
-
|
389
|
-
end
|
390
|
-
nil
|
391
|
-
end
|
392
|
-
end
|
393
|
-
else
|
394
|
-
def route_source_location
|
395
|
-
if Mapper.route_source_locations
|
396
|
-
action_dispatch_dir = File.expand_path("..", __dir__)
|
397
|
-
caller_locations.each do |location|
|
398
|
-
next if location.path.start_with?(action_dispatch_dir)
|
399
|
-
|
400
|
-
cleaned_path = Mapper.backtrace_cleaner.clean_frame(location.path)
|
401
|
-
next if cleaned_path.nil?
|
402
|
-
|
403
|
-
return "#{cleaned_path}:#{location.lineno}"
|
404
|
-
end
|
405
|
-
nil
|
387
|
+
return "#{cleaned_path}:#{location.lineno}"
|
406
388
|
end
|
389
|
+
nil
|
407
390
|
end
|
408
391
|
end
|
409
392
|
end
|
@@ -470,7 +453,6 @@ module ActionDispatch
|
|
470
453
|
# When a pattern points to an internal route, the route's `:action` and
|
471
454
|
# `:controller` should be set in options or hash shorthand. Examples:
|
472
455
|
#
|
473
|
-
# match 'photos/:id' => 'photos#show', via: :get
|
474
456
|
# match 'photos/:id', to: 'photos#show', via: :get
|
475
457
|
# match 'photos/:id', controller: 'photos', action: 'show', via: :get
|
476
458
|
#
|
@@ -614,10 +596,6 @@ module ActionDispatch
|
|
614
596
|
#
|
615
597
|
# mount SomeRackApp, at: "some_route"
|
616
598
|
#
|
617
|
-
# Alternatively:
|
618
|
-
#
|
619
|
-
# mount(SomeRackApp => "some_route")
|
620
|
-
#
|
621
599
|
# For options, see `match`, as `mount` uses it internally.
|
622
600
|
#
|
623
601
|
# All mounted applications come with routing helpers to access them. These are
|
@@ -625,7 +603,7 @@ module ActionDispatch
|
|
625
603
|
# `some_rack_app_path` or `some_rack_app_url`. To customize this helper's name,
|
626
604
|
# use the `:as` option:
|
627
605
|
#
|
628
|
-
# mount(SomeRackApp
|
606
|
+
# mount(SomeRackApp, at: "some_route", as: "exciting")
|
629
607
|
#
|
630
608
|
# This will generate the `exciting_path` and `exciting_url` helpers which can be
|
631
609
|
# used to navigate to this mounted app.
|
@@ -773,6 +751,16 @@ module ActionDispatch
|
|
773
751
|
map_method(:options, args, &block)
|
774
752
|
end
|
775
753
|
|
754
|
+
# Define a route that recognizes HTTP CONNECT (and GET) requests. More
|
755
|
+
# specifically this recognizes HTTP/1 protocol upgrade requests and HTTP/2
|
756
|
+
# CONNECT requests with the protocol pseudo header. For supported arguments,
|
757
|
+
# see [match](rdoc-ref:Base#match)
|
758
|
+
#
|
759
|
+
# connect 'live', to: 'live#index'
|
760
|
+
def connect(*args, &block)
|
761
|
+
map_method([:get, :connect], args, &block)
|
762
|
+
end
|
763
|
+
|
776
764
|
private
|
777
765
|
def map_method(method, args, &block)
|
778
766
|
options = args.extract_options!
|
@@ -1048,6 +1036,7 @@ module ActionDispatch
|
|
1048
1036
|
end
|
1049
1037
|
|
1050
1038
|
# Allows you to set default parameters for a route, such as this:
|
1039
|
+
#
|
1051
1040
|
# defaults id: 'home' do
|
1052
1041
|
# match 'scoped_pages/(:id)', to: 'pages#show'
|
1053
1042
|
# end
|
@@ -1173,6 +1162,16 @@ module ActionDispatch
|
|
1173
1162
|
CANONICAL_ACTIONS = %w(index create new show update destroy)
|
1174
1163
|
|
1175
1164
|
class Resource # :nodoc:
|
1165
|
+
class << self
|
1166
|
+
def default_actions(api_only)
|
1167
|
+
if api_only
|
1168
|
+
[:index, :create, :show, :update, :destroy]
|
1169
|
+
else
|
1170
|
+
[:index, :create, :new, :show, :update, :destroy, :edit]
|
1171
|
+
end
|
1172
|
+
end
|
1173
|
+
end
|
1174
|
+
|
1176
1175
|
attr_reader :controller, :path, :param
|
1177
1176
|
|
1178
1177
|
def initialize(entities, api_only, shallow, options = {})
|
@@ -1180,6 +1179,11 @@ module ActionDispatch
|
|
1180
1179
|
raise ArgumentError, ":param option can't contain colons"
|
1181
1180
|
end
|
1182
1181
|
|
1182
|
+
valid_actions = self.class.default_actions(false) # ignore api_only for this validation
|
1183
|
+
if invalid_actions = invalid_only_except_options(options, valid_actions).presence
|
1184
|
+
raise ArgumentError, ":only and :except must include only #{valid_actions}, but also included #{invalid_actions}"
|
1185
|
+
end
|
1186
|
+
|
1183
1187
|
@name = entities.to_s
|
1184
1188
|
@path = (options[:path] || @name).to_s
|
1185
1189
|
@controller = (options[:controller] || @name).to_s
|
@@ -1193,11 +1197,7 @@ module ActionDispatch
|
|
1193
1197
|
end
|
1194
1198
|
|
1195
1199
|
def default_actions
|
1196
|
-
|
1197
|
-
[:index, :create, :show, :update, :destroy]
|
1198
|
-
else
|
1199
|
-
[:index, :create, :new, :show, :update, :destroy, :edit]
|
1200
|
-
end
|
1200
|
+
self.class.default_actions(@api_only)
|
1201
1201
|
end
|
1202
1202
|
|
1203
1203
|
def actions
|
@@ -1265,9 +1265,24 @@ module ActionDispatch
|
|
1265
1265
|
end
|
1266
1266
|
|
1267
1267
|
def singleton?; false; end
|
1268
|
+
|
1269
|
+
private
|
1270
|
+
def invalid_only_except_options(options, valid_actions)
|
1271
|
+
options.values_at(:only, :except).flatten.compact.uniq.map(&:to_sym) - valid_actions
|
1272
|
+
end
|
1268
1273
|
end
|
1269
1274
|
|
1270
1275
|
class SingletonResource < Resource # :nodoc:
|
1276
|
+
class << self
|
1277
|
+
def default_actions(api_only)
|
1278
|
+
if api_only
|
1279
|
+
[:show, :create, :update, :destroy]
|
1280
|
+
else
|
1281
|
+
[:show, :create, :update, :destroy, :new, :edit]
|
1282
|
+
end
|
1283
|
+
end
|
1284
|
+
end
|
1285
|
+
|
1271
1286
|
def initialize(entities, api_only, shallow, options)
|
1272
1287
|
super
|
1273
1288
|
@as = nil
|
@@ -1276,11 +1291,7 @@ module ActionDispatch
|
|
1276
1291
|
end
|
1277
1292
|
|
1278
1293
|
def default_actions
|
1279
|
-
|
1280
|
-
[:show, :create, :update, :destroy]
|
1281
|
-
else
|
1282
|
-
[:show, :create, :update, :destroy, :new, :edit]
|
1283
|
-
end
|
1294
|
+
self.class.default_actions(@api_only)
|
1284
1295
|
end
|
1285
1296
|
|
1286
1297
|
def plural
|
@@ -1341,7 +1352,7 @@ module ActionDispatch
|
|
1341
1352
|
end
|
1342
1353
|
|
1343
1354
|
with_scope_level(:resource) do
|
1344
|
-
options = apply_action_options options
|
1355
|
+
options = apply_action_options :resource, options
|
1345
1356
|
resource_scope(SingletonResource.new(resources.pop, api_only?, @scope[:shallow], options)) do
|
1346
1357
|
yield if block_given?
|
1347
1358
|
|
@@ -1511,7 +1522,7 @@ module ActionDispatch
|
|
1511
1522
|
end
|
1512
1523
|
|
1513
1524
|
with_scope_level(:resources) do
|
1514
|
-
options = apply_action_options options
|
1525
|
+
options = apply_action_options :resources, options
|
1515
1526
|
resource_scope(Resource.new(resources.pop, api_only?, @scope[:shallow], options)) do
|
1516
1527
|
yield if block_given?
|
1517
1528
|
|
@@ -1672,7 +1683,6 @@ module ActionDispatch
|
|
1672
1683
|
# Matches a URL pattern to one or more routes. For more information, see
|
1673
1684
|
# [match](rdoc-ref:Base#match).
|
1674
1685
|
#
|
1675
|
-
# match 'path' => 'controller#action', via: :patch
|
1676
1686
|
# match 'path', to: 'controller#action', via: :post
|
1677
1687
|
# match 'path', 'otherpath', on: :member, via: :get
|
1678
1688
|
def match(path, *rest, &block)
|
@@ -1781,17 +1791,32 @@ module ActionDispatch
|
|
1781
1791
|
false
|
1782
1792
|
end
|
1783
1793
|
|
1784
|
-
def apply_action_options(options)
|
1794
|
+
def apply_action_options(method, options)
|
1785
1795
|
return options if action_options? options
|
1786
|
-
options.merge scope_action_options
|
1796
|
+
options.merge scope_action_options(method)
|
1787
1797
|
end
|
1788
1798
|
|
1789
1799
|
def action_options?(options)
|
1790
1800
|
options[:only] || options[:except]
|
1791
1801
|
end
|
1792
1802
|
|
1793
|
-
def scope_action_options
|
1794
|
-
@scope[:action_options]
|
1803
|
+
def scope_action_options(method)
|
1804
|
+
return {} unless @scope[:action_options]
|
1805
|
+
|
1806
|
+
actions = applicable_actions_for(method)
|
1807
|
+
@scope[:action_options].dup.tap do |options|
|
1808
|
+
(options[:only] = Array(options[:only]) & actions) if options[:only]
|
1809
|
+
(options[:except] = Array(options[:except]) & actions) if options[:except]
|
1810
|
+
end
|
1811
|
+
end
|
1812
|
+
|
1813
|
+
def applicable_actions_for(method)
|
1814
|
+
case method
|
1815
|
+
when :resource
|
1816
|
+
SingletonResource.default_actions(api_only?)
|
1817
|
+
when :resources
|
1818
|
+
Resource.default_actions(api_only?)
|
1819
|
+
end
|
1795
1820
|
end
|
1796
1821
|
|
1797
1822
|
def resource_scope?
|
@@ -1934,6 +1959,11 @@ module ActionDispatch
|
|
1934
1959
|
end
|
1935
1960
|
|
1936
1961
|
def map_match(paths, options)
|
1962
|
+
ActionDispatch.deprecator.warn(<<-MSG.squish) if paths.count > 1
|
1963
|
+
Mapping a route with multiple paths is deprecated and
|
1964
|
+
will be removed in Rails 8.1. Please use multiple method calls instead.
|
1965
|
+
MSG
|
1966
|
+
|
1937
1967
|
if (on = options[:on]) && !VALID_ON_OPTIONS.include?(on)
|
1938
1968
|
raise ArgumentError, "Unknown scope #{on.inspect} given to :on"
|
1939
1969
|
end
|
@@ -2024,7 +2054,7 @@ module ActionDispatch
|
|
2024
2054
|
name_for_action(options.delete(:as), action)
|
2025
2055
|
end
|
2026
2056
|
|
2027
|
-
path = Mapping.normalize_path URI::
|
2057
|
+
path = Mapping.normalize_path URI::RFC2396_PARSER.escape(path), formatted
|
2028
2058
|
ast = Journey::Parser.parse path
|
2029
2059
|
|
2030
2060
|
mapping = Mapping.build(@scope, @set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
|
@@ -2199,8 +2229,8 @@ module ActionDispatch
|
|
2199
2229
|
end
|
2200
2230
|
|
2201
2231
|
# Define custom polymorphic mappings of models to URLs. This alters the behavior
|
2202
|
-
# of `polymorphic_url` and consequently the behavior of `link_to
|
2203
|
-
# when passed a model instance, e.g:
|
2232
|
+
# of `polymorphic_url` and consequently the behavior of `link_to`, `form_with`
|
2233
|
+
# and `form_for` when passed a model instance, e.g:
|
2204
2234
|
#
|
2205
2235
|
# resource :basket
|
2206
2236
|
#
|
@@ -2209,7 +2239,7 @@ module ActionDispatch
|
|
2209
2239
|
# end
|
2210
2240
|
#
|
2211
2241
|
# This will now generate "/basket" when a `Basket` instance is passed to
|
2212
|
-
# `link_to` or `form_for` instead of the standard "/baskets/:id".
|
2242
|
+
# `link_to`, `form_with` or `form_for` instead of the standard "/baskets/:id".
|
2213
2243
|
#
|
2214
2244
|
# NOTE: This custom behavior only applies to simple polymorphic URLs where a
|
2215
2245
|
# single model instance is passed and not more complicated forms, e.g:
|
@@ -2266,9 +2296,9 @@ module ActionDispatch
|
|
2266
2296
|
|
2267
2297
|
attr_reader :parent, :scope_level
|
2268
2298
|
|
2269
|
-
def initialize(hash, parent =
|
2270
|
-
@hash = hash
|
2299
|
+
def initialize(hash, parent = ROOT, scope_level = nil)
|
2271
2300
|
@parent = parent
|
2301
|
+
@hash = parent ? parent.frame.merge(hash) : hash
|
2272
2302
|
@scope_level = scope_level
|
2273
2303
|
end
|
2274
2304
|
|
@@ -2281,7 +2311,7 @@ module ActionDispatch
|
|
2281
2311
|
end
|
2282
2312
|
|
2283
2313
|
def root?
|
2284
|
-
@parent
|
2314
|
+
@parent == ROOT
|
2285
2315
|
end
|
2286
2316
|
|
2287
2317
|
def resources?
|
@@ -2326,23 +2356,22 @@ module ActionDispatch
|
|
2326
2356
|
end
|
2327
2357
|
|
2328
2358
|
def [](key)
|
2329
|
-
|
2330
|
-
scope && scope.frame[key]
|
2359
|
+
frame[key]
|
2331
2360
|
end
|
2332
2361
|
|
2362
|
+
def frame; @hash; end
|
2363
|
+
|
2333
2364
|
include Enumerable
|
2334
2365
|
|
2335
2366
|
def each
|
2336
2367
|
node = self
|
2337
|
-
until node.equal?
|
2368
|
+
until node.equal? ROOT
|
2338
2369
|
yield node
|
2339
2370
|
node = node.parent
|
2340
2371
|
end
|
2341
2372
|
end
|
2342
2373
|
|
2343
|
-
|
2344
|
-
|
2345
|
-
NULL = Scope.new(nil, nil)
|
2374
|
+
ROOT = Scope.new({}, nil)
|
2346
2375
|
end
|
2347
2376
|
|
2348
2377
|
def initialize(set) # :nodoc:
|
@@ -31,7 +31,7 @@ module ActionDispatch
|
|
31
31
|
# * `url_for`, so you can use it with a record as the argument, e.g.
|
32
32
|
# `url_for(@article)`;
|
33
33
|
# * ActionView::Helpers::FormHelper uses `polymorphic_path`, so you can write
|
34
|
-
# `
|
34
|
+
# `form_with(model: @article)` without having to specify `:url` parameter for the
|
35
35
|
# form action;
|
36
36
|
# * `redirect_to` (which, in fact, uses `url_for`) so you can write
|
37
37
|
# `redirect_to(post)` in your controllers;
|
@@ -61,7 +61,7 @@ module ActionDispatch
|
|
61
61
|
# argument to the method. For example:
|
62
62
|
#
|
63
63
|
# polymorphic_url([blog, @post]) # calls blog.post_path(@post)
|
64
|
-
#
|
64
|
+
# form_with(model: [blog, @post]) # => "/blog/posts/1"
|
65
65
|
#
|
66
66
|
module PolymorphicRoutes
|
67
67
|
# Constructs a call to a named RESTful route for the given record and returns
|
@@ -351,7 +351,7 @@ module ActionDispatch
|
|
351
351
|
PATH = ->(options) { ActionDispatch::Http::URL.path_for(options) }
|
352
352
|
UNKNOWN = ->(options) { ActionDispatch::Http::URL.url_for(options) }
|
353
353
|
|
354
|
-
attr_accessor :formatter, :set, :named_routes, :
|
354
|
+
attr_accessor :formatter, :set, :named_routes, :router
|
355
355
|
attr_accessor :disable_clear_and_finalize, :resources_path_names
|
356
356
|
attr_accessor :default_url_options, :draw_paths
|
357
357
|
attr_reader :env_key, :polymorphic_mappings
|
@@ -363,7 +363,7 @@ module ActionDispatch
|
|
363
363
|
end
|
364
364
|
|
365
365
|
def self.new_with_config(config)
|
366
|
-
route_set_config = DEFAULT_CONFIG
|
366
|
+
route_set_config = DEFAULT_CONFIG.dup
|
367
367
|
|
368
368
|
# engines apparently don't have this set
|
369
369
|
if config.respond_to? :relative_url_root
|
@@ -374,14 +374,18 @@ module ActionDispatch
|
|
374
374
|
route_set_config.api_only = config.api_only
|
375
375
|
end
|
376
376
|
|
377
|
+
if config.respond_to? :default_scope
|
378
|
+
route_set_config.default_scope = config.default_scope
|
379
|
+
end
|
380
|
+
|
377
381
|
new route_set_config
|
378
382
|
end
|
379
383
|
|
380
|
-
Config = Struct.new :relative_url_root, :api_only
|
384
|
+
Config = Struct.new :relative_url_root, :api_only, :default_scope
|
381
385
|
|
382
|
-
DEFAULT_CONFIG = Config.new(nil, false)
|
386
|
+
DEFAULT_CONFIG = Config.new(nil, false, nil)
|
383
387
|
|
384
|
-
def initialize(config = DEFAULT_CONFIG)
|
388
|
+
def initialize(config = DEFAULT_CONFIG.dup)
|
385
389
|
self.named_routes = NamedRouteCollection.new
|
386
390
|
self.resources_path_names = self.class.default_resources_path_names
|
387
391
|
self.default_url_options = {}
|
@@ -416,6 +420,14 @@ module ActionDispatch
|
|
416
420
|
@config.api_only
|
417
421
|
end
|
418
422
|
|
423
|
+
def default_scope
|
424
|
+
@config.default_scope
|
425
|
+
end
|
426
|
+
|
427
|
+
def default_scope=(new_default_scope)
|
428
|
+
@config.default_scope = new_default_scope
|
429
|
+
end
|
430
|
+
|
419
431
|
def request_class
|
420
432
|
ActionDispatch::Request
|
421
433
|
end
|
@@ -647,14 +659,14 @@ module ActionDispatch
|
|
647
659
|
if route.segment_keys.include?(:controller)
|
648
660
|
ActionDispatch.deprecator.warn(<<-MSG.squish)
|
649
661
|
Using a dynamic :controller segment in a route is deprecated and
|
650
|
-
will be removed in Rails
|
662
|
+
will be removed in Rails 8.1.
|
651
663
|
MSG
|
652
664
|
end
|
653
665
|
|
654
666
|
if route.segment_keys.include?(:action)
|
655
667
|
ActionDispatch.deprecator.warn(<<-MSG.squish)
|
656
668
|
Using a dynamic :action segment in a route is deprecated and
|
657
|
-
will be removed in Rails
|
669
|
+
will be removed in Rails 8.1.
|
658
670
|
MSG
|
659
671
|
end
|
660
672
|
|
@@ -917,7 +929,7 @@ module ActionDispatch
|
|
917
929
|
params.each do |key, value|
|
918
930
|
if value.is_a?(String)
|
919
931
|
value = value.dup.force_encoding(Encoding::BINARY)
|
920
|
-
params[key] = URI::
|
932
|
+
params[key] = URI::RFC2396_PARSER.unescape(value)
|
921
933
|
end
|
922
934
|
end
|
923
935
|
req.path_parameters = params
|
@@ -9,7 +9,6 @@ module ActionDispatch
|
|
9
9
|
|
10
10
|
def initialize(name)
|
11
11
|
@name = name
|
12
|
-
set_default_options
|
13
12
|
end
|
14
13
|
|
15
14
|
def type
|
@@ -27,9 +26,9 @@ module ActionDispatch
|
|
27
26
|
@options ||=
|
28
27
|
case type
|
29
28
|
when :chrome
|
30
|
-
|
29
|
+
default_chrome_options
|
31
30
|
when :firefox
|
32
|
-
|
31
|
+
default_firefox_options
|
33
32
|
end
|
34
33
|
end
|
35
34
|
|
@@ -49,26 +48,18 @@ module ActionDispatch
|
|
49
48
|
end
|
50
49
|
|
51
50
|
private
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
51
|
+
def default_chrome_options
|
52
|
+
options = ::Selenium::WebDriver::Chrome::Options.new
|
53
|
+
options.add_argument("--disable-search-engine-choice-screen")
|
54
|
+
options.add_argument("--headless") if name == :headless_chrome
|
55
|
+
options.add_argument("--disable-gpu") if Gem.win_platform?
|
56
|
+
options
|
59
57
|
end
|
60
58
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def set_headless_firefox_browser_options
|
69
|
-
configure do |capabilities|
|
70
|
-
capabilities.add_argument("-headless")
|
71
|
-
end
|
59
|
+
def default_firefox_options
|
60
|
+
options = ::Selenium::WebDriver::Firefox::Options.new
|
61
|
+
options.add_argument("-headless") if name == :headless_firefox
|
62
|
+
options
|
72
63
|
end
|
73
64
|
|
74
65
|
def resolve_driver_path(namespace)
|
@@ -87,8 +87,13 @@ module ActionDispatch
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def generate_response_message(expected, actual = @response.response_code)
|
90
|
-
|
91
|
-
|
90
|
+
lambda do
|
91
|
+
(+"Expected response to be a <#{code_with_name(expected)}>,"\
|
92
|
+
" but was a <#{code_with_name(actual)}>").
|
93
|
+
concat(location_if_redirected).
|
94
|
+
concat(exception_if_present).
|
95
|
+
concat(response_body_if_short)
|
96
|
+
end
|
92
97
|
end
|
93
98
|
|
94
99
|
def response_body_if_short
|
@@ -96,6 +101,11 @@ module ActionDispatch
|
|
96
101
|
"\nResponse body: #{@response.body}"
|
97
102
|
end
|
98
103
|
|
104
|
+
def exception_if_present
|
105
|
+
return "" unless ex = @request&.env&.[]("action_dispatch.exception")
|
106
|
+
"\n\nException while processing request: #{Minitest::UnexpectedError.new(ex).message}\n"
|
107
|
+
end
|
108
|
+
|
99
109
|
def location_if_redirected
|
100
110
|
return "" unless @response.redirection? && @response.location.present?
|
101
111
|
location = normalize_argument_to_redirection(@response.location)
|
@@ -118,9 +118,9 @@ module ActionDispatch
|
|
118
118
|
# assert_equal "/users", users_path
|
119
119
|
# end
|
120
120
|
#
|
121
|
-
def with_routing(&block)
|
121
|
+
def with_routing(config = nil, &block)
|
122
122
|
old_routes, old_controller = @routes, @controller
|
123
|
-
create_routes(&block)
|
123
|
+
create_routes(config, &block)
|
124
124
|
ensure
|
125
125
|
reset_routes(old_routes, old_controller)
|
126
126
|
end
|
@@ -267,8 +267,8 @@ module ActionDispatch
|
|
267
267
|
end
|
268
268
|
|
269
269
|
private
|
270
|
-
def create_routes
|
271
|
-
@routes = ActionDispatch::Routing::RouteSet.new
|
270
|
+
def create_routes(config = nil)
|
271
|
+
@routes = ActionDispatch::Routing::RouteSet.new(config || ActionDispatch::Routing::RouteSet::DEFAULT_CONFIG)
|
272
272
|
if @controller
|
273
273
|
@controller = @controller.clone
|
274
274
|
_routes = @routes
|
@@ -284,7 +284,17 @@ module ActionDispatch
|
|
284
284
|
|
285
285
|
# NOTE: rack-test v0.5 doesn't build a default uri correctly Make sure requested
|
286
286
|
# path is always a full URI.
|
287
|
-
|
287
|
+
uri = build_full_uri(path, request_env)
|
288
|
+
|
289
|
+
if method == :get && String === request_env[:params]
|
290
|
+
# rack-test will needlessly parse and rebuild a :params
|
291
|
+
# querystring, using Rack's query parser. At best that's a
|
292
|
+
# waste of time; at worst it can change the value.
|
293
|
+
|
294
|
+
uri << "?" << request_env.delete(:params)
|
295
|
+
end
|
296
|
+
|
297
|
+
session.request(uri, request_env)
|
288
298
|
|
289
299
|
@request_count += 1
|
290
300
|
@request = ActionDispatch::Request.new(session.last_request.env)
|
data/lib/action_dispatch.rb
CHANGED
@@ -53,7 +53,13 @@ module ActionDispatch
|
|
53
53
|
eager_autoload do
|
54
54
|
autoload_under "http" do
|
55
55
|
autoload :ContentSecurityPolicy
|
56
|
+
autoload :InvalidParameterError, "action_dispatch/http/param_error"
|
57
|
+
autoload :ParamBuilder
|
58
|
+
autoload :ParamError
|
59
|
+
autoload :ParameterTypeError, "action_dispatch/http/param_error"
|
60
|
+
autoload :ParamsTooDeepError, "action_dispatch/http/param_error"
|
56
61
|
autoload :PermissionsPolicy
|
62
|
+
autoload :QueryParser
|
57
63
|
autoload :Request
|
58
64
|
autoload :Response
|
59
65
|
end
|