actionpack 4.2.10 → 7.2.0.rc1

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 (202) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +86 -600
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +13 -14
  5. data/lib/abstract_controller/asset_paths.rb +5 -1
  6. data/lib/abstract_controller/base.rb +166 -136
  7. data/lib/abstract_controller/caching/fragments.rb +149 -0
  8. data/lib/abstract_controller/caching.rb +68 -0
  9. data/lib/abstract_controller/callbacks.rb +126 -57
  10. data/lib/abstract_controller/collector.rb +13 -15
  11. data/lib/abstract_controller/deprecator.rb +9 -0
  12. data/lib/abstract_controller/error.rb +8 -0
  13. data/lib/abstract_controller/helpers.rb +181 -132
  14. data/lib/abstract_controller/logger.rb +5 -1
  15. data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
  16. data/lib/abstract_controller/rendering.rb +56 -56
  17. data/lib/abstract_controller/translation.rb +29 -15
  18. data/lib/abstract_controller/url_for.rb +15 -11
  19. data/lib/abstract_controller.rb +21 -5
  20. data/lib/action_controller/api/api_rendering.rb +18 -0
  21. data/lib/action_controller/api.rb +154 -0
  22. data/lib/action_controller/base.rb +219 -155
  23. data/lib/action_controller/caching.rb +28 -68
  24. data/lib/action_controller/deprecator.rb +9 -0
  25. data/lib/action_controller/form_builder.rb +55 -0
  26. data/lib/action_controller/log_subscriber.rb +35 -22
  27. data/lib/action_controller/metal/allow_browser.rb +119 -0
  28. data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
  29. data/lib/action_controller/metal/conditional_get.rb +259 -122
  30. data/lib/action_controller/metal/content_security_policy.rb +86 -0
  31. data/lib/action_controller/metal/cookies.rb +9 -5
  32. data/lib/action_controller/metal/data_streaming.rb +87 -104
  33. data/lib/action_controller/metal/default_headers.rb +21 -0
  34. data/lib/action_controller/metal/etag_with_flash.rb +22 -0
  35. data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
  36. data/lib/action_controller/metal/exceptions.rb +71 -24
  37. data/lib/action_controller/metal/flash.rb +26 -19
  38. data/lib/action_controller/metal/head.rb +45 -36
  39. data/lib/action_controller/metal/helpers.rb +80 -64
  40. data/lib/action_controller/metal/http_authentication.rb +297 -244
  41. data/lib/action_controller/metal/implicit_render.rb +57 -9
  42. data/lib/action_controller/metal/instrumentation.rb +76 -64
  43. data/lib/action_controller/metal/live.rb +238 -176
  44. data/lib/action_controller/metal/logging.rb +22 -0
  45. data/lib/action_controller/metal/mime_responds.rb +177 -166
  46. data/lib/action_controller/metal/parameter_encoding.rb +84 -0
  47. data/lib/action_controller/metal/params_wrapper.rb +145 -118
  48. data/lib/action_controller/metal/permissions_policy.rb +38 -0
  49. data/lib/action_controller/metal/rate_limiting.rb +62 -0
  50. data/lib/action_controller/metal/redirecting.rb +203 -64
  51. data/lib/action_controller/metal/renderers.rb +108 -65
  52. data/lib/action_controller/metal/rendering.rb +216 -56
  53. data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
  54. data/lib/action_controller/metal/rescue.rb +19 -21
  55. data/lib/action_controller/metal/streaming.rb +179 -138
  56. data/lib/action_controller/metal/strong_parameters.rb +1058 -382
  57. data/lib/action_controller/metal/testing.rb +11 -17
  58. data/lib/action_controller/metal/url_for.rb +37 -21
  59. data/lib/action_controller/metal.rb +236 -138
  60. data/lib/action_controller/railtie.rb +89 -11
  61. data/lib/action_controller/railties/helpers.rb +5 -1
  62. data/lib/action_controller/renderer.rb +161 -0
  63. data/lib/action_controller/template_assertions.rb +13 -0
  64. data/lib/action_controller/test_case.rb +425 -497
  65. data/lib/action_controller.rb +44 -22
  66. data/lib/action_dispatch/constants.rb +34 -0
  67. data/lib/action_dispatch/deprecator.rb +9 -0
  68. data/lib/action_dispatch/http/cache.rb +119 -63
  69. data/lib/action_dispatch/http/content_disposition.rb +47 -0
  70. data/lib/action_dispatch/http/content_security_policy.rb +364 -0
  71. data/lib/action_dispatch/http/filter_parameters.rb +36 -34
  72. data/lib/action_dispatch/http/filter_redirect.rb +24 -12
  73. data/lib/action_dispatch/http/headers.rb +66 -31
  74. data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
  75. data/lib/action_dispatch/http/mime_type.rb +196 -136
  76. data/lib/action_dispatch/http/mime_types.rb +25 -7
  77. data/lib/action_dispatch/http/parameters.rb +97 -45
  78. data/lib/action_dispatch/http/permissions_policy.rb +187 -0
  79. data/lib/action_dispatch/http/rack_cache.rb +6 -0
  80. data/lib/action_dispatch/http/request.rb +299 -170
  81. data/lib/action_dispatch/http/response.rb +311 -160
  82. data/lib/action_dispatch/http/upload.rb +52 -23
  83. data/lib/action_dispatch/http/url.rb +201 -125
  84. data/lib/action_dispatch/journey/formatter.rb +110 -50
  85. data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
  86. data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
  87. data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
  88. data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
  89. data/lib/action_dispatch/journey/nodes/node.rb +100 -20
  90. data/lib/action_dispatch/journey/parser.rb +19 -17
  91. data/lib/action_dispatch/journey/parser.y +4 -3
  92. data/lib/action_dispatch/journey/parser_extras.rb +14 -4
  93. data/lib/action_dispatch/journey/path/pattern.rb +79 -63
  94. data/lib/action_dispatch/journey/route.rb +108 -44
  95. data/lib/action_dispatch/journey/router/utils.rb +41 -29
  96. data/lib/action_dispatch/journey/router.rb +64 -57
  97. data/lib/action_dispatch/journey/routes.rb +23 -21
  98. data/lib/action_dispatch/journey/scanner.rb +28 -17
  99. data/lib/action_dispatch/journey/visitors.rb +100 -54
  100. data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
  101. data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
  102. data/lib/action_dispatch/journey.rb +7 -5
  103. data/lib/action_dispatch/log_subscriber.rb +25 -0
  104. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  105. data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
  106. data/lib/action_dispatch/middleware/callbacks.rb +7 -6
  107. data/lib/action_dispatch/middleware/cookies.rb +471 -328
  108. data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
  109. data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
  110. data/lib/action_dispatch/middleware/debug_view.rb +73 -0
  111. data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
  112. data/lib/action_dispatch/middleware/executor.rb +32 -0
  113. data/lib/action_dispatch/middleware/flash.rb +143 -101
  114. data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
  115. data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
  116. data/lib/action_dispatch/middleware/reloader.rb +10 -92
  117. data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
  118. data/lib/action_dispatch/middleware/request_id.rb +29 -15
  119. data/lib/action_dispatch/middleware/server_timing.rb +78 -0
  120. data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
  121. data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
  122. data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
  123. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
  124. data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
  125. data/lib/action_dispatch/middleware/ssl.rb +134 -36
  126. data/lib/action_dispatch/middleware/stack.rb +109 -44
  127. data/lib/action_dispatch/middleware/static.rb +159 -90
  128. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  129. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  130. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
  132. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  133. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
  136. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
  137. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
  138. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
  139. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
  140. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  141. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
  142. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
  143. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
  144. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  145. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
  146. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
  147. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
  148. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  149. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
  150. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
  151. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
  152. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
  153. data/lib/action_dispatch/railtie.rb +44 -16
  154. data/lib/action_dispatch/request/session.rb +159 -69
  155. data/lib/action_dispatch/request/utils.rb +97 -23
  156. data/lib/action_dispatch/routing/endpoint.rb +11 -2
  157. data/lib/action_dispatch/routing/inspector.rb +195 -106
  158. data/lib/action_dispatch/routing/mapper.rb +1338 -955
  159. data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
  160. data/lib/action_dispatch/routing/redirection.rb +78 -51
  161. data/lib/action_dispatch/routing/route_set.rb +460 -374
  162. data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
  163. data/lib/action_dispatch/routing/url_for.rb +172 -124
  164. data/lib/action_dispatch/routing.rb +159 -158
  165. data/lib/action_dispatch/system_test_case.rb +206 -0
  166. data/lib/action_dispatch/system_testing/browser.rb +84 -0
  167. data/lib/action_dispatch/system_testing/driver.rb +85 -0
  168. data/lib/action_dispatch/system_testing/server.rb +33 -0
  169. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
  170. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
  171. data/lib/action_dispatch/testing/assertion_response.rb +48 -0
  172. data/lib/action_dispatch/testing/assertions/response.rb +71 -39
  173. data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
  174. data/lib/action_dispatch/testing/assertions.rb +9 -6
  175. data/lib/action_dispatch/testing/integration.rb +486 -306
  176. data/lib/action_dispatch/testing/request_encoder.rb +60 -0
  177. data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
  178. data/lib/action_dispatch/testing/test_process.rb +35 -22
  179. data/lib/action_dispatch/testing/test_request.rb +29 -34
  180. data/lib/action_dispatch/testing/test_response.rb +48 -15
  181. data/lib/action_dispatch.rb +82 -40
  182. data/lib/action_pack/gem_version.rb +8 -4
  183. data/lib/action_pack/version.rb +6 -2
  184. data/lib/action_pack.rb +21 -18
  185. metadata +146 -56
  186. data/lib/action_controller/caching/fragments.rb +0 -103
  187. data/lib/action_controller/metal/force_ssl.rb +0 -97
  188. data/lib/action_controller/metal/hide_actions.rb +0 -40
  189. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  190. data/lib/action_controller/middleware.rb +0 -39
  191. data/lib/action_controller/model_naming.rb +0 -12
  192. data/lib/action_dispatch/http/parameter_filter.rb +0 -72
  193. data/lib/action_dispatch/journey/backwards.rb +0 -5
  194. data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
  195. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
  196. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
  197. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  198. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  199. data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
  200. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  201. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  202. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,43 +1,167 @@
