actionpack 7.0.8 → 7.1.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +360 -353
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -2
  5. data/lib/abstract_controller/base.rb +20 -11
  6. data/lib/abstract_controller/caching/fragments.rb +2 -0
  7. data/lib/abstract_controller/callbacks.rb +31 -6
  8. data/lib/abstract_controller/deprecator.rb +7 -0
  9. data/lib/abstract_controller/helpers.rb +61 -18
  10. data/lib/abstract_controller/railties/routes_helpers.rb +1 -16
  11. data/lib/abstract_controller/rendering.rb +3 -3
  12. data/lib/abstract_controller/translation.rb +7 -4
  13. data/lib/abstract_controller/url_for.rb +2 -0
  14. data/lib/abstract_controller.rb +6 -0
  15. data/lib/action_controller/api.rb +5 -3
  16. data/lib/action_controller/base.rb +3 -17
  17. data/lib/action_controller/caching.rb +2 -0
  18. data/lib/action_controller/deprecator.rb +7 -0
  19. data/lib/action_controller/form_builder.rb +2 -0
  20. data/lib/action_controller/log_subscriber.rb +16 -4
  21. data/lib/action_controller/metal/content_security_policy.rb +1 -1
  22. data/lib/action_controller/metal/data_streaming.rb +2 -0
  23. data/lib/action_controller/metal/default_headers.rb +2 -0
  24. data/lib/action_controller/metal/etag_with_flash.rb +2 -0
  25. data/lib/action_controller/metal/etag_with_template_digest.rb +2 -0
  26. data/lib/action_controller/metal/exceptions.rb +8 -0
  27. data/lib/action_controller/metal/head.rb +8 -6
  28. data/lib/action_controller/metal/helpers.rb +3 -14
  29. data/lib/action_controller/metal/http_authentication.rb +17 -8
  30. data/lib/action_controller/metal/implicit_render.rb +5 -3
  31. data/lib/action_controller/metal/instrumentation.rb +8 -1
  32. data/lib/action_controller/metal/live.rb +24 -0
  33. data/lib/action_controller/metal/mime_responds.rb +2 -2
  34. data/lib/action_controller/metal/params_wrapper.rb +4 -2
  35. data/lib/action_controller/metal/permissions_policy.rb +1 -1
  36. data/lib/action_controller/metal/redirecting.rb +7 -7
  37. data/lib/action_controller/metal/renderers.rb +2 -2
  38. data/lib/action_controller/metal/rendering.rb +0 -7
  39. data/lib/action_controller/metal/request_forgery_protection.rb +139 -50
  40. data/lib/action_controller/metal/rescue.rb +2 -0
  41. data/lib/action_controller/metal/streaming.rb +70 -30
  42. data/lib/action_controller/metal/strong_parameters.rb +132 -52
  43. data/lib/action_controller/metal/url_for.rb +7 -0
  44. data/lib/action_controller/metal.rb +79 -21
  45. data/lib/action_controller/railtie.rb +22 -9
  46. data/lib/action_controller/renderer.rb +98 -65
  47. data/lib/action_controller/test_case.rb +15 -5
  48. data/lib/action_controller.rb +8 -1
  49. data/lib/action_dispatch/constants.rb +32 -0
  50. data/lib/action_dispatch/deprecator.rb +7 -0
  51. data/lib/action_dispatch/http/cache.rb +1 -3
  52. data/lib/action_dispatch/http/content_security_policy.rb +9 -8
  53. data/lib/action_dispatch/http/filter_parameters.rb +11 -5
  54. data/lib/action_dispatch/http/headers.rb +2 -0
  55. data/lib/action_dispatch/http/mime_negotiation.rb +22 -22
  56. data/lib/action_dispatch/http/mime_type.rb +35 -12
  57. data/lib/action_dispatch/http/mime_types.rb +3 -1
  58. data/lib/action_dispatch/http/parameters.rb +1 -1
  59. data/lib/action_dispatch/http/permissions_policy.rb +40 -18
  60. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  61. data/lib/action_dispatch/http/request.rb +48 -14
  62. data/lib/action_dispatch/http/response.rb +80 -59
  63. data/lib/action_dispatch/http/upload.rb +2 -0
  64. data/lib/action_dispatch/journey/formatter.rb +8 -2
  65. data/lib/action_dispatch/journey/path/pattern.rb +14 -14
  66. data/lib/action_dispatch/journey/route.rb +3 -2
  67. data/lib/action_dispatch/journey/router.rb +9 -8
  68. data/lib/action_dispatch/journey/routes.rb +2 -2
  69. data/lib/action_dispatch/log_subscriber.rb +23 -0
  70. data/lib/action_dispatch/middleware/actionable_exceptions.rb +5 -6
  71. data/lib/action_dispatch/middleware/assume_ssl.rb +24 -0
  72. data/lib/action_dispatch/middleware/callbacks.rb +2 -0
  73. data/lib/action_dispatch/middleware/cookies.rb +81 -98
  74. data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -25
  75. data/lib/action_dispatch/middleware/debug_locks.rb +4 -1
  76. data/lib/action_dispatch/middleware/debug_view.rb +7 -2
  77. data/lib/action_dispatch/middleware/exception_wrapper.rb +186 -27
  78. data/lib/action_dispatch/middleware/executor.rb +1 -1
  79. data/lib/action_dispatch/middleware/flash.rb +7 -0
  80. data/lib/action_dispatch/middleware/host_authorization.rb +6 -3
  81. data/lib/action_dispatch/middleware/public_exceptions.rb +5 -3
  82. data/lib/action_dispatch/middleware/reloader.rb +7 -5
  83. data/lib/action_dispatch/middleware/remote_ip.rb +17 -16
  84. data/lib/action_dispatch/middleware/request_id.rb +2 -0
  85. data/lib/action_dispatch/middleware/server_timing.rb +4 -4
  86. data/lib/action_dispatch/middleware/session/abstract_store.rb +5 -0
  87. data/lib/action_dispatch/middleware/session/cache_store.rb +2 -0
  88. data/lib/action_dispatch/middleware/session/cookie_store.rb +11 -5
  89. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +3 -1
  90. data/lib/action_dispatch/middleware/show_exceptions.rb +19 -15
  91. data/lib/action_dispatch/middleware/ssl.rb +18 -6
  92. data/lib/action_dispatch/middleware/stack.rb +7 -2
  93. data/lib/action_dispatch/middleware/static.rb +12 -8
  94. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +2 -2
  95. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +4 -4
  96. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +8 -1
  97. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
  98. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
  99. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
  100. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
  101. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
  102. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  103. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
  104. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  105. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  106. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
  107. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +46 -37
  108. data/lib/action_dispatch/railtie.rb +14 -4
  109. data/lib/action_dispatch/request/session.rb +16 -6
  110. data/lib/action_dispatch/request/utils.rb +8 -3
  111. data/lib/action_dispatch/routing/inspector.rb +54 -6
  112. data/lib/action_dispatch/routing/mapper.rb +35 -24
  113. data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
  114. data/lib/action_dispatch/routing/redirection.rb +15 -6
  115. data/lib/action_dispatch/routing/route_set.rb +52 -22
  116. data/lib/action_dispatch/routing/routes_proxy.rb +10 -15
  117. data/lib/action_dispatch/routing/url_for.rb +5 -1
  118. data/lib/action_dispatch/routing.rb +7 -7
  119. data/lib/action_dispatch/system_test_case.rb +3 -3
  120. data/lib/action_dispatch/system_testing/browser.rb +20 -19
  121. data/lib/action_dispatch/system_testing/driver.rb +13 -21
  122. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +27 -16
  123. data/lib/action_dispatch/testing/assertion_response.rb +1 -1
  124. data/lib/action_dispatch/testing/assertions/response.rb +13 -6
  125. data/lib/action_dispatch/testing/assertions/routing.rb +67 -28
  126. data/lib/action_dispatch/testing/assertions.rb +3 -1
  127. data/lib/action_dispatch/testing/integration.rb +27 -17
  128. data/lib/action_dispatch/testing/request_encoder.rb +4 -1
  129. data/lib/action_dispatch/testing/test_process.rb +4 -3
  130. data/lib/action_dispatch/testing/test_request.rb +1 -1
  131. data/lib/action_dispatch/testing/test_response.rb +23 -9
  132. data/lib/action_dispatch.rb +37 -4
  133. data/lib/action_pack/gem_version.rb +4 -4
  134. data/lib/action_pack/version.rb +1 -1
  135. data/lib/action_pack.rb +1 -1
  136. metadata +64 -28
