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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +86 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +13 -14
- data/lib/abstract_controller/asset_paths.rb +5 -1
- data/lib/abstract_controller/base.rb +166 -136
- data/lib/abstract_controller/caching/fragments.rb +149 -0
- data/lib/abstract_controller/caching.rb +68 -0
- data/lib/abstract_controller/callbacks.rb +126 -57
- data/lib/abstract_controller/collector.rb +13 -15
- data/lib/abstract_controller/deprecator.rb +9 -0
- data/lib/abstract_controller/error.rb +8 -0
- data/lib/abstract_controller/helpers.rb +181 -132
- data/lib/abstract_controller/logger.rb +5 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
- data/lib/abstract_controller/rendering.rb +56 -56
- data/lib/abstract_controller/translation.rb +29 -15
- data/lib/abstract_controller/url_for.rb +15 -11
- data/lib/abstract_controller.rb +21 -5
- data/lib/action_controller/api/api_rendering.rb +18 -0
- data/lib/action_controller/api.rb +154 -0
- data/lib/action_controller/base.rb +219 -155
- data/lib/action_controller/caching.rb +28 -68
- data/lib/action_controller/deprecator.rb +9 -0
- data/lib/action_controller/form_builder.rb +55 -0
- data/lib/action_controller/log_subscriber.rb +35 -22
- data/lib/action_controller/metal/allow_browser.rb +119 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
- data/lib/action_controller/metal/conditional_get.rb +259 -122
- data/lib/action_controller/metal/content_security_policy.rb +86 -0
- data/lib/action_controller/metal/cookies.rb +9 -5
- data/lib/action_controller/metal/data_streaming.rb +87 -104
- data/lib/action_controller/metal/default_headers.rb +21 -0
- data/lib/action_controller/metal/etag_with_flash.rb +22 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
- data/lib/action_controller/metal/exceptions.rb +71 -24
- data/lib/action_controller/metal/flash.rb +26 -19
- data/lib/action_controller/metal/head.rb +45 -36
- data/lib/action_controller/metal/helpers.rb +80 -64
- data/lib/action_controller/metal/http_authentication.rb +297 -244
- data/lib/action_controller/metal/implicit_render.rb +57 -9
- data/lib/action_controller/metal/instrumentation.rb +76 -64
- data/lib/action_controller/metal/live.rb +238 -176
- data/lib/action_controller/metal/logging.rb +22 -0
- data/lib/action_controller/metal/mime_responds.rb +177 -166
- data/lib/action_controller/metal/parameter_encoding.rb +84 -0
- data/lib/action_controller/metal/params_wrapper.rb +145 -118
- data/lib/action_controller/metal/permissions_policy.rb +38 -0
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +203 -64
- data/lib/action_controller/metal/renderers.rb +108 -65
- data/lib/action_controller/metal/rendering.rb +216 -56
- data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
- data/lib/action_controller/metal/rescue.rb +19 -21
- data/lib/action_controller/metal/streaming.rb +179 -138
- data/lib/action_controller/metal/strong_parameters.rb +1058 -382
- data/lib/action_controller/metal/testing.rb +11 -17
- data/lib/action_controller/metal/url_for.rb +37 -21
- data/lib/action_controller/metal.rb +236 -138
- data/lib/action_controller/railtie.rb +89 -11
- data/lib/action_controller/railties/helpers.rb +5 -1
- data/lib/action_controller/renderer.rb +161 -0
- data/lib/action_controller/template_assertions.rb +13 -0
- data/lib/action_controller/test_case.rb +425 -497
- data/lib/action_controller.rb +44 -22
- data/lib/action_dispatch/constants.rb +34 -0
- data/lib/action_dispatch/deprecator.rb +9 -0
- data/lib/action_dispatch/http/cache.rb +119 -63
- data/lib/action_dispatch/http/content_disposition.rb +47 -0
- data/lib/action_dispatch/http/content_security_policy.rb +364 -0
- data/lib/action_dispatch/http/filter_parameters.rb +36 -34
- data/lib/action_dispatch/http/filter_redirect.rb +24 -12
- data/lib/action_dispatch/http/headers.rb +66 -31
- data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
- data/lib/action_dispatch/http/mime_type.rb +196 -136
- data/lib/action_dispatch/http/mime_types.rb +25 -7
- data/lib/action_dispatch/http/parameters.rb +97 -45
- data/lib/action_dispatch/http/permissions_policy.rb +187 -0
- data/lib/action_dispatch/http/rack_cache.rb +6 -0
- data/lib/action_dispatch/http/request.rb +299 -170
- data/lib/action_dispatch/http/response.rb +311 -160
- data/lib/action_dispatch/http/upload.rb +52 -23
- data/lib/action_dispatch/http/url.rb +201 -125
- data/lib/action_dispatch/journey/formatter.rb +110 -50
- data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
- data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
- data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
- data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
- data/lib/action_dispatch/journey/nodes/node.rb +100 -20
- data/lib/action_dispatch/journey/parser.rb +19 -17
- data/lib/action_dispatch/journey/parser.y +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +14 -4
- data/lib/action_dispatch/journey/path/pattern.rb +79 -63
- data/lib/action_dispatch/journey/route.rb +108 -44
- data/lib/action_dispatch/journey/router/utils.rb +41 -29
- data/lib/action_dispatch/journey/router.rb +64 -57
- data/lib/action_dispatch/journey/routes.rb +23 -21
- data/lib/action_dispatch/journey/scanner.rb +28 -17
- data/lib/action_dispatch/journey/visitors.rb +100 -54
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/log_subscriber.rb +25 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
- data/lib/action_dispatch/middleware/callbacks.rb +7 -6
- data/lib/action_dispatch/middleware/cookies.rb +471 -328
- data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
- data/lib/action_dispatch/middleware/debug_view.rb +73 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
- data/lib/action_dispatch/middleware/executor.rb +32 -0
- data/lib/action_dispatch/middleware/flash.rb +143 -101
- data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
- data/lib/action_dispatch/middleware/reloader.rb +10 -92
- data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
- data/lib/action_dispatch/middleware/request_id.rb +29 -15
- data/lib/action_dispatch/middleware/server_timing.rb +78 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
- data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
- data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
- data/lib/action_dispatch/middleware/ssl.rb +134 -36
- data/lib/action_dispatch/middleware/stack.rb +109 -44
- data/lib/action_dispatch/middleware/static.rb +159 -90
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
- data/lib/action_dispatch/railtie.rb +44 -16
- data/lib/action_dispatch/request/session.rb +159 -69
- data/lib/action_dispatch/request/utils.rb +97 -23
- data/lib/action_dispatch/routing/endpoint.rb +11 -2
- data/lib/action_dispatch/routing/inspector.rb +195 -106
- data/lib/action_dispatch/routing/mapper.rb +1338 -955
- data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
- data/lib/action_dispatch/routing/redirection.rb +78 -51
- data/lib/action_dispatch/routing/route_set.rb +460 -374
- data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
- data/lib/action_dispatch/routing/url_for.rb +172 -124
- data/lib/action_dispatch/routing.rb +159 -158
- data/lib/action_dispatch/system_test_case.rb +206 -0
- data/lib/action_dispatch/system_testing/browser.rb +84 -0
- data/lib/action_dispatch/system_testing/driver.rb +85 -0
- data/lib/action_dispatch/system_testing/server.rb +33 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
- data/lib/action_dispatch/testing/assertion_response.rb +48 -0
- data/lib/action_dispatch/testing/assertions/response.rb +71 -39
- data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
- data/lib/action_dispatch/testing/assertions.rb +9 -6
- data/lib/action_dispatch/testing/integration.rb +486 -306
- data/lib/action_dispatch/testing/request_encoder.rb +60 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +35 -22
- data/lib/action_dispatch/testing/test_request.rb +29 -34
- data/lib/action_dispatch/testing/test_response.rb +48 -15
- data/lib/action_dispatch.rb +82 -40
- data/lib/action_pack/gem_version.rb +8 -4
- data/lib/action_pack/version.rb +6 -2
- data/lib/action_pack.rb +21 -18
- metadata +146 -56
- data/lib/action_controller/caching/fragments.rb +0 -103
- data/lib/action_controller/metal/force_ssl.rb +0 -97
- data/lib/action_controller/metal/hide_actions.rb +0 -40
- data/lib/action_controller/metal/rack_delegation.rb +0 -32
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/model_naming.rb +0 -12
- data/lib/action_dispatch/http/parameter_filter.rb +0 -72
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,43 +1,167 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
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
|
12
|
+
# Suite of assertions to test routes generated by Rails and the handling of
|
13
|
+
# requests made to them.
|
9
14
|
module RoutingAssertions
|
10
|
-
|
11
|
-
|
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 (
|
14
|
-
# requiring a specific HTTP method. The hash should
|
15
|
-
#
|
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
|
-
#
|
18
|
-
#
|
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
|
21
|
-
#
|
22
|
-
#
|
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
|
-
#
|
25
|
-
#
|
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
|
150
|
+
# The `message` parameter allows you to pass in an error message that is
|
151
|
+
# displayed upon failure.
|
28
152
|
#
|
29
|
-
#
|
30
|
-
#
|
153
|
+
# # Check the default route (i.e., the index action)
|
154
|
+
# assert_recognizes({controller: 'items', action: 'index'}, 'items')
|
31
155
|
#
|
32
|
-
#
|
33
|
-
#
|
156
|
+
# # Test a specific action
|
157
|
+
# assert_recognizes({controller: 'items', action: 'list'}, 'items/list')
|
34
158
|
#
|
35
|
-
#
|
36
|
-
#
|
159
|
+
# # Test an action with a parameter
|
160
|
+
# assert_recognizes({controller: 'items', action: 'destroy', id: '1'}, 'items/destroy/1')
|
37
161
|
#
|
38
|
-
#
|
39
|
-
#
|
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.
|
62
|
-
#
|
63
|
-
#
|
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
|
191
|
+
# The `defaults` parameter is unused.
|
66
192
|
#
|
67
|
-
#
|
68
|
-
#
|
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
|
-
#
|
71
|
-
#
|
196
|
+
# # Tests that the list action is properly routed
|
197
|
+
# assert_generates "/items/list", controller: "items", action: "list"
|
72
198
|
#
|
73
|
-
#
|
74
|
-
#
|
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
|
-
#
|
77
|
-
#
|
78
|
-
def assert_generates(expected_path, options, defaults={}, extras={}, message=nil)
|
79
|
-
if expected_path
|
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.
|
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
|
-
|
90
|
-
|
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
|
101
|
-
#
|
102
|
-
# and
|
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
|
105
|
-
#
|
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
|
-
#
|
108
|
-
#
|
234
|
+
# # Asserts a basic route: a controller with the default action (index)
|
235
|
+
# assert_routing '/home', controller: 'home', action: 'index'
|
109
236
|
#
|
110
|
-
#
|
111
|
-
#
|
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
|
-
#
|
114
|
-
#
|
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
|
-
#
|
117
|
-
#
|
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
|
-
#
|
120
|
-
#
|
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,
|
168
|
-
if
|
169
|
-
@controller.
|
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
|
-
|
186
|
-
request = ActionController::TestRequest.
|
310
|
+
controller = @controller if defined?(@controller)
|
311
|
+
request = ActionController::TestRequest.create controller&.class
|
187
312
|
|
188
|
-
if path
|
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.
|
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,
|
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
|
-
|
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.
|
18
|
+
@html_document ||= if @response.media_type&.end_with?("xml")
|
16
19
|
Nokogiri::XML::Document.parse(@response.body)
|
17
20
|
else
|
18
|
-
|
21
|
+
Rails::Dom::Testing.html_document.parse(@response.body)
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|