1
- require 'uri'
2
- require 'active_support/core_ext/hash/indifferent_access'
3
- require 'active_support/core_ext/string/access'
4
- require 'action_controller/metal/exceptions'
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ require "uri"
6
+ require "active_support/core_ext/hash/indifferent_access"
7
+ require "active_support/core_ext/string/access"
8
+ require "action_controller/metal/exceptions"
5
9
 
6
10
  module ActionDispatch
7
11
  module Assertions
8
- # Suite of assertions to test routes generated by \Rails and the handling of requests made to them.
12
+ # Suite of assertions to test routes generated by Rails and the handling of
13
+ # requests made to them.
9
14
  module RoutingAssertions
10
- # Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash)
11
- # match +path+. Basically, it asserts that \Rails recognizes the route given by +expected_options+.
15
+ extend ActiveSupport::Concern
16
+
17
+ module WithIntegrationRouting # :nodoc:
18
+ extend ActiveSupport::Concern
19
+
20
+ module ClassMethods
21
+ def with_routing(&block)
22
+ old_routes = nil
23
+ old_integration_session = nil
24
+
25
+ setup do
26
+ old_routes = app.routes
27
+ old_integration_session = integration_session
28
+ create_routes(&block)
29
+ end
30
+
31
+ teardown do
32
+ reset_routes(old_routes, old_integration_session)
33
+ end
34
+ end
35
+ end
36
+
37
+ def with_routing(&block)
38
+ old_routes = app.routes
39
+ old_integration_session = integration_session
40
+ create_routes(&block)
41
+ ensure
42
+ reset_routes(old_routes, old_integration_session)
43
+ end
44
+
45
+ private
46
+ def create_routes
47
+ app = self.app
48
+ routes = ActionDispatch::Routing::RouteSet.new
49
+ rack_app = app.config.middleware.build(routes)
50
+ https = integration_session.https?
51
+ host = integration_session.host
52
+
53
+ app.instance_variable_set(:@routes, routes)
54
+ app.instance_variable_set(:@app, rack_app)
55
+ @integration_session = Class.new(ActionDispatch::Integration::Session) do
56
+ include app.routes.url_helpers
57
+ include app.routes.mounted_helpers
58
+ end.new(app)
59
+ @integration_session.https! https
60
+ @integration_session.host! host
61
+ @routes = routes
62
+
63
+ yield routes
64
+ end
65
+
66
+ def reset_routes(old_routes, old_integration_session)
67
+ old_rack_app = app.config.middleware.build(old_routes)
68
+
69
+ app.instance_variable_set(:@routes, old_routes)
70
+ app.instance_variable_set(:@app, old_rack_app)
71
+ @integration_session = old_integration_session
72
+ @routes = old_routes
73
+ end
74
+ end
75
+
76
+ module ClassMethods
77
+ # A helper to make it easier to test different route configurations. This method
78
+ # temporarily replaces @routes with a new RouteSet instance before each test.
79
+ #
80
+ # The new instance is yielded to the passed block. Typically the block will
81
+ # create some routes using `set.draw { match ... }`:
82
+ #
83
+ # with_routing do |set|
84
+ # set.draw do
85
+ # resources :users
86
+ # end
87
+ # end
88
+ #
89
+ def with_routing(&block)
90
+ old_routes, old_controller = nil
91
+
92
+ setup do
93
+ old_routes, old_controller = @routes, @controller
94
+ create_routes(&block)
95
+ end
96
+
97
+ teardown do
98
+ reset_routes(old_routes, old_controller)
99
+ end
100
+ end
101
+ end
102
+
103
+ def setup # :nodoc:
104
+ @routes ||= nil
105
+ super
106
+ end
107
+
108
+ # A helper to make it easier to test different route configurations. This method
109
+ # temporarily replaces @routes with a new RouteSet instance.
110
+ #
111
+ # The new instance is yielded to the passed block. Typically the block will
112
+ # create some routes using `set.draw { match ... }`:
113
+ #
114
+ # with_routing do |set|
115
+ # set.draw do
116
+ # resources :users
117
+ # end
118
+ # assert_equal "/users", users_path
119
+ # end
120
+ #
121
+ def with_routing(&block)
122
+ old_routes, old_controller = @routes, @controller
123
+ create_routes(&block)
124
+ ensure
125
+ reset_routes(old_routes, old_controller)
126
+ end
127
+
128
+ # Asserts that the routing of the given `path` was handled correctly and that
129
+ # the parsed options (given in the `expected_options` hash) match `path`.
130
+ # Basically, it asserts that Rails recognizes the route given by
131
+ # `expected_options`.
12
132
  #