@@ -9,6 +9,36 @@ module ActionDispatch
9
9
  module Assertions
10
10
  # Suite of assertions to test routes generated by \Rails and the handling of requests made to them.
11
11
  module RoutingAssertions
12
+ extend ActiveSupport::Concern
13
+
14
+ module ClassMethods
15
+ # A helper to make it easier to test different route configurations.
16
+ # This method temporarily replaces @routes with a new RouteSet instance
17
+ # before each test.
18
+ #
19
+ # The new instance is yielded to the passed block. Typically the block
20
+ # will create some routes using <tt>set.draw { match ... }</tt>:
21
+ #
22
+ # with_routing do |set|
23
+ # set.draw do
24
+ # resources :users
25
+ # end
26
+ # end
27
+ #
28
+ def with_routing(&block)
29
+ old_routes, old_controller = nil
30
+
31
+ setup do
32
+ old_routes, old_controller = @routes, @controller
33
+ create_routes(&block)
34
+ end
35
+
36
+ teardown do
37
+ reset_routes(old_routes, old_controller)
38
+ end
39
+ end
40
+ end
41
+
12
42
  def setup # :nodoc:
13
43
  @routes ||= nil
14
44
  super
@@ -83,7 +113,7 @@ module ActionDispatch
83
113
  # # Asserts that the generated route gives us our custom route
