actionpack 7.0.5 → 7.1.3.4

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 (138) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +368 -315
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  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 +68 -22
  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 +9 -6
  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 +24 -7
  37. data/lib/action_controller/metal/renderers.rb +4 -4
  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 +6 -3
  41. data/lib/action_controller/metal/streaming.rb +70 -30
  42. data/lib/action_controller/metal/strong_parameters.rb +158 -101
  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 +38 -23
  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 +18 -8
  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 +25 -18
  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/blocked_host.html.erb +7 -3
  98. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -3
  99. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +7 -7
  100. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +2 -2
  101. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +17 -0
  102. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +16 -12
  103. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +1 -1
  104. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +3 -3
  105. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +4 -4
  106. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  107. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  108. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +3 -0
  109. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +46 -37
  110. data/lib/action_dispatch/railtie.rb +14 -4
  111. data/lib/action_dispatch/request/session.rb +16 -6
  112. data/lib/action_dispatch/request/utils.rb +8 -3
  113. data/lib/action_dispatch/routing/inspector.rb +54 -6
  114. data/lib/action_dispatch/routing/mapper.rb +35 -24
  115. data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
  116. data/lib/action_dispatch/routing/redirection.rb +15 -6
  117. data/lib/action_dispatch/routing/route_set.rb +52 -22
  118. data/lib/action_dispatch/routing/routes_proxy.rb +10 -15
  119. data/lib/action_dispatch/routing/url_for.rb +5 -1
  120. data/lib/action_dispatch/routing.rb +7 -7
  121. data/lib/action_dispatch/system_test_case.rb +3 -3
  122. data/lib/action_dispatch/system_testing/browser.rb +20 -19
  123. data/lib/action_dispatch/system_testing/driver.rb +13 -21
  124. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +27 -16
  125. data/lib/action_dispatch/testing/assertion_response.rb +1 -1
  126. data/lib/action_dispatch/testing/assertions/response.rb +13 -6
  127. data/lib/action_dispatch/testing/assertions/routing.rb +67 -28
  128. data/lib/action_dispatch/testing/assertions.rb +3 -1
  129. data/lib/action_dispatch/testing/integration.rb +27 -17
  130. data/lib/action_dispatch/testing/request_encoder.rb +4 -1
  131. data/lib/action_dispatch/testing/test_process.rb +4 -3
  132. data/lib/action_dispatch/testing/test_request.rb +1 -1
  133. data/lib/action_dispatch/testing/test_response.rb +23 -9
  134. data/lib/action_dispatch.rb +37 -4
  135. data/lib/action_pack/gem_version.rb +4 -4
  136. data/lib/action_pack/version.rb +1 -1
  137. data/lib/action_pack.rb +1 -1
  138. metadata +67 -31
@@ -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 = 5
13
- PRE = nil
11
+ MINOR = 1
12
+ TINY = 3
13
+ PRE = "4"
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