13
- # Pass a hash in the second argument (+path+) to specify the request method. This is useful for routes
14
- # requiring a specific HTTP method. The hash should contain a :path with the incoming request path
15
- # and a :method containing the required HTTP verb.
133
+ # Pass a hash in the second argument (`path`) to specify the request method.
134
+ # This is useful for routes requiring a specific HTTP method. The hash should
135
+ # contain a `:path` with the incoming request path and a `:method` containing
136
+ # the required HTTP verb.
16
137
  #
17
- # # assert that POSTing to /items will call the create action on ItemsController
18
- # assert_recognizes({controller: 'items', action: 'create'}, {path: 'items', method: :post})
138
+ # # Asserts that POSTing to /items will call the create action on ItemsController
139
+ # assert_recognizes({controller: 'items', action: 'create'}, {path: 'items', method: :post})
19
140
  #
20
- # You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string. This can be used
21
- # to assert that values in the query string string will end up in the params hash correctly. To test query strings you must use the
22
- # extras argument, appending the query string on the path directly will not work. For example:
141
+ # You can also pass in `extras` with a hash containing URL parameters that would
142
+ # normally be in the query string. This can be used to assert that values in the
143
+ # query string will end up in the params hash correctly. To test query strings
144
+ # you must use the extras argument because appending the query string on the
145
+ # path directly will not work. For example:
23
146
  #