84
114
  # assert_generates "changesets/12", { controller: 'scm', action: 'show_diff', revision: "12" }
85
115
  def assert_generates(expected_path, options, defaults = {}, extras = {}, message = nil)
86
- if %r{://}.match?(expected_path)
116
+ if expected_path.include?("://")
87
117
  fail_on(URI::InvalidURIError, message) do
88
118
  uri = URI.parse(expected_path)
89
119
  expected_path = uri.path.to_s.empty? ? "/" : uri.path
@@ -150,33 +180,11 @@ module ActionDispatch
150
180
  # assert_equal "/users", users_path
151
181
  # end
152
182
  #
153
- def with_routing
154
- old_routes, @routes = @routes, ActionDispatch::Routing::RouteSet.new
155
- if defined?(@controller) && @controller
156
- old_controller, @controller = @controller, @controller.clone
157
- _routes = @routes
158
-
159
- @controller.singleton_class.include(_routes.url_helpers)
160
-
161
- if @controller.respond_to? :view_context_class
162
- view_context_class = Class.new(@controller.view_context_class) do
163
- include _routes.url_helpers
164
- end
165
-
166
- custom_view_context = Module.new {
167
- define_method(:view_context_class) do
168
- view_context_class
169
- end
170
- }
171
- @controller.extend(custom_view_context)
172
- end
173
- end
174
- yield @routes
183
+ def with_routing(&block)
184
+ old_routes, old_controller = @routes, @controller
185
+ create_routes(&block)
175
186
  ensure
176
- @routes = old_routes
177
- if defined?(@controller) && @controller
178
- @controller = old_controller
179
- end
187
+ reset_routes(old_routes, old_controller)
180
188
  end
181
189
 
182
190
  # ROUTES TODO: These assertions should really work in an integration context
@@ -190,6 +198,37 @@ module ActionDispatch
190
198
  ruby2_keywords(:method_missing)
191
199
 
192
200
  private
201
+ def create_routes
202
+ @routes = ActionDispatch::Routing::RouteSet.new
203
+ if defined?(@controller) && @controller
204
+ @controller = @controller.clone
205
+ _routes = @routes
206
+
207
+ @controller.singleton_class.include(_routes.url_helpers)
208
+
209
+ if @controller.respond_to? :view_context_class
210
+ view_context_class = Class.new(@controller.view_context_class) do
211
+ include _routes.url_helpers
212
+ end
213
+
214
+ custom_view_context = Module.new {
215
+ define_method(:view_context_class) do
216
+ view_context_class
217
+ end
218
+ }
219
+ @controller.extend(custom_view_context)
220
+ end
221
+ end
222
+ yield @routes
223
+ end
224
+
225
+ def reset_routes(old_routes, old_controller)
226
+ @routes = old_routes
227
+ if defined?(@controller) && @controller
228
+ @controller = old_controller
229
+ end
230
+ end
231
+
193
232
  # Recognizes the route for a given path.
194
233
  def recognized_request_for(path, extras = {}, msg)
195
234
  if path.is_a?(Hash)
@@ -202,7 +241,7 @@ module ActionDispatch
202
241
  controller = @controller if defined?(@controller)
203
242
  request = ActionController::TestRequest.create controller&.class
204
243
 
205
- if %r{://}.match?(path)
244
+ if path.include?("://")
206
245
  fail_on(URI::InvalidURIError, msg) do
207
246
  uri = URI.parse(path)
208
247
  request.env["rack.url_scheme"] = uri.scheme || "http"
@@ -6,6 +6,8 @@ require "action_dispatch/testing/assertions/routing"
6
6
 
7
7
  module ActionDispatch
8
8
  module Assertions
9
+ extend ActiveSupport::Concern
10
+
9
11
  include ResponseAssertions
10
12
  include RoutingAssertions
11
13
  include Rails::Dom::Testing::Assertions
@@ -14,7 +16,7 @@ module ActionDispatch
14
16
  @html_document ||= if @response.media_type&.end_with?("xml")
15
17
  Nokogiri::XML::Document.parse(@response.body)
16
18
  else
17
- Nokogiri::HTML::Document.parse(@response.body)
19
+ Rails::Dom::Testing.html_document.parse(@response.body)
18
20
  end
19
21
  end
20
22
  end
@@ -3,7 +3,7 @@
3
3
  require "stringio"
4
4
  require "uri"
5
5
  require "rack/test"
6
- require "minitest"
6
+ require "active_support/test_case"
7
7
 
8
8
  require "action_dispatch/testing/request_encoder"
9
9
 
@@ -58,7 +58,9 @@ module ActionDispatch
58
58
  # the same HTTP verb will be used when redirecting, otherwise a GET request
59
59
  # will be performed. Any arguments are passed to the
60
60
  # underlying request.
61
- def follow_redirect!(**args)
61
+ #
62
+ # The HTTP_REFERER header will be set to the previous url.
63
+ def follow_redirect!(headers: {}, **args)
62
64
  raise "not a redirect! #{status} #{status_message}" unless redirect?
63
65
 
64
66
  method =
@@ -68,7 +70,11 @@ module ActionDispatch
68
70
  :get
69
71
  end
70
72
 
71
- public_send(method, response.location, **args)
73
+ if [ :HTTP_REFERER, "HTTP_REFERER" ].none? { |key| headers.key? key }
74
+ headers["HTTP_REFERER"] = request.url
75
+ end
76
+
77
+ public_send(method, response.location, headers: headers, **args)
72
78
  status
73
79
  end
74
80
  end
@@ -78,9 +84,8 @@ module ActionDispatch
78
84
  # multiple sessions and run them side-by-side, you can also mimic (to some
79
85
  # limited extent) multiple simultaneous users interacting with your system.
80
86
  #
81
- # Typically, you will instantiate a new session using
82
- # IntegrationTest#open_session, rather than instantiating
83
- # Integration::Session directly.
87
+ # Typically, you will instantiate a new session using Runner#open_session,
88
+ # rather than instantiating a \Session directly.
84
89
  class Session
85
90
  DEFAULT_HOST = "www.example.com"
86
91
 
@@ -122,7 +127,7 @@ module ActionDispatch
122
127
 
123
128
  include ActionDispatch::Routing::UrlFor
124
129
 
125
- # Create and initialize a new Session instance.
130
+ # Create and initialize a new \Session instance.
126
131
  def initialize(app)
127
132
  super()
128
133
  @app = app
@@ -206,9 +211,10 @@ module ActionDispatch
206
211
  # Supports +:json+ by default and will set the appropriate request headers.
207
212
  # The headers will be merged into the Rack env hash.
208
213
  #
209
- # This method is rarely used directly. Use +#get+, +#post+, or other standard
210
- # HTTP methods in integration tests. +#process+ is only required when using a
211
- # request method that doesn't have a method defined in the integration tests.
214
+ # This method is rarely used directly. Use RequestHelpers#get,
215
+ # RequestHelpers#post, or other standard HTTP methods in integration
216
+ # tests. +#process+ is only required when using a request method that
217
+ # doesn't have a method defined in the integration tests.
212
218
  #
213
219
  # This method returns the response status, after performing the request.
214
220
  # Furthermore, if this method was called from an ActionDispatch::IntegrationTest object,
@@ -226,7 +232,7 @@ module ActionDispatch
226
232
  method = :post
227
233
  end
228
234
 
229
- if %r{://}.match?(path)
235
+ if path.include?("://")
230
236
  path = build_expanded_path(path) do |location|
231
237
  https! URI::HTTPS === location if location.scheme
232
238
 
@@ -252,10 +258,13 @@ module ActionDispatch
252
258
  "REQUEST_URI" => path,
253
259
  "HTTP_HOST" => host,
254
260
  "REMOTE_ADDR" => remote_addr,
255
- "CONTENT_TYPE" => request_encoder.content_type,
256
261
  "HTTP_ACCEPT" => request_encoder.accept_header || accept
257
262
  }
258
263
 
264
+ if request_encoder.content_type
265
+ request_env["CONTENT_TYPE"] = request_encoder.content_type
266
+ end
267
+
259
268
  wrapped_headers = Http::Headers.from_hash({})
260
269
  wrapped_headers.merge!(headers) if headers
261
270
 
@@ -440,8 +449,9 @@ module ActionDispatch
440
449
  # more completely than either unit or functional tests do, exercising the
441
450
  # entire stack, from the dispatcher to the database.
442
451
  #
443
- # At its simplest, you simply extend <tt>IntegrationTest</tt> and write your tests
444
- # using the get/post methods:
452
+ # At its simplest, you simply extend <tt>IntegrationTest</tt> and write your
453
+ # tests using the Integration::RequestHelpers#get and/or
454
+ # Integration::RequestHelpers#post methods:
445
455
  #
446
456
  # require "test_helper"
447
457
  #
@@ -612,7 +622,7 @@ module ActionDispatch
612
622
  # the request format to JSON unless overridden), sets the content type to
613
623
  # "application/json" and encodes the parameters as JSON.
614
624
  #
615
- # Calling +parsed_body+ on the response parses the response body based on the
625
+ # Calling TestResponse#parsed_body on the response parses the response body based on the
616
626
  # last response MIME type.
617
627
  #
618
628
  # Out of the box, only <tt>:json</tt> is supported. But for any custom MIME
@@ -624,9 +634,9 @@ module ActionDispatch
624
634
  #
625
635
  # Where +param_encoder+ defines how the params should be encoded and
626
636
  # +response_parser+ defines how the response body should be parsed through
627
- # +parsed_body+.
637
+ # TestResponse#parsed_body.
628
638
  #
629
- # Consult the Rails Testing Guide for more.
639
+ # Consult the {Rails Testing Guide}[https://guides.rubyonrails.org/testing.html] for more.
630
640
 
631
641
  class IntegrationTest < ActiveSupport::TestCase
632
642
  include TestProcess::FixtureFile
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "nokogiri"
4
+
3
5
  module ActionDispatch
4
6
  class RequestEncoder # :nodoc:
5
7
  class IdentityEncoder
@@ -50,6 +52,7 @@ module ActionDispatch
50
52
  @encoders[mime_name] = new(mime_name, param_encoder, response_parser)
51
53
  end
52
54
 
53
- register_encoder :json, response_parser: -> body { JSON.parse(body) }
55
+ register_encoder :html, response_parser: -> body { Rails::Dom::Testing.html_document.parse(body) }
56
+ register_encoder :json, response_parser: -> body { JSON.parse(body, object_class: ActiveSupport::HashWithIndifferentAccess) }
54
57
  end
55
58
  end
@@ -8,21 +8,22 @@ 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('david.png', 'image/png') }
11
+ # post :change_avatar, params: { avatar: file_fixture_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('david.png', 'image/png', :binary) }
19
- def fixture_file_upload(path, mime_type = nil, binary = false)
18
+ # post :change_avatar, params: { avatar: file_fixture_upload('david.png', 'image/png', :binary) }
19
+ def file_fixture_upload(path, mime_type = nil, binary = false)
20
20
  if self.class.file_fixture_path && !File.exist?(path)
21
21
  path = file_fixture(path)
22
22
  end
23
23
 
24
24
  Rack::Test::UploadedFile.new(path, mime_type, binary)
25
25
  end
26
+ alias_method :fixture_file_upload, :file_fixture_upload
26
27
  end
27
28
 
28
29
  include FixtureFile
@@ -32,7 +32,7 @@ module ActionDispatch
32
32
  end
33
33
 
34
34
  def port=(number)
35
- set_header("SERVER_PORT", number.to_i)
35
+ set_header("SERVER_PORT", number)
36
36
  end
37
37
 
38
38
  def request_uri=(uri)
@@ -19,19 +19,33 @@ module ActionDispatch
19
19
  #
20
20
  # ==== Examples
21
21
  # get "/posts"
22
- # response.content_type # => "text/html; charset=utf-8"
23
- # response.parsed_body.class # => String
24
- # response.parsed_body # => "<!DOCTYPE html>\n<html>\n..."
22
+ # response.content_type # => "text/html; charset=utf-8"
23
+ # response.parsed_body.class # => Nokogiri::HTML5::Document
24
+ # response.parsed_body.to_html # => "<!DOCTYPE html>\n<html>\n..."
25
+ #
26
+ # assert_pattern { response.parsed_body.at("main") => { content: "Hello, world" } }
27
+ #
28
+ # response.parsed_body.at("main") => {name:, content:}
29
+ # assert_equal "main", name
30
+ # assert_equal "Some main content", content
25
31
  #
26
32
  # get "/posts.json"
27
- # response.content_type # => "application/json; charset=utf-8"
28
- # response.parsed_body.class # => Array
29
- # response.parsed_body # => [{"id"=>42, "title"=>"Title"},...
33
+ # response.content_type # => "application/json; charset=utf-8"
34
+ # response.parsed_body.class # => Array
35
+ # response.parsed_body # => [{"id"=>42, "title"=>"Title"},...
36
+ #
37
+ # assert_pattern { response.parsed_body => [{ id: 42 }] }
30
38
  #
31
39
  # get "/posts/42.json"
32
- # response.content_type # => "application/json; charset=utf-8"
33
- # response.parsed_body.class # => Hash
34
- # response.parsed_body # => {"id"=>42, "title"=>"Title"}
40
+ # response.content_type # => "application/json; charset=utf-8"
41
+ # response.parsed_body.class # => ActiveSupport::HashWithIndifferentAccess
42
+ # response.parsed_body # => {"id"=>42, "title"=>"Title"}
43
+ #
44
+ # assert_pattern { response.parsed_body => [{ title: /title/i }] }
45
+ #
46
+ # response.parsed_body => {id:, title:}
47
+ # assert_equal 42, id
48
+ # assert_equal "Title", title
35
49
  def parsed_body
36
50
  @parsed_body ||= response_parser.call(body)
37
51
  end
@@ -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) 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
@@ -29,16 +29,29 @@ require "active_support/core_ext/module/attribute_accessors"
29
29
 
