actionpack 6.1.5 → 7.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +99 -521
  3. data/MIT-LICENSE +2 -1
  4. data/README.rdoc +2 -3
  5. data/lib/abstract_controller/asset_paths.rb +1 -1
  6. data/lib/abstract_controller/base.rb +7 -21
  7. data/lib/abstract_controller/caching/fragments.rb +2 -2
  8. data/lib/abstract_controller/caching.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +9 -8
  10. data/lib/abstract_controller/collector.rb +2 -2
  11. data/lib/abstract_controller/error.rb +1 -1
  12. data/lib/abstract_controller/helpers.rb +3 -2
  13. data/lib/abstract_controller/logger.rb +1 -1
  14. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  15. data/lib/abstract_controller/translation.rb +0 -2
  16. data/lib/abstract_controller/url_for.rb +4 -6
  17. data/lib/action_controller/api.rb +1 -1
  18. data/lib/action_controller/log_subscriber.rb +3 -1
  19. data/lib/action_controller/metal/conditional_get.rb +38 -1
  20. data/lib/action_controller/metal/content_security_policy.rb +1 -1
  21. data/lib/action_controller/metal/cookies.rb +1 -1
  22. data/lib/action_controller/metal/data_streaming.rb +5 -13
  23. data/lib/action_controller/metal/exceptions.rb +19 -30
  24. data/lib/action_controller/metal/flash.rb +6 -2
  25. data/lib/action_controller/metal/http_authentication.rb +15 -16
  26. data/lib/action_controller/metal/instrumentation.rb +55 -52
  27. data/lib/action_controller/metal/live.rb +42 -2
  28. data/lib/action_controller/metal/mime_responds.rb +3 -3
  29. data/lib/action_controller/metal/params_wrapper.rb +7 -7
  30. data/lib/action_controller/metal/permissions_policy.rb +1 -1
  31. data/lib/action_controller/metal/query_tags.rb +16 -0
  32. data/lib/action_controller/metal/redirecting.rb +50 -16
  33. data/lib/action_controller/metal/rendering.rb +7 -7
  34. data/lib/action_controller/metal/request_forgery_protection.rb +64 -20
  35. data/lib/action_controller/metal/rescue.rb +1 -1
  36. data/lib/action_controller/metal/streaming.rb +1 -3
  37. data/lib/action_controller/metal/strong_parameters.rb +25 -29
  38. data/lib/action_controller/metal/testing.rb +0 -2
  39. data/lib/action_controller/metal.rb +7 -10
  40. data/lib/action_controller/railtie.rb +42 -5
  41. data/lib/action_controller/test_case.rb +6 -2
  42. data/lib/action_controller.rb +2 -5
  43. data/lib/action_dispatch/http/cache.rb +13 -6
  44. data/lib/action_dispatch/http/content_security_policy.rb +40 -37
  45. data/lib/action_dispatch/http/filter_parameters.rb +5 -0
  46. data/lib/action_dispatch/http/mime_negotiation.rb +13 -3
  47. data/lib/action_dispatch/http/mime_type.rb +9 -11
  48. data/lib/action_dispatch/http/parameters.rb +4 -4
  49. data/lib/action_dispatch/http/permissions_policy.rb +1 -1
  50. data/lib/action_dispatch/http/request.rb +10 -19
  51. data/lib/action_dispatch/http/response.rb +3 -3
  52. data/lib/action_dispatch/http/url.rb +9 -10
  53. data/lib/action_dispatch/journey/gtg/builder.rb +11 -12
  54. data/lib/action_dispatch/journey/gtg/simulator.rb +10 -4
  55. data/lib/action_dispatch/journey/gtg/transition_table.rb +77 -21
  56. data/lib/action_dispatch/journey/nodes/node.rb +70 -5
  57. data/lib/action_dispatch/journey/path/pattern.rb +22 -13
  58. data/lib/action_dispatch/journey/route.rb +5 -12
  59. data/lib/action_dispatch/journey/router/utils.rb +2 -2
  60. data/lib/action_dispatch/journey/router.rb +1 -1
  61. data/lib/action_dispatch/journey/routes.rb +3 -3
  62. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  63. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  64. data/lib/action_dispatch/middleware/actionable_exceptions.rb +0 -1
  65. data/lib/action_dispatch/middleware/cookies.rb +7 -3
  66. data/lib/action_dispatch/middleware/debug_exceptions.rb +6 -4
  67. data/lib/action_dispatch/middleware/debug_locks.rb +3 -3
  68. data/lib/action_dispatch/middleware/exception_wrapper.rb +4 -0
  69. data/lib/action_dispatch/middleware/executor.rb +1 -1
  70. data/lib/action_dispatch/middleware/flash.rb +9 -11
  71. data/lib/action_dispatch/middleware/host_authorization.rb +25 -73
  72. data/lib/action_dispatch/middleware/remote_ip.rb +16 -4
  73. data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -1
  74. data/lib/action_dispatch/middleware/show_exceptions.rb +6 -18
  75. data/lib/action_dispatch/middleware/stack.rb +50 -9
  76. data/lib/action_dispatch/middleware/static.rb +2 -5
  77. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +1 -1
  78. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -11
  79. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +2 -2
  80. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +2 -2
  81. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +4 -4
  82. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +3 -3
  83. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +28 -18
  84. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +3 -3
  85. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +3 -3
  86. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  87. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  88. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +3 -3
  89. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +5 -14
  90. data/lib/action_dispatch/railtie.rb +8 -2
  91. data/lib/action_dispatch/request/session.rb +43 -13
  92. data/lib/action_dispatch/routing/mapper.rb +44 -72
  93. data/lib/action_dispatch/routing/redirection.rb +0 -2
  94. data/lib/action_dispatch/routing/route_set.rb +7 -4
  95. data/lib/action_dispatch/routing/routes_proxy.rb +1 -1
  96. data/lib/action_dispatch/routing/url_for.rb +1 -2
  97. data/lib/action_dispatch/routing.rb +2 -2
  98. data/lib/action_dispatch/system_test_case.rb +6 -12
  99. data/lib/action_dispatch/system_testing/driver.rb +24 -4
  100. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +10 -6
  101. data/lib/action_dispatch/testing/assertions.rb +2 -5
  102. data/lib/action_dispatch/testing/integration.rb +6 -8
  103. data/lib/action_dispatch/testing/test_process.rb +2 -2
  104. data/lib/action_dispatch.rb +1 -1
  105. data/lib/action_pack/gem_version.rb +4 -4
  106. data/lib/action_pack.rb +1 -1
  107. metadata +18 -18