24
- # # assert that a path of '/items/list/1?view=print' returns the correct options
25
- # assert_recognizes({controller: 'items', action: 'list', id: '1', view: 'print'}, 'items/list/1', { view: "print" })
147
+ # # Asserts that a path of '/items/list/1?view=print' returns the correct options
148
+ # assert_recognizes({controller: 'items', action: 'list', id: '1', view: 'print'}, 'items/list/1', { view: "print" })
26
149
  #
27
- # The +message+ parameter allows you to pass in an error message that is displayed upon failure.
150
+ # The `message` parameter allows you to pass in an error message that is
151
+ # displayed upon failure.
28
152
  #
29
- # # Check the default route (i.e., the index action)
30
- # assert_recognizes({controller: 'items', action: 'index'}, 'items')
153
+ # # Check the default route (i.e., the index action)
154
+ # assert_recognizes({controller: 'items', action: 'index'}, 'items')
31
155
  #
32
- # # Test a specific action
33
- # assert_recognizes({controller: 'items', action: 'list'}, 'items/list')
156
+ # # Test a specific action
157
+ # assert_recognizes({controller: 'items', action: 'list'}, 'items/list')
34
158
  #
35
- # # Test an action with a parameter
36
- # assert_recognizes({controller: 'items', action: 'destroy', id: '1'}, 'items/destroy/1')
159
+ # # Test an action with a parameter
160
+ # assert_recognizes({controller: 'items', action: 'destroy', id: '1'}, 'items/destroy/1')
37
161
  #