30
30
  require "action_pack"
31
31
  require "rack"
32
+ require "action_dispatch/deprecator"
32
33
 
33
- module Rack
34
+ module Rack # :nodoc:
34
35
  autoload :Test, "rack/test"
35
36
  end
36
37
 
38
+ # = Action Dispatch
39
+ #
40
+ # Action Dispatch is a module of Action Pack.
41
+ #
42
+ # Action Dispatch parses information about the web request, handles
43
+ # routing as defined by the user, and does advanced processing related to HTTP
44
+ # such as MIME-type negotiation, decoding parameters in POST, PATCH, or PUT
45
+ # bodies, handling HTTP caching logic, cookies and sessions.
37
46
  module ActionDispatch
47
+ include ActiveSupport::Deprecation::DeprecatedConstantAccessor
38
48
  extend ActiveSupport::Autoload
39
49
 
40
- class IllegalStateError < StandardError
50
+ class DeprecatedIllegalStateError < StandardError
41
51
  end
52
+ deprecate_constant "IllegalStateError", "ActionDispatch::DeprecatedIllegalStateError",
53
+ message: "ActionDispatch::IllegalStateError is deprecated without replacement.",
54
+ deprecator: ActionDispatch.deprecator
42
55
 
43
56
  class MissingController < NameError