@@ -4,7 +4,6 @@ require "active_support/core_ext/hash/slice"
4
4
  require "active_support/core_ext/enumerable"
5
5
  require "active_support/core_ext/array/extract_options"
6
6
  require "active_support/core_ext/regexp"
7
- require "active_support/core_ext/symbol/starts_ends_with"
8
7
  require "action_dispatch/routing/redirection"
9
8
  require "action_dispatch/routing/endpoint"
10
9
 
@@ -13,7 +12,7 @@ module ActionDispatch
13
12
  class Mapper
14
13
  URL_OPTIONS = [:protocol, :subdomain, :domain, :host, :port]
15
14
 
16
- class Constraints < Routing::Endpoint #:nodoc:
15
+ class Constraints < Routing::Endpoint # :nodoc:
17
16
  attr_reader :app, :constraints
18
17
 
19
18
  SERVE = ->(app, req) { app.serve req }
@@ -67,11 +66,11 @@ module ActionDispatch
67
66
  end
68
67
  end
69
68
 
70
- class Mapping #:nodoc:
69
+ class Mapping # :nodoc:
71
70
  ANCHOR_CHARACTERS_REGEX = %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
72
71
  OPTIONAL_FORMAT_REGEX = %r{(?:\(\.:format\)+|\.:format|/)\Z}
73
72
 
74
- attr_reader :requirements, :defaults, :to, :default_controller,
73
+ attr_reader :path, :requirements, :defaults, :to, :default_controller,
75
74
  :default_action, :required_defaults, :ast, :scope_options
76
75
 
77
76
  def self.build(scope, set, ast, controller, default_action, to, via, formatted, options_constraints, anchor, options)