38
- # # Test a custom route
39
- # assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1')
40
- def assert_recognizes(expected_options, path, extras={}, msg=nil)
162
+ # # Test a custom route
163
+ # assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1')
164
+ def assert_recognizes(expected_options, path, extras = {}, msg = nil)
41
165
  if path.is_a?(Hash) && path[:method].to_s == "all"
42
166
  [:get, :post, :put, :delete].each do |method|
43
167
  assert_recognizes(expected_options, path.merge(method: method), extras, msg)
@@ -58,36 +182,38 @@ module ActionDispatch
58
182
  end
59
183
  end
60
184
 
61
- # Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
62
- # The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in
63
- # a query string. The +message+ parameter allows you to specify a custom error message for assertion failures.
185
+ # Asserts that the provided options can be used to generate the provided path.
186
+ # This is the inverse of `assert_recognizes`. The `extras` parameter is used to
187
+ # tell the request the names and values of additional request parameters that
188
+ # would be in a query string. The `message` parameter allows you to specify a
189
+ # custom error message for assertion failures.
64
190
  #
65
- # The +defaults+ parameter is unused.
191
+ # The `defaults` parameter is unused.
66
192
  #
67
- # # Asserts that the default action is generated for a route with no action
68
- # assert_generates "/items", controller: "items", action: "index"
193
+ # # Asserts that the default action is generated for a route with no action
194
+ # assert_generates "/items", controller: "items", action: "index"
69
195
  #
70
- # # Tests that the list action is properly routed
71
- # assert_generates "/items/list", controller: "items", action: "list"
196
+ # # Tests that the list action is properly routed
197
+ # assert_generates "/items/list", controller: "items", action: "list"
72
198
  #
73
- # # Tests the generation of a route with a parameter
74
- # assert_generates "/items/list/1", { controller: "items", action: "list", id: "1" }
199
+ # # Tests the generation of a route with a parameter
200
+ # assert_generates "/items/list/1", { controller: "items", action: "list", id: "1" }
75
201
  #