44
57
  end
@@ -53,6 +66,7 @@ module ActionDispatch
53
66
  end
54
67
 
55
68
  autoload_under "middleware" do
69
+ autoload :AssumeSSL
56
70
  autoload :HostAuthorization
57
71
  autoload :RequestId
58
72
  autoload :Callbacks
@@ -73,6 +87,7 @@ module ActionDispatch
73
87
  autoload :Static
74
88
  end
75
89
 
90
+ autoload :Constants
76
91
  autoload :Journey
77
92
  autoload :MiddlewareStack, "action_dispatch/middleware/stack"
78
93
  autoload :Routing
@@ -94,6 +109,19 @@ module ActionDispatch
94
109
  autoload :CookieStore, "action_dispatch/middleware/session/cookie_store"
95
110
  autoload :MemCacheStore, "action_dispatch/middleware/session/mem_cache_store"
96
111
  autoload :CacheStore, "action_dispatch/middleware/session/cache_store"
112
+
113
+ def self.resolve_store(session_store) # :nodoc:
114
+ self.const_get(session_store.to_s.camelize)
115
+ rescue NameError
116
+ raise <<~ERROR
117
+ Unable to resolve session store #{session_store.inspect}.
118
+
119
+ #{session_store.inspect} resolves to ActionDispatch::Session::#{session_store.to_s.camelize},
120
+ but that class is undefined.
121
+
122
+ Is #{session_store.inspect} spelled correctly, and are any necessary gems installed?
123
+ ERROR
124
+ end
97
125
  end
