actionpack 7.2.2.1 → 8.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +123 -109
- data/lib/abstract_controller/rendering.rb +0 -1
- data/lib/action_controller/base.rb +1 -1
- data/lib/action_controller/form_builder.rb +3 -3
- data/lib/action_controller/metal/allow_browser.rb +11 -1
- data/lib/action_controller/metal/conditional_get.rb +5 -1
- data/lib/action_controller/metal/data_streaming.rb +4 -2
- data/lib/action_controller/metal/instrumentation.rb +1 -2
- data/lib/action_controller/metal/live.rb +13 -4
- data/lib/action_controller/metal/rate_limiting.rb +13 -4
- data/lib/action_controller/metal/redirecting.rb +2 -1
- 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 +277 -89
- data/lib/action_controller/railtie.rb +1 -7
- data/lib/action_controller/test_case.rb +4 -2
- data/lib/action_dispatch/http/cache.rb +27 -10
- data/lib/action_dispatch/http/content_security_policy.rb +1 -0
- data/lib/action_dispatch/http/param_builder.rb +186 -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 +53 -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 +44 -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/request_id.rb +2 -1
- data/lib/action_dispatch/middleware/ssl.rb +13 -3
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +0 -3
- data/lib/action_dispatch/railtie.rb +8 -0
- data/lib/action_dispatch/request/session.rb +1 -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 +90 -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/testing/test_process.rb +1 -2
- data/lib/action_dispatch.rb +6 -4
- 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!
|
@@ -1174,6 +1162,16 @@ module ActionDispatch
|
|
1174
1162
|
CANONICAL_ACTIONS = %w(index create new show update destroy)
|
1175
1163
|
|
1176
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
|
+
|
1177
1175
|
attr_reader :controller, :path, :param
|
1178
1176
|
|
1179
1177
|
def initialize(entities, api_only, shallow, options = {})
|
@@ -1181,6 +1179,11 @@ module ActionDispatch
|
|
1181
1179
|
raise ArgumentError, ":param option can't contain colons"
|
1182
1180
|
end
|
1183
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
|
+
|
1184
1187
|
@name = entities.to_s
|
1185
1188
|
@path = (options[:path] || @name).to_s
|
1186
1189
|
@controller = (options[:controller] || @name).to_s
|
@@ -1194,11 +1197,7 @@ module ActionDispatch
|
|
1194
1197
|
end
|
1195
1198
|
|
1196
1199
|
def default_actions
|
1197
|
-
|
1198
|
-
[:index, :create, :show, :update, :destroy]
|
1199
|
-
else
|
1200
|
-
[:index, :create, :new, :show, :update, :destroy, :edit]
|
1201
|
-
end
|
1200
|
+
self.class.default_actions(@api_only)
|
1202
1201
|
end
|
1203
1202
|
|
1204
1203
|
def actions
|
@@ -1266,9 +1265,24 @@ module ActionDispatch
|
|
1266
1265
|
end
|
1267
1266
|
|
1268
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
|
1269
1273
|
end
|
1270
1274
|
|
1271
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
|
+
|
1272
1286
|
def initialize(entities, api_only, shallow, options)
|
1273
1287
|
super
|
1274
1288
|
@as = nil
|
@@ -1277,11 +1291,7 @@ module ActionDispatch
|
|
1277
1291
|
end
|
1278
1292
|
|
1279
1293
|
def default_actions
|
1280
|
-
|
1281
|
-
[:show, :create, :update, :destroy]
|
1282
|
-
else
|
1283
|
-
[:show, :create, :update, :destroy, :new, :edit]
|
1284
|
-
end
|
1294
|
+
self.class.default_actions(@api_only)
|
1285
1295
|
end
|
1286
1296
|
|
1287
1297
|
def plural
|
@@ -1342,7 +1352,7 @@ module ActionDispatch
|
|
1342
1352
|
end
|
1343
1353
|
|
1344
1354
|
with_scope_level(:resource) do
|
1345
|
-
options = apply_action_options options
|
1355
|
+
options = apply_action_options :resource, options
|
1346
1356
|
resource_scope(SingletonResource.new(resources.pop, api_only?, @scope[:shallow], options)) do
|
1347
1357
|
yield if block_given?
|
1348
1358
|
|
@@ -1512,7 +1522,7 @@ module ActionDispatch
|
|
1512
1522
|
end
|
1513
1523
|
|
1514
1524
|
with_scope_level(:resources) do
|
1515
|
-
options = apply_action_options options
|
1525
|
+
options = apply_action_options :resources, options
|
1516
1526
|
resource_scope(Resource.new(resources.pop, api_only?, @scope[:shallow], options)) do
|
1517
1527
|
yield if block_given?
|
1518
1528
|
|
@@ -1673,7 +1683,6 @@ module ActionDispatch
|
|
1673
1683
|
# Matches a URL pattern to one or more routes. For more information, see
|
1674
1684
|
# [match](rdoc-ref:Base#match).
|
1675
1685
|
#
|
1676
|
-
# match 'path' => 'controller#action', via: :patch
|
1677
1686
|
# match 'path', to: 'controller#action', via: :post
|
1678
1687
|
# match 'path', 'otherpath', on: :member, via: :get
|
1679
1688
|
def match(path, *rest, &block)
|
@@ -1782,17 +1791,32 @@ module ActionDispatch
|
|
1782
1791
|
false
|
1783
1792
|
end
|
1784
1793
|
|
1785
|
-
def apply_action_options(options)
|
1794
|
+
def apply_action_options(method, options)
|
1786
1795
|
return options if action_options? options
|
1787
|
-
options.merge scope_action_options
|
1796
|
+
options.merge scope_action_options(method)
|
1788
1797
|
end
|
1789
1798
|
|
1790
1799
|
def action_options?(options)
|
1791
1800
|
options[:only] || options[:except]
|
1792
1801
|
end
|
1793
1802
|
|
1794
|
-
def scope_action_options
|
1795
|
-
@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
|
1796
1820
|
end
|
1797
1821
|
|
1798
1822
|
def resource_scope?
|
@@ -1935,6 +1959,11 @@ module ActionDispatch
|
|
1935
1959
|
end
|
1936
1960
|
|
1937
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
|
+
|
1938
1967
|
if (on = options[:on]) && !VALID_ON_OPTIONS.include?(on)
|
1939
1968
|
raise ArgumentError, "Unknown scope #{on.inspect} given to :on"
|
1940
1969
|
end
|
@@ -2025,7 +2054,7 @@ module ActionDispatch
|
|
2025
2054
|
name_for_action(options.delete(:as), action)
|
2026
2055
|
end
|
2027
2056
|
|
2028
|
-
path = Mapping.normalize_path RFC2396_PARSER.escape(path), formatted
|
2057
|
+
path = Mapping.normalize_path URI::RFC2396_PARSER.escape(path), formatted
|
2029
2058
|
ast = Journey::Parser.parse path
|
2030
2059
|
|
2031
2060
|
mapping = Mapping.build(@scope, @set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
|
@@ -2200,8 +2229,8 @@ module ActionDispatch
|
|
2200
2229
|
end
|
2201
2230
|
|
2202
2231
|
# Define custom polymorphic mappings of models to URLs. This alters the behavior
|
2203
|
-
# of `polymorphic_url` and consequently the behavior of `link_to
|
2204
|
-
# 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:
|
2205
2234
|
#
|
2206
2235
|
# resource :basket
|
2207
2236
|
#
|
@@ -2210,7 +2239,7 @@ module ActionDispatch
|
|
2210
2239
|
# end
|
2211
2240
|
#
|
2212
2241
|
# This will now generate "/basket" when a `Basket` instance is passed to
|
2213
|
-
# `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".
|
2214
2243
|
#
|
2215
2244
|
# NOTE: This custom behavior only applies to simple polymorphic URLs where a
|
2216
2245
|
# single model instance is passed and not more complicated forms, e.g:
|
@@ -2267,9 +2296,9 @@ module ActionDispatch
|
|
2267
2296
|
|
2268
2297
|
attr_reader :parent, :scope_level
|
2269
2298
|
|
2270
|
-
def initialize(hash, parent =
|
2271
|
-
@hash = hash
|
2299
|
+
def initialize(hash, parent = ROOT, scope_level = nil)
|
2272
2300
|
@parent = parent
|
2301
|
+
@hash = parent ? parent.frame.merge(hash) : hash
|
2273
2302
|
@scope_level = scope_level
|
2274
2303
|
end
|
2275
2304
|
|
@@ -2282,7 +2311,7 @@ module ActionDispatch
|
|
2282
2311
|
end
|
2283
2312
|
|
2284
2313
|
def root?
|
2285
|
-
@parent
|
2314
|
+
@parent == ROOT
|
2286
2315
|
end
|
2287
2316
|
|
2288
2317
|
def resources?
|
@@ -2327,23 +2356,22 @@ module ActionDispatch
|
|
2327
2356
|
end
|
2328
2357
|
|
2329
2358
|
def [](key)
|
2330
|
-
|
2331
|
-
scope && scope.frame[key]
|
2359
|
+
frame[key]
|
2332
2360
|
end
|
2333
2361
|
|
2362
|
+
def frame; @hash; end
|
2363
|
+
|
2334
2364
|
include Enumerable
|
2335
2365
|
|
2336
2366
|
def each
|
2337
2367
|
node = self
|
2338
|
-
until node.equal?
|
2368
|
+
until node.equal? ROOT
|
2339
2369
|
yield node
|
2340
2370
|
node = node.parent
|
2341
2371
|
end
|
2342
2372
|
end
|
2343
2373
|
|
2344
|
-
|
2345
|
-
|
2346
|
-
NULL = Scope.new(nil, nil)
|
2374
|
+
ROOT = Scope.new({}, nil)
|
2347
2375
|
end
|
2348
2376
|
|
2349
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] = RFC2396_PARSER.unescape(value)
|
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)
|
@@ -9,8 +9,7 @@ module ActionDispatch
|
|
9
9
|
module TestProcess
|
10
10
|
module FixtureFile
|
11
11
|
# Shortcut for
|
12
|
-
# `Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.
|
13
|
-
# ixture_path, path), type)`:
|
12
|
+
# `Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.file_fixture_path, path), type)`:
|
14
13
|
#
|
15
14
|
# post :change_avatar, params: { avatar: file_fixture_upload('david.png', 'image/png') }
|
16
15
|
#
|
data/lib/action_dispatch.rb
CHANGED
@@ -30,7 +30,6 @@ require "active_support/core_ext/module/attribute_accessors"
|
|
30
30
|
|
31
31
|
require "action_pack"
|
32
32
|
require "rack"
|
33
|
-
require "uri"
|
34
33
|
require "action_dispatch/deprecator"
|
35
34
|
|
36
35
|
module Rack # :nodoc:
|
@@ -48,16 +47,19 @@ end
|
|
48
47
|
module ActionDispatch
|
49
48
|
extend ActiveSupport::Autoload
|
50
49
|
|
51
|
-
RFC2396_PARSER = defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::RFC2396_Parser.new
|
52
|
-
private_constant :RFC2396_PARSER
|
53
|
-
|
54
50
|
class MissingController < NameError
|
55
51
|
end
|
56
52
|
|
57
53
|
eager_autoload do
|
58
54
|
autoload_under "http" do
|
59
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"
|
60
61
|
autoload :PermissionsPolicy
|
62
|
+
autoload :QueryParser
|
61
63
|
autoload :Request
|
62
64
|
autoload :Response
|
63
65
|
end
|