76
- # # Asserts that the generated route gives us our custom route
77
- # assert_generates "changesets/12", { controller: 'scm', action: 'show_diff', revision: "12" }
78
- def assert_generates(expected_path, options, defaults={}, extras={}, message=nil)
79
- if expected_path =~ %r{://}
202
+ # # Asserts that the generated route gives us our custom route
203
+ # assert_generates "changesets/12", { controller: 'scm', action: 'show_diff', revision: "12" }
204
+ def assert_generates(expected_path, options, defaults = {}, extras = {}, message = nil)
205
+ if expected_path.include?("://")
80
206
  fail_on(URI::InvalidURIError, message) do
81
207
  uri = URI.parse(expected_path)
82
208
  expected_path = uri.path.to_s.empty? ? "/" : uri.path
83
209
  end
84
210
  else
85
- expected_path = "/#{expected_path}" unless expected_path.first == '/'
211
+ expected_path = "/#{expected_path}" unless expected_path.start_with?("/")
86
212
  end
87
- # Load routes.rb if it hasn't been loaded.
88
213
 
89
- generated_path, extra_keys = @routes.generate_extras(options, defaults)
90
- found_extras = options.reject { |k, _| ! extra_keys.include? k }
214
+ options = options.clone
215
+ generated_path, query_string_keys = @routes.generate_extras(options, defaults)
216
+ found_extras = options.reject { |k, _| ! query_string_keys.include? k }
91
217
 
92
218
  msg = message || sprintf("found extras <%s>, not <%s>", found_extras, extras)
93
219
  assert_equal(extras, found_extras, msg)
@@ -97,28 +223,29 @@ module ActionDispatch
97
223
  assert_equal(expected_path, generated_path, msg)
98
224
  end
99
225
 
100
- # Asserts that path and options match both ways; in other words, it verifies that <tt>path</tt> generates
101
- # <tt>options</tt> and then that <tt>options</tt> generates <tt>path</tt>. This essentially combines +assert_recognizes+
102
- # and +assert_generates+ into one step.
226
+ # Asserts that path and options match both ways; in other words, it verifies
227
+ # that `path` generates `options` and then that `options` generates `path`. This
228
+ # essentially combines `assert_recognizes` and `assert_generates` into one step.
103
229
  #
104
- # The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The
105
- # +message+ parameter allows you to specify a custom error message to display upon failure.
230
+ # The `extras` hash allows you to specify options that would normally be
231
+ # provided as a query string to the action. The `message` parameter allows you
232
+ # to specify a custom error message to display upon failure.
106
233
  #
107
- # # Assert a basic route: a controller with the default action (index)
108
- # assert_routing '/home', controller: 'home', action: 'index'
234
+ # # Asserts a basic route: a controller with the default action (index)
235
+ # assert_routing '/home', controller: 'home', action: 'index'
109
236
  #
110
- # # Test a route generated with a specific controller, action, and parameter (id)
111
- # assert_routing '/entries/show/23', controller: 'entries', action: 'show', id: 23
237
+ # # Test a route generated with a specific controller, action, and parameter (id)
238
+ # assert_routing '/entries/show/23', controller: 'entries', action: 'show', id: 23
112
239
  #
113
- # # Assert a basic route (controller + default action), with an error message if it fails
114
- # assert_routing '/store', { controller: 'store', action: 'index' }, {}, {}, 'Route for store index not generated properly'
240
+ # # Asserts a basic route (controller + default action), with an error message if it fails
241
+ # assert_routing '/store', { controller: 'store', action: 'index' }, {}, {}, 'Route for store index not generated properly'
115
242
  #
116
- # # Tests a route, providing a defaults hash
117
- # assert_routing 'controller/action/9', {id: "9", item: "square"}, {controller: "controller", action: "action"}, {}, {item: "square"}
243
+ # # Tests a route, providing a defaults hash
244
+ # assert_routing 'controller/action/9', {id: "9", item: "square"}, {controller: "controller", action: "action"}, {}, {item: "square"}
118
245
  #
119
- # # Tests a route with a HTTP method
120
- # assert_routing({ method: 'put', path: '/product/321' }, { controller: "product", action: "update", id: "321" })
121
- def assert_routing(path, options, defaults={}, extras={}, message=nil)
246
+ # # Tests a route with an HTTP method
247
+ # assert_routing({ method: 'put', path: '/product/321' }, { controller: "product", action: "update", id: "321" })
248
+ def assert_routing(path, options, defaults = {}, extras = {}, message = nil)
122
249
  assert_recognizes(options, path, extras, message)
123
250
 
124
251
  controller, default_controller = options[:controller], defaults[:controller]
@@ -126,53 +253,51 @@ module ActionDispatch
126
253
  options[:controller] = "/#{controller}"
127
254
  end
128
255
 
129
- generate_options = options.dup.delete_if{ |k, _| defaults.key?(k) }
256
+ generate_options = options.dup.delete_if { |k, _| defaults.key?(k) }
130
257
  assert_generates(path.is_a?(Hash) ? path[:path] : path, generate_options, defaults, extras, message)
131
258
  end
132
259
 
133
- # A helper to make it easier to test different route configurations.
134
- # This method temporarily replaces @routes
135
- # with a new RouteSet instance.
136
- #
137
- # The new instance is yielded to the passed block. Typically the block
138
- # will create some routes using <tt>set.draw { match ... }</tt>:
139
- #
140
- # with_routing do |set|
141
- # set.draw do
142
- # resources :users
143
- # end
144
- # assert_equal "/users", users_path
145
- # end
146
- #
147
- def with_routing
148
- old_routes, @routes = @routes, ActionDispatch::Routing::RouteSet.new
149
- if defined?(@controller) && @controller
150
- old_controller, @controller = @controller, @controller.clone
151
- _routes = @routes
152
-
153
- @controller.singleton_class.send(:include, _routes.url_helpers)
154
- @controller.view_context_class = Class.new(@controller.view_context_class) do
155
- include _routes.url_helpers
156
- end
157
- end
158
- yield @routes
159
- ensure
160
- @routes = old_routes
161
- if defined?(@controller) && @controller
162
- @controller = old_controller
163
- end
164
- end
165
-
166
260
  # ROUTES TODO: These assertions should really work in an integration context
167
- def method_missing(selector, *args, &block)
168
- if defined?(@controller) && @controller && defined?(@routes) && @routes && @routes.named_routes.route_defined?(selector)
169
- @controller.send(selector, *args, &block)
261
+ def method_missing(selector, ...)
262
+ if @controller && @routes&.named_routes&.route_defined?(selector)
263
+ @controller.public_send(selector, ...)
170
264
  else
171
265
  super
172
266
  end
173
267
  end
174
268
 
175
269
  private
270
+ def create_routes
271
+ @routes = ActionDispatch::Routing::RouteSet.new
272
+ if @controller
273
+ @controller = @controller.clone
274
+ _routes = @routes
275
+
276
+ @controller.singleton_class.include(_routes.url_helpers)
277
+
278
+ if @controller.respond_to? :view_context_class
279
+ view_context_class = Class.new(@controller.view_context_class) do
280
+ include _routes.url_helpers
281
+ end
282
+
283
+ custom_view_context = Module.new {
284
+ define_method(:view_context_class) do
285
+ view_context_class
286
+ end
287
+ }
288
+ @controller.extend(custom_view_context)
289
+ end
290
+ end
291
+ yield @routes
292
+ end
293
+
294
+ def reset_routes(old_routes, old_controller)
295
+ @routes = old_routes
296
+ if @controller
297
+ @controller = old_controller
298
+ end
299
+ end
300
+
176
301
  # Recognizes the route for a given path.
177
302
  def recognized_request_for(path, extras = {}, msg)
178
303
  if path.is_a?(Hash)
@@ -182,10 +307,10 @@ module ActionDispatch
182
307
  method = :get
183
308
  end
184
309
 
185
- # Assume given controller
186
- request = ActionController::TestRequest.new
310
+ controller = @controller if defined?(@controller)
311
+ request = ActionController::TestRequest.create controller&.class
187
312
 
188
- if path =~ %r{://}
313
+ if path.include?("://")
189
314
  fail_on(URI::InvalidURIError, msg) do
190
315
  uri = URI.parse(path)
191
316
  request.env["rack.url_scheme"] = uri.scheme || "http"
@@ -194,14 +319,14 @@ module ActionDispatch
194
319
  request.path = uri.path.to_s.empty? ? "/" : uri.path
195
320
  end
196
321
  else
197
- path = "/#{path}" unless path.first == "/"
322
+ path = "/#{path}" unless path.start_with?("/")
198
323
  request.path = path
199
324
  end
200
325
 
201
326
  request.request_method = method if method
202
327
 
203
328
  params = fail_on(ActionController::RoutingError, msg) do
204
- @routes.recognize_path(path, { :method => method, :extras => extras })
329
+ @routes.recognize_path(path, method: method, extras: extras)
205
330
  end
206
331
  request.path_parameters = params.with_indifferent_access
207
332
 
@@ -1,10 +1,13 @@
1
- require 'rails-dom-testing'
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ require "rails-dom-testing"
6
+ require "action_dispatch/testing/assertions/response"
7
+ require "action_dispatch/testing/assertions/routing"
2
8
 
3
9
  module ActionDispatch
4
10
  module Assertions
5
- autoload :ResponseAssertions, 'action_dispatch/testing/assertions/response'
6
- autoload :RoutingAssertions, 'action_dispatch/testing/assertions/routing'
7
-
8
11
  extend ActiveSupport::Concern
9
12
 
10
13
  include ResponseAssertions
@@ -12,10 +15,10 @@ module ActionDispatch
12
15
  include Rails::Dom::Testing::Assertions
13
16
 
14
17
  def html_document
15
- @html_document ||= if @response.content_type.to_s =~ /xml$/
18
+ @html_document ||= if @response.media_type&.end_with?("xml")
16
19
  Nokogiri::XML::Document.parse(@response.body)
17
20
  else
18
- Nokogiri::HTML::Document.parse(@response.body)
21
+ Rails::Dom::Testing.html_document.parse(@response.body)
19
22
  end
20
23
  end
21
24
  end