98
126
 
99
127
  mattr_accessor :test_app
@@ -109,12 +137,17 @@ module ActionDispatch
109
137
  end
110
138
 
111
139
  autoload :SystemTestCase, "action_dispatch/system_test_case"
140
+
141
+ def eager_load!
142
+ super
143
+ Routing.eager_load!
144
+ end
112
145
  end
113
146
 
114
147
  autoload :Mime, "action_dispatch/http/mime_type"
115
148
 
116
149
  ActiveSupport.on_load(:action_view) do
117
150
  ActionView::Base.default_formats ||= Mime::SET.symbols
118
- ActionView::Template::Types.delegate_to Mime
151
+ ActionView::Template.mime_types_implementation = Mime
119
152
  ActionView::LookupContext::DetailsKey.clear
120
153
  end
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionPack
4
- # Returns the currently loaded version of Action Pack as a <tt>Gem::Version</tt>.
4
+ # Returns the currently loaded version of Action Pack as a +Gem::Version+.
5
5
  def self.gem_version
6
6
  Gem::Version.new VERSION::STRING
7
7
  end
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 7
11
- MINOR = 0
12
- TINY = 8
13
- PRE = nil
11
+ MINOR = 1
12
+ TINY = 3
13
+ PRE = "2"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -3,7 +3,7 @@
3
3
  require_relative "gem_version"
4
4
 
5
5
  module ActionPack
6
- # Returns the currently loaded version of Action Pack as a <tt>Gem::Version</tt>.
6
+ # Returns the currently loaded version of Action Pack as a +Gem::Version+.
7
7
  def self.version
8
8
  gem_version
9
9
  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) 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