@@ -122,31 +121,17 @@ module ActionDispatch
122
121
  @to = intern(to)
123
122
  @default_controller = intern(controller)
124
123
  @default_action = intern(default_action)
125
- @ast = ast
126
124
  @anchor = anchor
127
125
  @via = via
128
126
  @internal = options.delete(:internal)
129
127
  @scope_options = scope_params[:options]
128
+ ast = Journey::Ast.new(ast, formatted)
130
129
 
131
- path_params = []
132
- wildcard_options = {}
133
- ast.each do |node|
134
- if node.symbol?
135
- path_params << node.to_sym
136
- elsif formatted != false && node.star?
137
- # Add a constraint for wildcard route to make it non-greedy and match the
138
- # optional format part of the route by default.
139
- wildcard_options[node.name.to_sym] ||= /.+?/
140
- elsif node.cat?
141
- alter_regex_for_custom_routes(node)
142
- end
143
- end
144
-
145
- options = wildcard_options.merge!(options)
130
+ options = ast.wildcard_options.merge!(options)
146
131
 
147
- options = normalize_options!(options, path_params, scope_params[:module])
132
+ options = normalize_options!(options, ast.path_params, scope_params[:module])
148
133
 
149
- split_options = constraints(options, path_params)
134
+ split_options = constraints(options, ast.path_params)
150
135
 
151
136
  constraints = scope_params[:constraints].merge Hash[split_options[:constraints] || []]
152
137
 
@@ -160,7 +145,7 @@ module ActionDispatch
160
145
  @blocks = blocks(options_constraints)
161
146
  end
162
147
 
163
- requirements, conditions = split_constraints path_params, constraints
148
+ requirements, conditions = split_constraints ast.path_params, constraints
164
149
  verify_regexp_requirements requirements.map(&:last).grep(Regexp)
165
150
 
166
151
  formats = normalize_format(formatted)
@@ -169,13 +154,18 @@ module ActionDispatch
169
154
  @conditions = Hash[conditions]
170
155
  @defaults = formats[:defaults].merge(@defaults).merge(normalize_defaults(options))
171
156
 
172
- if path_params.include?(:action) && !@requirements.key?(:action)
157
+ if ast.path_params.include?(:action) && !@requirements.key?(:action)
173
158
  @defaults[:action] ||= "index"
174
159
  end
175
160
 
176
161
  @required_defaults = (split_options[:required_defaults] || []).map(&:first)
162
+
163
+ ast.requirements = @requirements
164
+ @path = Journey::Path::Pattern.new(ast, @requirements, JOINED_SEPARATORS, @anchor)
177
165
  end
178
166
 
167
+ JOINED_SEPARATORS = SEPARATORS.join # :nodoc:
168
+
179
169
  def make_route(name, precedence)
