actionpack 7.1.3.2 → 7.2.0.beta1
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 +4 -4
- data/CHANGELOG.md +70 -530
- data/lib/abstract_controller/asset_paths.rb +2 -0
- data/lib/abstract_controller/base.rb +102 -98
- data/lib/abstract_controller/caching/fragments.rb +50 -53
- data/lib/abstract_controller/caching.rb +2 -0
- data/lib/abstract_controller/callbacks.rb +66 -64
- data/lib/abstract_controller/collector.rb +6 -6
- data/lib/abstract_controller/deprecator.rb +2 -0
- data/lib/abstract_controller/error.rb +2 -0
- data/lib/abstract_controller/helpers.rb +70 -85
- data/lib/abstract_controller/logger.rb +2 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
- data/lib/abstract_controller/rendering.rb +13 -12
- data/lib/abstract_controller/translation.rb +11 -10
- data/lib/abstract_controller/url_for.rb +8 -6
- data/lib/abstract_controller.rb +2 -0
- data/lib/action_controller/api/api_rendering.rb +2 -0
- data/lib/action_controller/api.rb +74 -72
- data/lib/action_controller/base.rb +155 -117
- data/lib/action_controller/caching.rb +15 -12
- data/lib/action_controller/deprecator.rb +2 -0
- data/lib/action_controller/form_builder.rb +20 -17
- data/lib/action_controller/log_subscriber.rb +3 -1
- data/lib/action_controller/metal/allow_browser.rb +119 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
- data/lib/action_controller/metal/conditional_get.rb +188 -174
- data/lib/action_controller/metal/content_security_policy.rb +25 -24
- data/lib/action_controller/metal/cookies.rb +4 -2
- data/lib/action_controller/metal/data_streaming.rb +64 -55
- data/lib/action_controller/metal/default_headers.rb +5 -3
- data/lib/action_controller/metal/etag_with_flash.rb +3 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +17 -15
- data/lib/action_controller/metal/exceptions.rb +11 -9
- data/lib/action_controller/metal/flash.rb +12 -10
- data/lib/action_controller/metal/head.rb +12 -10
- data/lib/action_controller/metal/helpers.rb +63 -55
- data/lib/action_controller/metal/http_authentication.rb +209 -201
- data/lib/action_controller/metal/implicit_render.rb +17 -15
- data/lib/action_controller/metal/instrumentation.rb +15 -12
- data/lib/action_controller/metal/live.rb +113 -107
- data/lib/action_controller/metal/logging.rb +6 -4
- data/lib/action_controller/metal/mime_responds.rb +151 -142
- data/lib/action_controller/metal/parameter_encoding.rb +34 -32
- data/lib/action_controller/metal/params_wrapper.rb +57 -59
- data/lib/action_controller/metal/permissions_policy.rb +13 -12
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +108 -82
- data/lib/action_controller/metal/renderers.rb +50 -49
- data/lib/action_controller/metal/rendering.rb +103 -75
- data/lib/action_controller/metal/request_forgery_protection.rb +162 -133
- data/lib/action_controller/metal/rescue.rb +11 -9
- data/lib/action_controller/metal/streaming.rb +138 -136
- data/lib/action_controller/metal/strong_parameters.rb +525 -480
- data/lib/action_controller/metal/testing.rb +2 -0
- data/lib/action_controller/metal/url_for.rb +17 -15
- data/lib/action_controller/metal.rb +58 -57
- data/lib/action_controller/railtie.rb +3 -0
- data/lib/action_controller/railties/helpers.rb +2 -0
- data/lib/action_controller/renderer.rb +42 -36
- data/lib/action_controller/template_assertions.rb +4 -2
- data/lib/action_controller/test_case.rb +146 -126
- data/lib/action_controller.rb +10 -3
- data/lib/action_dispatch/constants.rb +2 -0
- data/lib/action_dispatch/deprecator.rb +2 -0
- data/lib/action_dispatch/http/cache.rb +27 -26
- data/lib/action_dispatch/http/content_disposition.rb +2 -0
- data/lib/action_dispatch/http/content_security_policy.rb +44 -38
- data/lib/action_dispatch/http/filter_parameters.rb +9 -5
- data/lib/action_dispatch/http/filter_redirect.rb +15 -1
- data/lib/action_dispatch/http/headers.rb +22 -22
- data/lib/action_dispatch/http/mime_negotiation.rb +30 -41
- data/lib/action_dispatch/http/mime_type.rb +29 -22
- data/lib/action_dispatch/http/mime_types.rb +2 -0
- data/lib/action_dispatch/http/parameters.rb +11 -9
- data/lib/action_dispatch/http/permissions_policy.rb +20 -37
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +71 -71
- data/lib/action_dispatch/http/response.rb +61 -61
- data/lib/action_dispatch/http/upload.rb +18 -16
- data/lib/action_dispatch/http/url.rb +75 -73
- data/lib/action_dispatch/journey/formatter.rb +13 -6
- data/lib/action_dispatch/journey/gtg/builder.rb +4 -3
- data/lib/action_dispatch/journey/gtg/simulator.rb +2 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +10 -8
- data/lib/action_dispatch/journey/nfa/dot.rb +2 -0
- data/lib/action_dispatch/journey/nodes/node.rb +6 -5
- data/lib/action_dispatch/journey/parser.rb +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +2 -0
- data/lib/action_dispatch/journey/path/pattern.rb +4 -1
- data/lib/action_dispatch/journey/route.rb +9 -7
- data/lib/action_dispatch/journey/router/utils.rb +16 -15
- data/lib/action_dispatch/journey/router.rb +4 -2
- data/lib/action_dispatch/journey/routes.rb +4 -2
- data/lib/action_dispatch/journey/scanner.rb +4 -2
- data/lib/action_dispatch/journey/visitors.rb +2 -0
- data/lib/action_dispatch/journey.rb +2 -0
- data/lib/action_dispatch/log_subscriber.rb +2 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +2 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +8 -5
- data/lib/action_dispatch/middleware/callbacks.rb +3 -1
- data/lib/action_dispatch/middleware/cookies.rb +119 -104
- data/lib/action_dispatch/middleware/debug_exceptions.rb +13 -5
- data/lib/action_dispatch/middleware/debug_locks.rb +15 -13
- data/lib/action_dispatch/middleware/debug_view.rb +2 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +6 -11
- data/lib/action_dispatch/middleware/executor.rb +8 -0
- data/lib/action_dispatch/middleware/flash.rb +63 -51
- data/lib/action_dispatch/middleware/host_authorization.rb +17 -15
- data/lib/action_dispatch/middleware/public_exceptions.rb +8 -6
- data/lib/action_dispatch/middleware/reloader.rb +5 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +77 -72
- data/lib/action_dispatch/middleware/request_id.rb +14 -9
- data/lib/action_dispatch/middleware/server_timing.rb +4 -2
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +13 -8
- data/lib/action_dispatch/middleware/session/cookie_store.rb +27 -26
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +31 -21
- data/lib/action_dispatch/middleware/ssl.rb +43 -40
- data/lib/action_dispatch/middleware/stack.rb +11 -10
- data/lib/action_dispatch/middleware/static.rb +33 -31
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +1 -1
- data/lib/action_dispatch/railtie.rb +2 -4
- data/lib/action_dispatch/request/session.rb +23 -21
- data/lib/action_dispatch/request/utils.rb +2 -0
- data/lib/action_dispatch/routing/endpoint.rb +2 -0
- data/lib/action_dispatch/routing/inspector.rb +5 -3
- data/lib/action_dispatch/routing/mapper.rb +670 -635
- data/lib/action_dispatch/routing/polymorphic_routes.rb +69 -62
- data/lib/action_dispatch/routing/redirection.rb +37 -32
- data/lib/action_dispatch/routing/route_set.rb +59 -45
- data/lib/action_dispatch/routing/routes_proxy.rb +6 -4
- data/lib/action_dispatch/routing/url_for.rb +130 -125
- data/lib/action_dispatch/routing.rb +150 -148
- data/lib/action_dispatch/system_test_case.rb +91 -81
- data/lib/action_dispatch/system_testing/browser.rb +10 -3
- data/lib/action_dispatch/system_testing/driver.rb +3 -1
- data/lib/action_dispatch/system_testing/server.rb +2 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +32 -21
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +2 -0
- data/lib/action_dispatch/testing/assertion_response.rb +8 -6
- data/lib/action_dispatch/testing/assertions/response.rb +26 -23
- data/lib/action_dispatch/testing/assertions/routing.rb +153 -84
- data/lib/action_dispatch/testing/assertions.rb +2 -0
- data/lib/action_dispatch/testing/integration.rb +223 -222
- data/lib/action_dispatch/testing/request_encoder.rb +2 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +12 -8
- data/lib/action_dispatch/testing/test_request.rb +3 -1
- data/lib/action_dispatch/testing/test_response.rb +27 -26
- data/lib/action_dispatch.rb +22 -28
- data/lib/action_pack/gem_version.rb +6 -4
- data/lib/action_pack/version.rb +3 -1
- data/lib/action_pack.rb +17 -16
- metadata +30 -13
@@ -1,248 +1,250 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
module ActionDispatch
|
4
6
|
# The routing module provides URL rewriting in native Ruby. It's a way to
|
5
7
|
# redirect incoming requests to controllers and actions. This replaces
|
6
|
-
# mod_rewrite rules. Best of all, Rails'
|
7
|
-
# Routes are defined in
|
8
|
+
# mod_rewrite rules. Best of all, Rails' Routing works with any web server.
|
9
|
+
# Routes are defined in `config/routes.rb`.
|
8
10
|
#
|
9
11
|
# Think of creating routes as drawing a map for your requests. The map tells
|
10
12
|
# them where to go based on some predefined pattern:
|
11
13
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
14
|
+
# Rails.application.routes.draw do
|
15
|
+
# Pattern 1 tells some request to go to one place
|
16
|
+
# Pattern 2 tell them to go to another
|
17
|
+
# ...
|
18
|
+
# end
|
17
19
|
#
|
18
20
|
# The following symbols are special:
|
19
21
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
+
# :controller maps to your controller name
|
23
|
+
# :action maps to an action with your controllers
|
22
24
|
#
|
23
|
-
# Other names simply map to a parameter as in the case of
|
25
|
+
# Other names simply map to a parameter as in the case of `:id`.
|
24
26
|
#
|
25
|
-
#
|
27
|
+
# ## Resources
|
26
28
|
#
|
27
|
-
# Resource routing allows you to quickly declare all of the common routes
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
29
|
+
# Resource routing allows you to quickly declare all of the common routes for a
|
30
|
+
# given resourceful controller. Instead of declaring separate routes for your
|
31
|
+
# `index`, `show`, `new`, `edit`, `create`, `update`, and `destroy` actions, a
|
32
|
+
# resourceful route declares them in a single line of code:
|
31
33
|
#
|
32
|
-
#
|
34
|
+
# resources :photos
|
33
35
|
#
|
34
|
-
# Sometimes, you have a resource that clients always look up without
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
36
|
+
# Sometimes, you have a resource that clients always look up without referencing
|
37
|
+
# an ID. A common example, /profile always shows the profile of the currently
|
38
|
+
# logged in user. In this case, you can use a singular resource to map /profile
|
39
|
+
# (rather than /profile/:id) to the show action.
|
38
40
|
#
|
39
|
-
#
|
41
|
+
# resource :profile
|
40
42
|
#
|
41
|
-
# It's common to have resources that are logically children of other
|
42
|
-
# resources:
|
43
|
+
# It's common to have resources that are logically children of other resources:
|
43
44
|
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
45
|
+
# resources :magazines do
|
46
|
+
# resources :ads
|
47
|
+
# end
|
47
48
|
#
|
48
49
|
# You may wish to organize groups of controllers under a namespace. Most
|
49
|
-
# commonly, you might group a number of administrative controllers under
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
50
|
+
# commonly, you might group a number of administrative controllers under an
|
51
|
+
# `admin` namespace. You would place these controllers under the
|
52
|
+
# `app/controllers/admin` directory, and you can group them together in your
|
53
|
+
# router:
|
53
54
|
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
55
|
+
# namespace "admin" do
|
56
|
+
# resources :posts, :comments
|
57
|
+
# end
|
57
58
|
#
|
58
59
|
# Alternatively, you can add prefixes to your path without using a separate
|
59
|
-
# directory by using
|
60
|
-
#
|
60
|
+
# directory by using `scope`. `scope` takes additional options which apply to
|
61
|
+
# all enclosed routes.
|
61
62
|
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
63
|
+
# scope path: "/cpanel", as: 'admin' do
|
64
|
+
# resources :posts, :comments
|
65
|
+
# end
|
65
66
|
#
|
66
67
|
# For more, see Routing::Mapper::Resources#resources,
|
67
68
|
# Routing::Mapper::Scoping#namespace, and Routing::Mapper::Scoping#scope.
|
68
69
|
#
|
69
|
-
#
|
70
|
+
# ## Non-resourceful routes
|
70
71
|
#
|
71
|
-
# For routes that don't fit the
|
72
|
-
# methods
|
72
|
+
# For routes that don't fit the `resources` mold, you can use the HTTP helper
|
73
|
+
# methods `get`, `post`, `patch`, `put` and `delete`.
|
73
74
|
#
|
74
|
-
#
|
75
|
-
#
|
75
|
+
# get 'post/:id', to: 'posts#show'
|
76
|
+
# post 'post/:id', to: 'posts#create_comment'
|
76
77
|
#
|
77
|
-
# Now, if you POST to
|
78
|
-
# URL will route to the
|
78
|
+
# Now, if you POST to `/posts/:id`, it will route to the `create_comment`
|
79
|
+
# action. A GET on the same URL will route to the `show` action.
|
79
80
|
#
|
80
|
-
# If your route needs to respond to more than one HTTP method (or all methods)
|
81
|
-
#
|
81
|
+
# If your route needs to respond to more than one HTTP method (or all methods)
|
82
|
+
# then using the `:via` option on `match` is preferable.
|
82
83
|
#
|
83
|
-
#
|
84
|
+
# match 'post/:id', to: 'posts#show', via: [:get, :post]
|
84
85
|
#
|
85
|
-
#
|
86
|
+
# ## Named routes
|
86
87
|
#
|
87
|
-
# Routes can be named by passing an
|
88
|
-
#
|
89
|
-
#
|
88
|
+
# Routes can be named by passing an `:as` option, allowing for easy reference
|
89
|
+
# within your source as `name_of_route_url` for the full URL and
|
90
|
+
# `name_of_route_path` for the URI path.
|
90
91
|
#
|
91
92
|
# Example:
|
92
93
|
#
|
93
|
-
#
|
94
|
-
#
|
94
|
+
# # In config/routes.rb
|
95
|
+
# get '/login', to: 'accounts#login', as: 'login'
|
95
96
|
#
|
96
|
-
#
|
97
|
-
#
|
97
|
+
# # With render, redirect_to, tests, etc.
|
98
|
+
# redirect_to login_url
|
98
99
|
#
|
99
100
|
# Arguments can be passed as well.
|
100
101
|
#
|
101
|
-
#
|
102
|
+
# redirect_to show_item_path(id: 25)
|
102
103
|
#
|
103
|
-
# Use
|
104
|
+
# Use `root` as a shorthand to name a route for the root path "/".
|
104
105
|
#
|
105
|
-
#
|
106
|
-
#
|
106
|
+
# # In config/routes.rb
|
107
|
+
# root to: 'blogs#index'
|
107
108
|
#
|
108
|
-
#
|
109
|
-
#
|
109
|
+
# # would recognize http://www.example.com/ as
|
110
|
+
# params = { controller: 'blogs', action: 'index' }
|
110
111
|
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
112
|
+
# # and provide these named routes
|
113
|
+
# root_url # => 'http://www.example.com/'
|
114
|
+
# root_path # => '/'
|
114
115
|
#
|
115
|
-
# Note: when using
|
116
|
-
#
|
116
|
+
# Note: when using `controller`, the route is simply named after the method you
|
117
|
+
# call on the block parameter rather than map.
|
117
118
|
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
119
|
+
# # In config/routes.rb
|
120
|
+
# controller :blog do
|
121
|
+
# get 'blog/show' => :list
|
122
|
+
# get 'blog/delete' => :delete
|
123
|
+
# get 'blog/edit' => :edit
|
124
|
+
# end
|
124
125
|
#
|
125
|
-
#
|
126
|
-
#
|
126
|
+
# # provides named routes for show, delete, and edit
|
127
|
+
# link_to @article.title, blog_show_path(id: @article.id)
|
127
128
|
#
|
128
|
-
#
|
129
|
+
# ## Pretty URLs
|
129
130
|
#
|
130
131
|
# Routes can generate pretty URLs. For example:
|
131
132
|
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
133
|
+
# get '/articles/:year/:month/:day', to: 'articles#find_by_id', constraints: {
|
134
|
+
# year: /\d{4}/,
|
135
|
+
# month: /\d{1,2}/,
|
136
|
+
# day: /\d{1,2}/
|
137
|
+
# }
|
137
138
|
#
|
138
139
|
# Using the route above, the URL "http://localhost:3000/articles/2005/11/06"
|
139
140
|
# maps to
|
140
141
|
#
|
141
|
-
#
|
142
|
+
# params = {year: '2005', month: '11', day: '06'}
|
142
143
|
#
|
143
|
-
#
|
144
|
+
# ## Regular Expressions and parameters
|
144
145
|
# You can specify a regular expression to define a format for a parameter.
|
145
146
|
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
147
|
+
# controller 'geocode' do
|
148
|
+
# get 'geocode/:postalcode', to: :show, constraints: {
|
149
|
+
# postalcode: /\d{5}(-\d{4})?/
|
150
|
+
# }
|
151
|
+
# end
|
151
152
|
#
|
152
153
|
# Constraints can include the 'ignorecase' and 'extended syntax' regular
|
153
154
|
# expression modifiers:
|
154
155
|
#
|
155
|
-
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
156
|
+
# controller 'geocode' do
|
157
|
+
# get 'geocode/:postalcode', to: :show, constraints: {
|
158
|
+
# postalcode: /hx\d\d\s\d[a-z]{2}/i
|
159
|
+
# }
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
# controller 'geocode' do
|
163
|
+
# get 'geocode/:postalcode', to: :show, constraints: {
|
164
|
+
# postalcode: /# Postalcode format
|
165
|
+
# \d{5} #Prefix
|
166
|
+
# (-\d{4})? #Suffix
|
167
|
+
# /x
|
168
|
+
# }
|
169
|
+
# end
|
169
170
|
#
|
170
|
-
# Using the multiline modifier will raise an
|
171
|
-
#
|
172
|
-
#
|
171
|
+
# Using the multiline modifier will raise an `ArgumentError`. Encoding regular
|
172
|
+
# expression modifiers are silently ignored. The match will always use the
|
173
|
+
# default encoding or ASCII.
|
173
174
|
#
|
174
|
-
#
|
175
|
+
# ## External redirects
|
175
176
|
#
|
176
|
-
# You can redirect any path to another path using the redirect helper in your
|
177
|
+
# You can redirect any path to another path using the redirect helper in your
|
178
|
+
# router:
|
177
179
|
#
|
178
|
-
#
|
180
|
+
# get "/stories", to: redirect("/posts")
|
179
181
|
#
|
180
|
-
#
|
182
|
+
# ## Unicode character routes
|
181
183
|
#
|
182
184
|
# You can specify unicode character routes in your router:
|
183
185
|
#
|
184
|
-
#
|
186
|
+
# get "こんにちは", to: "welcome#index"
|
185
187
|
#
|
186
|
-
#
|
188
|
+
# ## Routing to Rack Applications
|
187
189
|
#
|
188
|
-
# Instead of a String, like
|
189
|
-
#
|
190
|
-
#
|
190
|
+
# Instead of a String, like `posts#index`, which corresponds to the index action
|
191
|
+
# in the PostsController, you can specify any Rack application as the endpoint
|
192
|
+
# for a matcher:
|
191
193
|
#
|
192
|
-
#
|
194
|
+
# get "/application.js", to: Sprockets
|
193
195
|
#
|
194
|
-
#
|
196
|
+
# ## Reloading routes
|
195
197
|
#
|
196
198
|
# You can reload routes if you feel you must:
|
197
199
|
#
|
198
|
-
#
|
200
|
+
# Rails.application.reload_routes!
|
199
201
|
#
|
200
|
-
# This will clear all named routes and reload config/routes.rb if the file has
|
201
|
-
# last load. To absolutely force reloading, use
|
202
|
+
# This will clear all named routes and reload config/routes.rb if the file has
|
203
|
+
# been modified from last load. To absolutely force reloading, use `reload!`.
|
202
204
|
#
|
203
|
-
#
|
205
|
+
# ## Testing Routes
|
204
206
|
#
|
205
207
|
# The two main methods for testing your routes:
|
206
208
|
#
|
207
|
-
#
|
209
|
+
# ### `assert_routing`
|
208
210
|
#
|
209
|
-
#
|
210
|
-
#
|
211
|
-
#
|
212
|
-
#
|
211
|
+
# def test_movie_route_properly_splits
|
212
|
+
# opts = {controller: "plugin", action: "checkout", id: "2"}
|
213
|
+
# assert_routing "plugin/checkout/2", opts
|
214
|
+
# end
|
213
215
|
#
|
214
|
-
#
|
216
|
+
# `assert_routing` lets you test whether or not the route properly resolves into
|
217
|
+
# options.
|
215
218
|
#
|
216
|
-
#
|
219
|
+
# ### `assert_recognizes`
|
217
220
|
#
|
218
|
-
#
|
219
|
-
#
|
220
|
-
#
|
221
|
-
#
|
221
|
+
# def test_route_has_options
|
222
|
+
# opts = {controller: "plugin", action: "show", id: "12"}
|
223
|
+
# assert_recognizes opts, "/plugins/show/12"
|
224
|
+
# end
|
222
225
|
#
|
223
|
-
# Note the subtle difference between the two:
|
224
|
-
#
|
225
|
-
#
|
226
|
+
# Note the subtle difference between the two: `assert_routing` tests that a URL
|
227
|
+
# fits options while `assert_recognizes` tests that a URL breaks into parameters
|
228
|
+
# properly.
|
226
229
|
#
|
227
|
-
# In tests you can simply pass the URL or named route to
|
230
|
+
# In tests you can simply pass the URL or named route to `get` or `post`.
|
228
231
|
#
|
229
|
-
#
|
230
|
-
#
|
231
|
-
#
|
232
|
-
#
|
232
|
+
# def send_to_jail
|
233
|
+
# get '/jail'
|
234
|
+
# assert_response :success
|
235
|
+
# end
|
233
236
|
#
|
234
|
-
#
|
235
|
-
#
|
236
|
-
#
|
237
|
-
#
|
237
|
+
# def goes_to_login
|
238
|
+
# get login_url
|
239
|
+
# #...
|
240
|
+
# end
|
238
241
|
#
|
239
|
-
#
|
242
|
+
# ## View a list of all your routes
|
240
243
|
#
|
241
|
-
#
|
244
|
+
# $ bin/rails routes
|
242
245
|
#
|
243
|
-
# Target a specific controller with
|
244
|
-
#
|
245
|
-
# which displays routes vertically.
|
246
|
+
# Target a specific controller with `-c`, or grep routes using `-g`. Useful in
|
247
|
+
# conjunction with `--expanded` which displays routes vertically.
|
246
248
|
module Routing
|
247
249
|
extend ActiveSupport::Autoload
|
248
250
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
gem "capybara", ">= 3.26"
|
4
6
|
|
5
7
|
require "capybara/dsl"
|
@@ -12,103 +14,103 @@ require "action_dispatch/system_testing/test_helpers/screenshot_helper"
|
|
12
14
|
require "action_dispatch/system_testing/test_helpers/setup_and_teardown"
|
13
15
|
|
14
16
|
module ActionDispatch
|
15
|
-
#
|
17
|
+
# # System Testing
|
16
18
|
#
|
17
|
-
# System tests let you test applications in the browser. Because system
|
18
|
-
#
|
19
|
-
#
|
19
|
+
# System tests let you test applications in the browser. Because system tests
|
20
|
+
# use a real browser experience, you can test all of your JavaScript easily from
|
21
|
+
# your test suite.
|
20
22
|
#
|
21
|
-
# To create a system test in your application, extend your test class
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
# application or scaffold.
|
23
|
+
# To create a system test in your application, extend your test class from
|
24
|
+
# `ApplicationSystemTestCase`. System tests use Capybara as a base and allow you
|
25
|
+
# to configure the settings through your `application_system_test_case.rb` file
|
26
|
+
# that is generated with a new application or scaffold.
|
26
27
|
#
|
27
28
|
# Here is an example system test:
|
28
29
|
#
|
29
|
-
#
|
30
|
+
# require "application_system_test_case"
|
30
31
|
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
32
|
+
# class Users::CreateTest < ApplicationSystemTestCase
|
33
|
+
# test "adding a new user" do
|
34
|
+
# visit users_path
|
35
|
+
# click_on 'New User'
|
35
36
|
#
|
36
|
-
#
|
37
|
-
#
|
37
|
+
# fill_in 'Name', with: 'Arya'
|
38
|
+
# click_on 'Create User'
|
38
39
|
#
|
39
|
-
#
|
40
|
+
# assert_text 'Arya'
|
41
|
+
# end
|
40
42
|
# end
|
41
|
-
# end
|
42
43
|
#
|
43
|
-
# When generating an application or scaffold, an
|
44
|
-
# file will also be generated containing the
|
45
|
-
# This is where you can change the driver, add
|
46
|
-
# configuration for your system tests.
|
44
|
+
# When generating an application or scaffold, an
|
45
|
+
# `application_system_test_case.rb` file will also be generated containing the
|
46
|
+
# base class for system testing. This is where you can change the driver, add
|
47
|
+
# Capybara settings, and other configuration for your system tests.
|
47
48
|
#
|
48
|
-
#
|
49
|
+
# require "test_helper"
|
49
50
|
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
51
|
+
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
52
|
+
# driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
|
53
|
+
# end
|
53
54
|
#
|
54
|
-
# By default,
|
55
|
-
#
|
55
|
+
# By default, `ActionDispatch::SystemTestCase` is driven by the Selenium driver,
|
56
|
+
# with the Chrome browser, and a browser size of 1400x1400.
|
56
57
|
#
|
57
58
|
# Changing the driver configuration options is easy. Let's say you want to use
|
58
|
-
# the Firefox browser instead of Chrome. In your
|
59
|
-
# file add the following:
|
60
|
-
#
|
61
|
-
# require "test_helper"
|
59
|
+
# the Firefox browser instead of Chrome. In your
|
60
|
+
# `application_system_test_case.rb` file add the following:
|
62
61
|
#
|
63
|
-
#
|
64
|
-
# driven_by :selenium, using: :firefox
|
65
|
-
# end
|
62
|
+
# require "test_helper"
|
66
63
|
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
# headless drivers and will be silently ignored if passed.
|
71
|
-
#
|
72
|
-
# Headless browsers such as headless Chrome and headless Firefox are also supported.
|
73
|
-
# You can use these browsers by setting the +:using+ argument to +:headless_chrome+ or +:headless_firefox+.
|
64
|
+
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
65
|
+
# driven_by :selenium, using: :firefox
|
66
|
+
# end
|
74
67
|
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
68
|
+
# `driven_by` has a required argument for the driver name. The keyword arguments
|
69
|
+
# are `:using` for the browser and `:screen_size` to change the size of the
|
70
|
+
# browser screen. These two options are not applicable for headless drivers and
|
71
|
+
# will be silently ignored if passed.
|
72
|
+
#
|
73
|
+
# Headless browsers such as headless Chrome and headless Firefox are also
|
74
|
+
# supported. You can use these browsers by setting the `:using` argument to
|
75
|
+
# `:headless_chrome` or `:headless_firefox`.
|
76
|
+
#
|
77
|
+
# To use a headless driver, like Cuprite, update your Gemfile to use Cuprite
|
78
|
+
# instead of Selenium and then declare the driver name in the
|
79
|
+
# `application_system_test_case.rb` file. In this case, you would leave out the
|
80
|
+
# `:using` option because the driver is headless, but you can still use
|
81
|
+
# `:screen_size` to change the size of the browser screen, also you can use
|
82
|
+
# `:options` to pass options supported by the driver. Please refer to your
|
81
83
|
# driver documentation to learn about supported options.
|
82
84
|
#
|
83
|
-
#
|
84
|
-
#
|
85
|
+
# require "test_helper"
|
86
|
+
# require "capybara/cuprite"
|
85
87
|
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
88
|
+
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
89
|
+
# driven_by :cuprite, screen_size: [1400, 1400], options:
|
90
|
+
# { js_errors: true }
|
91
|
+
# end
|
90
92
|
#
|
91
|
-
# Some drivers require browser capabilities to be passed as a block instead
|
92
|
-
#
|
93
|
+
# Some drivers require browser capabilities to be passed as a block instead of
|
94
|
+
# through the `options` hash.
|
93
95
|
#
|
94
96
|
# As an example, if you want to add mobile emulation on chrome, you'll have to
|
95
|
-
# create an instance of selenium's
|
96
|
-
#
|
97
|
-
#
|
98
|
-
# The block will be passed an instance of
|
99
|
-
# define the capabilities you want. Please refer to your driver documentation
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
97
|
+
# create an instance of selenium's `Chrome::Options` object and add capabilities
|
98
|
+
# with a block.
|
99
|
+
#
|
100
|
+
# The block will be passed an instance of `<Driver>::Options` where you can
|
101
|
+
# define the capabilities you want. Please refer to your driver documentation to
|
102
|
+
# learn about supported options.
|
103
|
+
#
|
104
|
+
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
105
|
+
# driven_by :selenium, using: :chrome, screen_size: [1024, 768] do |driver_option|
|
106
|
+
# driver_option.add_emulation(device_name: 'iPhone 6')
|
107
|
+
# driver_option.add_extension('path/to/chrome_extension.crx')
|
108
|
+
# end
|
106
109
|
# end
|
107
|
-
# end
|
108
110
|
#
|
109
|
-
# Because
|
110
|
-
#
|
111
|
-
#
|
111
|
+
# Because `ActionDispatch::SystemTestCase` is a shim between Capybara and Rails,
|
112
|
+
# any driver that is supported by Capybara is supported by system tests as long
|
113
|
+
# as you include the required gems and files.
|
112
114
|
class SystemTestCase < ActiveSupport::TestCase
|
113
115
|
include Capybara::DSL
|
114
116
|
include Capybara::Minitest::Assertions
|
@@ -137,28 +139,36 @@ module ActionDispatch
|
|
137
139
|
|
138
140
|
# System Test configuration options
|
139
141
|
#
|
140
|
-
# The default settings are Selenium, using Chrome, with a screen size
|
141
|
-
#
|
142
|
+
# The default settings are Selenium, using Chrome, with a screen size of
|
143
|
+
# 1400x1400.
|
142
144
|
#
|
143
145
|
# Examples:
|
144
146
|
#
|
145
|
-
#
|
147
|
+
# driven_by :cuprite
|
146
148
|
#
|
147
|
-
#
|
149
|
+
# driven_by :selenium, screen_size: [800, 800]
|
148
150
|
#
|
149
|
-
#
|
151
|
+
# driven_by :selenium, using: :chrome
|
150
152
|
#
|
151
|
-
#
|
153
|
+
# driven_by :selenium, using: :headless_chrome
|
152
154
|
#
|
153
|
-
#
|
155
|
+
# driven_by :selenium, using: :firefox
|
154
156
|
#
|
155
|
-
#
|
157
|
+
# driven_by :selenium, using: :headless_firefox
|
156
158
|
def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {}, &capabilities)
|
157
159
|
driver_options = { using: using, screen_size: screen_size, options: options }
|
158
160
|
|
159
161
|
self.driver = SystemTesting::Driver.new(driver, **driver_options, &capabilities)
|
160
162
|
end
|
161
163
|
|
164
|
+
# Configuration for the System Test application server.
|
165
|
+
#
|
166
|
+
# By default this is localhost. This method allows the host and port to be specified manually.
|
167
|
+
def self.served_by(host:, port:)
|
168
|
+
Capybara.server_host = host
|
169
|
+
Capybara.server_port = port
|
170
|
+
end
|
171
|
+
|
162
172
|
private
|
163
173
|
def url_helpers
|
164
174
|
@url_helpers ||=
|
@@ -178,9 +188,9 @@ module ActionDispatch
|
|
178
188
|
end
|
179
189
|
end
|
180
190
|
|
181
|
-
def method_missing(name,
|
191
|
+
def method_missing(name, ...)
|
182
192
|
if url_helpers.respond_to?(name)
|
183
|
-
url_helpers.public_send(name,
|
193
|
+
url_helpers.public_send(name, ...)
|
184
194
|
else
|
185
195
|
super
|
186
196
|
end
|