180
170
  Journey::Route.new(name: name, app: application, path: path, constraints: conditions,
181
171
  required_defaults: required_defaults, defaults: defaults,
@@ -187,12 +177,6 @@ module ActionDispatch
187
177
  app(@blocks)
188
178
  end
189
179
 
190
- JOINED_SEPARATORS = SEPARATORS.join # :nodoc:
191
-
192
- def path
193
- Journey::Path::Pattern.new(@ast, requirements, JOINED_SEPARATORS, @anchor)
194
- end
195
-
196
180
  def conditions
197
181
  build_conditions @conditions, @set.request_class
198
182
  end
@@ -212,24 +196,6 @@ module ActionDispatch
212
196
  private :request_method
213
197
 
214
198
  private
215
- # Find all the symbol nodes that are adjacent to literal nodes and alter
216
- # the regexp so that Journey will partition them into custom routes.
217
- def alter_regex_for_custom_routes(node)
218
- if node.left.literal? && node.right.symbol?
219
- symbol = node.right
220
- elsif node.left.literal? && node.right.cat? && node.right.left.symbol?
221
- symbol = node.right.left
222
- elsif node.left.symbol? && node.right.literal?
223
- symbol = node.left
224
- elsif node.left.symbol? && node.right.cat? && node.right.left.literal?
225
- symbol = node.left
226
- end
227
-
228
- if symbol
229
- symbol.regexp = /(?:#{Regexp.union(symbol.regexp, '-')})+/
230
- end
231
- end
232
-
233
199
  def intern(object)
234
200
  object.is_a?(String) ? -object : object
235
201
  end
@@ -956,7 +922,7 @@ module ActionDispatch
956
922
  # namespace :admin, as: "sekret" do
957
923
  # resources :posts
958
924
  # end
959
- def namespace(path, options = {})
925
+ def namespace(path, options = {}, &block)
960
926
  path = path.to_s
961
927
 
962
928
  defaults = {
@@ -967,7 +933,7 @@ module ActionDispatch
967
933
  }
968
934
 
969
935
  path_scope(options.delete(:path) { path }) do
970
- scope(defaults.merge!(options)) { yield }
936
+ scope(defaults.merge!(options), &block)
971
937
  end
972
938
  end
973
939
 
@@ -1026,8 +992,8 @@ module ActionDispatch
1026
992
  # constraints(Iphone) do
1027
993
  # resources :iphones
1028
994
  # end
1029
- def constraints(constraints = {})
1030
- scope(constraints: constraints) { yield }
995
+ def constraints(constraints = {}, &block)
996
+ scope(constraints: constraints, &block)
1031
997
  end
1032
998
 
1033
999
  # Allows you to set default parameters for a route, such as this:
@@ -1156,7 +1122,7 @@ module ActionDispatch
1156
1122
  RESOURCE_OPTIONS = [:as, :controller, :path, :only, :except, :param, :concerns]
1157
1123
  CANONICAL_ACTIONS = %w(index create new show update destroy)
1158
1124
 
1159
- class Resource #:nodoc:
1125
+ class Resource # :nodoc:
1160
1126
  attr_reader :controller, :path, :param
1161
1127
 
1162
1128
  def initialize(entities, api_only, shallow, options = {})
@@ -1251,7 +1217,7 @@ module ActionDispatch
1251
1217
  def singleton?; false; end
1252
1218
  end
1253
1219
 
1254
- class SingletonResource < Resource #:nodoc:
1220
+ class SingletonResource < Resource # :nodoc:
1255
1221
  def initialize(entities, api_only, shallow, options)
1256
1222
  super
1257
1223
  @as = nil
@@ -1307,6 +1273,16 @@ module ActionDispatch
1307
1273
  # DELETE /profile
1308
1274
  # POST /profile
1309
1275
  #
1276
+ # If you want instances of a model to work with this resource via
1277
+ # record identification (e.g. in +form_with+ or +redirect_to+), you
1278
+ # will need to call resolve[rdoc-ref:CustomUrls#resolve]:
1279
+ #
1280
+ # resource :profile
1281
+ # resolve('Profile') { [:profile] }
1282
+ #
1283
+ # # Enables this to work with singular routes:
1284
+ # form_with(model: @profile) {}
1285
+ #
1310
1286
  # === Options
1311
1287
  # Takes same options as resources[rdoc-ref:#resources]
1312
1288
  def resource(*resources, &block)
@@ -1517,15 +1493,13 @@ module ActionDispatch
1517
1493
  # with GET, and route to the search action of +PhotosController+. It will also
1518
1494
  # create the <tt>search_photos_url</tt> and <tt>search_photos_path</tt>
1519
1495
  # route helpers.
1520
- def collection
1496
+ def collection(&block)
1521
1497
  unless resource_scope?
1522
1498
  raise ArgumentError, "can't use collection outside resource(s) scope"
1523
1499
  end
1524
1500
 
1525
1501
  with_scope_level(:collection) do
1526
- path_scope(parent_resource.collection_scope) do
1527
- yield
1528
- end
1502
+ path_scope(parent_resource.collection_scope, &block)
1529
1503
  end
1530
1504
  end
1531
1505
 
@@ -1540,7 +1514,7 @@ module ActionDispatch
1540
1514
  # This will recognize <tt>/photos/1/preview</tt> with GET, and route to the
1541
1515
  # preview action of +PhotosController+. It will also create the
1542
1516
  # <tt>preview_photo_url</tt> and <tt>preview_photo_path</tt> helpers.
1543
- def member
1517
+ def member(&block)
1544
1518
  unless resource_scope?
1545
1519
  raise ArgumentError, "can't use member outside resource(s) scope"
1546
1520
  end
@@ -1548,27 +1522,25 @@ module ActionDispatch
1548
1522
  with_scope_level(:member) do
1549
1523
  if shallow?
1550
1524
  shallow_scope {
1551
- path_scope(parent_resource.member_scope) { yield }
1525
+ path_scope(parent_resource.member_scope, &block)
1552
1526
  }
1553
1527
  else
1554
- path_scope(parent_resource.member_scope) { yield }
1528
+ path_scope(parent_resource.member_scope, &block)
1555
1529
  end
1556
1530
  end
1557
1531
  end
1558
1532
 
1559
- def new
1533
+ def new(&block)
1560
1534
  unless resource_scope?
1561
1535
  raise ArgumentError, "can't use new outside resource(s) scope"
1562
1536
  end
1563
1537
 
1564
1538
  with_scope_level(:new) do
1565
- path_scope(parent_resource.new_scope(action_path(:new))) do
1566
- yield
1567
- end
1539
+ path_scope(parent_resource.new_scope(action_path(:new)), &block)
1568
1540
  end
1569
1541
  end
1570
1542
 
1571
- def nested
1543
+ def nested(&block)
1572
1544
  unless resource_scope?
1573
1545
  raise ArgumentError, "can't use nested outside resource(s) scope"
1574
1546
  end
@@ -1577,12 +1549,12 @@ module ActionDispatch
1577
1549
  if shallow? && shallow_nesting_depth >= 1
1578
1550
  shallow_scope do
1579
1551
  path_scope(parent_resource.nested_scope) do
1580
- scope(nested_options) { yield }
1552
+ scope(nested_options, &block)
1581
1553
  end
1582
1554
  end
1583
1555
  else
1584
1556
  path_scope(parent_resource.nested_scope) do
1585
- scope(nested_options) { yield }
1557
+ scope(nested_options, &block)
1586
1558
  end
1587
1559
  end
1588
1560
  end
@@ -1768,10 +1740,10 @@ module ActionDispatch
1768
1740
  @scope = @scope.parent
1769
1741
  end
1770
1742
 
1771
- def resource_scope(resource)
1743
+ def resource_scope(resource, &block)
1772
1744
  @scope = @scope.new(scope_level_resource: resource)
1773
1745
 
1774
- controller(resource.resource_scope) { yield }
1746
+ controller(resource.resource_scope, &block)
1775
1747
  ensure
1776
1748
  @scope = @scope.parent
1777
1749
  end
@@ -1889,7 +1861,7 @@ module ActionDispatch
1889
1861
  end
1890
1862
 
1891
1863
  def map_match(paths, options)
1892
- if options[:on] && !VALID_ON_OPTIONS.include?(options[:on])
1864
+ if (on = options[:on]) && !VALID_ON_OPTIONS.include?(on)
1893
1865
  raise ArgumentError, "Unknown scope #{on.inspect} given to :on"
1894
1866
  end
1895
1867
 
@@ -2300,7 +2272,7 @@ module ActionDispatch
2300
2272
  NULL = Scope.new(nil, nil)
2301
2273
  end
2302
2274
 
2303
- def initialize(set) #:nodoc:
2275
+ def initialize(set) # :nodoc:
2304
2276
  @set = set
2305
2277
  @draw_paths = set.draw_paths
2306
2278
  @scope = Scope.new(path_names: @set.resources_path_names)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "action_dispatch/http/request"
4
- require "active_support/core_ext/uri"
5
3
  require "active_support/core_ext/array/extract_options"
6
4
  require "rack/utils"
7
5
  require "action_controller/metal/exceptions"
@@ -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
@@ -132,8 +131,8 @@ module ActionDispatch
132
131
  alias [] get
133
132
  alias clear clear!
134
133
 
135
- def each
136
- routes.each { |name, route| yield name, route }
134
+ def each(&block)
135
+ routes.each(&block)
137
136
  self
138
137
  end
139
138
 
@@ -824,7 +823,11 @@ module ActionDispatch
824
823
  params = route_with_params.params
825
824
 
826
825
  if options.key? :params
827
- params.merge! options[:params]
826
+ if options[:params]&.respond_to?(:to_hash)
827
+ params.merge! options[:params]
828
+ else
829
+ params[:params] = options[:params]
830
+ end
828
831
  end
829
832
 
830
833
  options[:path] = path
@@ -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 #:nodoc:
7
+ class RoutesProxy # :nodoc:
8
8
  include ActionDispatch::Routing::UrlFor
9
9
 
10
10
  attr_accessor :scope, :routes
@@ -103,11 +103,10 @@ module ActionDispatch
103
103
  include(*_url_for_modules) if respond_to?(:_url_for_modules)
104
104
  end
105
105
 
106
- def initialize(*)
106
+ def initialize(...)
107
107
  @_routes = nil
108
108
  super
109
109
  end
110
- ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
111
110
 
112
111
  # Hook overridden in controller to add request information
113
112
  # with +default_url_options+. Application logic should not
@@ -255,7 +255,7 @@ module ActionDispatch
255
255
  autoload :UrlFor
256
256
  autoload :PolymorphicRoutes
257
257
 
258
- SEPARATORS = %w( / . ? ) #:nodoc:
259
- HTTP_METHODS = [:get, :head, :post, :patch, :put, :delete, :options] #:nodoc:
258
+ SEPARATORS = %w( / . ? ) # :nodoc:
259
+ HTTP_METHODS = [:get, :head, :post, :patch, :put, :delete, :options] # :nodoc:
260
260
  end
261
261
  end
@@ -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 Poltergeist, update your Gemfile to use
76
- # Poltergeist instead of Selenium and then declare the driver name in the
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/poltergeist"
84
+ # require "capybara/cuprite"
85
85
  #
86
86
  # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
87
- # driven_by :poltergeist, screen_size: [1400, 1400], options:
87
+ # driven_by :cuprite, screen_size: [1400, 1400], options:
88
88
  # { js_errors: true }
89
89
  # end
90
90
  #
@@ -115,8 +115,6 @@ module ActionDispatch
115
115
  include SystemTesting::TestHelpers::SetupAndTeardown
116
116
  include SystemTesting::TestHelpers::ScreenshotHelper
117
117
 
118
- DEFAULT_HOST = "http://127.0.0.1"
119
-
120
118
  def initialize(*) # :nodoc:
121
119
  super
122
120
  self.class.driven_by(:selenium) unless self.class.driver?
@@ -142,7 +140,7 @@ module ActionDispatch
142
140
  #
143
141
  # Examples:
144
142
  #
145
- # driven_by :poltergeist
143
+ # driven_by :cuprite
146
144
  #
147
145
  # driven_by :selenium, screen_size: [800, 800]
148
146
  #
@@ -168,11 +166,7 @@ module ActionDispatch
168
166
  include ActionDispatch.test_app.routes.mounted_helpers
169
167
 
170
168
  def url_options
171
- default_url_options.reverse_merge(host: app_host)
172
- end
173
-
174
- def app_host
175
- Capybara.app_host || Capybara.current_session.server_url || DEFAULT_HOST
169
+ default_url_options.reverse_merge(host: Capybara.app_host || Capybara.current_session.server_url)
176
170
  end
177
171
  end.new
178
172
  end
@@ -5,14 +5,24 @@ module ActionDispatch
5
5
  class Driver # :nodoc:
6
6
  def initialize(name, **options, &capabilities)
7
7
  @name = name
8
- @browser = Browser.new(options[:using])
9
8
  @screen_size = options[:screen_size]
10
9
  @options = options[:options] || {}
11
10
  @capabilities = capabilities
12
11
 
12
+ if [:poltergeist, :webkit].include?(name)
13
+ ActiveSupport::Deprecation.warn <<~MSG.squish
14
+ Poltergeist and capybara-webkit are not maintained already.
15
+ Driver registration of :poltergeist or :webkit is deprecated and will be removed in Rails 7.1.
16
+ You can still use :selenium, and also :cuprite is available for alternative to Poltergeist.
17
+ MSG
18
+ end
19
+
13
20
  if name == :selenium
14
21
  require "selenium/webdriver"
22
+ @browser = Browser.new(options[:using])
15
23
  @browser.preload
24
+ else
25
+ @browser = nil
16
26
  end
17
27
  end
18
28
 
@@ -24,17 +34,19 @@ module ActionDispatch
24
34
 
25
35
  private
26
36
  def registerable?
27
- [:selenium, :poltergeist, :webkit].include?(@name)
37
+ [:selenium, :poltergeist, :webkit, :cuprite, :rack_test].include?(@name)
28
38
  end
29
39
 
30
40
  def register
31
- @browser.configure(&@capabilities)
41
+ @browser&.configure(&@capabilities)
32
42
 
33
43
  Capybara.register_driver @name do |app|
34
44
  case @name
35
45
  when :selenium then register_selenium(app)
36
46
  when :poltergeist then register_poltergeist(app)
37
47
  when :webkit then register_webkit(app)
48
+ when :cuprite then register_cuprite(app)
49
+ when :rack_test then register_rack_test(app)
38
50
  end
39
51
  end
40
52
  end
@@ -44,7 +56,7 @@ module ActionDispatch
44
56
  end
45
57
 
46
58
  def register_selenium(app)
47
- Capybara::Selenium::Driver.new(app, **{ browser: @browser.type }.merge(browser_options)).tap do |driver|
59
+ Capybara::Selenium::Driver.new(app, browser: @browser.type, **browser_options).tap do |driver|
48
60
  driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*@screen_size)
49
61
  end
50
62
  end
@@ -59,6 +71,14 @@ module ActionDispatch
59
71
  end
60
72
  end
61
73
 
74
+ def register_cuprite(app)
75
+ Capybara::Cuprite::Driver.new(app, @options.merge(window_size: @screen_size))
76
+ end
77
+
78
+ def register_rack_test(app)
79
+ Capybara::RackTest::Driver.new(app, respect_data_method: true, **@options)
80
+ end
81
+
62
82
  def setup
63
83
  Capybara.current_driver = @name
64
84
  end
@@ -15,8 +15,11 @@ module ActionDispatch
15
15
  #
16
16
  # The screenshot will be displayed in your console, if supported.
17
17
  #
18
+ # The default screenshots directory is +tmp/screenshots+ but you can set a different
19
+ # one with +Capybara.save_path+
20
+ #
18
21
  # You can set the +RAILS_SYSTEM_TESTING_SCREENSHOT_HTML+ environment variable to
19
- # save the HTML from the page that is being screenhoted so you can investigate the
22
+ # save the HTML from the page that is being screenshotted so you can investigate the
20
23
  # elements on the page at the time of the screenshot
21
24
  #
22
25
  # You can set the +RAILS_SYSTEM_TESTING_SCREENSHOT+ environment variable to
@@ -37,10 +40,7 @@ module ActionDispatch
37
40
  # Takes a screenshot of the current page in the browser if the test
38
41
  # failed.
39
42
  #
40
- # +take_failed_screenshot+ is included in <tt>application_system_test_case.rb</tt>
41
- # that is generated with the application. To take screenshots when a test
42
- # fails add +take_failed_screenshot+ to the teardown block before clearing
43
- # sessions.
43
+ # +take_failed_screenshot+ is called during system test teardown.
44
44
  def take_failed_screenshot
45
45
  take_screenshot if failed? && supports_screenshot?
46
46
  end
@@ -76,7 +76,11 @@ module ActionDispatch
76
76
  end
77
77
 
78
78
  def absolute_path
79
- Rails.root.join("tmp/screenshots/#{image_name}")
79
+ Rails.root.join(screenshots_dir, image_name)
80
+ end
81
+
82
+ def screenshots_dir
83
+ Capybara.save_path.presence || "tmp/screenshots"
80
84
  end
81
85
 
82
86
  def absolute_image_path
@@ -1,14 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rails-dom-testing"
4
+ require "action_dispatch/testing/assertions/response"
5
+ require "action_dispatch/testing/assertions/routing"
4
6
 
5
7
  module ActionDispatch
6
8
  module Assertions
7
- autoload :ResponseAssertions, "action_dispatch/testing/assertions/response"
8
- autoload :RoutingAssertions, "action_dispatch/testing/assertions/routing"
9
-
10
- extend ActiveSupport::Concern
11
-
12
9
  include ResponseAssertions
13
10
  include RoutingAssertions
14
11
  include Rails::Dom::Testing::Assertions
@@ -8,7 +8,7 @@ require "minitest"
8
8
  require "action_dispatch/testing/request_encoder"
9
9
 
10
10
  module ActionDispatch
11
- module Integration #:nodoc:
11
+ module Integration # :nodoc:
12
12
  module RequestHelpers
13
13
  # Performs a GET request with the given parameters. See ActionDispatch::Integration::Session#process
14
14
  # for more details.
@@ -199,7 +199,7 @@ module ActionDispatch
199
199
  # merged into the Rack env hash.
200
200
  # - +env+: Additional env to pass, as a Hash. The headers will be
201
201
  # merged into the Rack env hash.
202
- # - +xhr+: Set to +true+ if you want to make and Ajax request.
202
+ # - +xhr+: Set to +true+ if you want to make an Ajax request.
203
203
  # Adds request headers characteristic of XMLHttpRequest e.g. HTTP_X_REQUESTED_WITH.
204
204
  # The headers will be merged into the Rack env hash.
205
205
  # - +as+: Used for encoding the request with different content type.
@@ -363,13 +363,11 @@ module ActionDispatch
363
363
  reset_html_document = "@html_document = nil"
364
364
  end
365
365
 
366
- definition = RUBY_VERSION >= "2.7" ? "..." : "*args"
367
-
368
366
  module_eval <<~RUBY, __FILE__, __LINE__ + 1
369
- def #{method}(#{definition})
367
+ def #{method}(...)
370
368
  #{reset_html_document}
371
369
 
372
- result = integration_session.#{method}(#{definition})
370
+ result = integration_session.#{method}(...)
373
371
  copy_session_variables!
374
372
  result
375
373
  end
@@ -404,7 +402,7 @@ module ActionDispatch
404
402
 
405
403
  # Copy the instance variables from the current session instance into the
406
404
  # test instance.
407
- def copy_session_variables! #:nodoc:
405
+ def copy_session_variables! # :nodoc:
408
406
  @controller = @integration_session.controller
409
407
  @response = @integration_session.response
410
408
  @request = @integration_session.request
@@ -433,7 +431,7 @@ module ActionDispatch
433
431
  super
434
432
  end
435
433
  end
436
- ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
434
+ ruby2_keywords(:method_missing)
437
435
  end
438
436
  end
439
437
 
@@ -8,14 +8,14 @@ module ActionDispatch
8
8
  module FixtureFile
9
9
  # Shortcut for <tt>Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.file_fixture_path, path), type)</tt>:
10
10
  #
11
- # post :change_avatar, params: { avatar: fixture_file_upload('spongebob.png', 'image/png') }
11
+ # post :change_avatar, params: { avatar: fixture_file_upload('david.png', 'image/png') }
12
12
  #
13
13
  # Default fixture files location is <tt>test/fixtures/files</tt>.
14
14
  #
15
15
  # To upload binary files on Windows, pass <tt>:binary</tt> as the last parameter.
16
16
  # This will not affect other platforms:
17
17
  #
18
- # post :change_avatar, params: { avatar: fixture_file_upload('spongebob.png', 'image/png', :binary) }
18
+ # post :change_avatar, params: { avatar: fixture_file_upload('david.png', 'image/png', :binary) }
19
19
  def fixture_file_upload(path, mime_type = nil, binary = false)
20
20
  if self.class.respond_to?(:fixture_path) && self.class.fixture_path &&
21
21
  !File.exist?(path)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2004-2022 David Heinemeier Hansson
4
+ # Copyright (c) 2004-2021 David Heinemeier Hansson
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
@@ -7,10 +7,10 @@ module ActionPack
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 6
11
- MINOR = 1
12
- TINY = 5
13
- PRE = nil
10
+ MAJOR = 7
11
+ MINOR = 0
12
+ TINY = 0
13
+ PRE = "alpha1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
data/lib/action_pack.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2004-2022 David Heinemeier Hansson
4
+ # Copyright (c) 2004-2021 David Heinemeier Hansson
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the