actionpack 5.1.7 → 5.2.4.3
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 +282 -362
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/lib/abstract_controller.rb +3 -0
- data/lib/abstract_controller/asset_paths.rb +2 -0
- data/lib/abstract_controller/base.rb +10 -2
- data/lib/abstract_controller/caching.rb +3 -2
- data/lib/abstract_controller/caching/fragments.rb +30 -7
- data/lib/abstract_controller/callbacks.rb +25 -3
- data/lib/abstract_controller/collector.rb +2 -0
- data/lib/abstract_controller/error.rb +2 -0
- data/lib/abstract_controller/helpers.rb +4 -5
- data/lib/abstract_controller/logger.rb +2 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
- data/lib/abstract_controller/rendering.rb +9 -16
- data/lib/abstract_controller/translation.rb +2 -0
- data/lib/abstract_controller/url_for.rb +2 -0
- data/lib/action_controller.rb +3 -0
- data/lib/action_controller/api.rb +2 -0
- data/lib/action_controller/api/api_rendering.rb +2 -0
- data/lib/action_controller/base.rb +3 -0
- data/lib/action_controller/caching.rb +2 -0
- data/lib/action_controller/form_builder.rb +2 -0
- data/lib/action_controller/log_subscriber.rb +5 -3
- data/lib/action_controller/metal.rb +13 -14
- data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
- data/lib/action_controller/metal/conditional_get.rb +4 -3
- data/lib/action_controller/metal/content_security_policy.rb +52 -0
- data/lib/action_controller/metal/cookies.rb +2 -0
- data/lib/action_controller/metal/data_streaming.rb +7 -5
- data/lib/action_controller/metal/etag_with_flash.rb +2 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +3 -2
- data/lib/action_controller/metal/exceptions.rb +2 -3
- data/lib/action_controller/metal/flash.rb +3 -2
- data/lib/action_controller/metal/force_ssl.rb +4 -2
- data/lib/action_controller/metal/head.rb +2 -0
- data/lib/action_controller/metal/helpers.rb +4 -3
- data/lib/action_controller/metal/http_authentication.rb +8 -9
- data/lib/action_controller/metal/implicit_render.rb +2 -0
- data/lib/action_controller/metal/instrumentation.rb +4 -6
- data/lib/action_controller/metal/live.rb +3 -1
- data/lib/action_controller/metal/mime_responds.rb +3 -1
- data/lib/action_controller/metal/parameter_encoding.rb +2 -0
- data/lib/action_controller/metal/params_wrapper.rb +14 -10
- data/lib/action_controller/metal/redirecting.rb +22 -11
- data/lib/action_controller/metal/renderers.rb +4 -3
- data/lib/action_controller/metal/rendering.rb +2 -2
- data/lib/action_controller/metal/request_forgery_protection.rb +62 -10
- data/lib/action_controller/metal/rescue.rb +5 -3
- data/lib/action_controller/metal/streaming.rb +3 -1
- data/lib/action_controller/metal/strong_parameters.rb +36 -25
- data/lib/action_controller/metal/testing.rb +2 -6
- data/lib/action_controller/metal/url_for.rb +2 -0
- data/lib/action_controller/railtie.rb +16 -4
- data/lib/action_controller/railties/helpers.rb +2 -0
- data/lib/action_controller/renderer.rb +2 -0
- data/lib/action_controller/template_assertions.rb +2 -0
- data/lib/action_controller/test_case.rb +16 -10
- data/lib/action_dispatch.rb +9 -5
- data/lib/action_dispatch/http/cache.rb +22 -14
- data/lib/action_dispatch/http/content_security_policy.rb +272 -0
- data/lib/action_dispatch/http/filter_parameters.rb +4 -2
- data/lib/action_dispatch/http/filter_redirect.rb +2 -0
- data/lib/action_dispatch/http/headers.rb +2 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +4 -8
- data/lib/action_dispatch/http/mime_type.rb +15 -13
- data/lib/action_dispatch/http/mime_types.rb +17 -2
- data/lib/action_dispatch/http/parameter_filter.rb +2 -0
- data/lib/action_dispatch/http/parameters.rb +6 -9
- data/lib/action_dispatch/http/rack_cache.rb +2 -0
- data/lib/action_dispatch/http/request.rb +36 -16
- data/lib/action_dispatch/http/response.rb +11 -9
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/http/url.rb +5 -6
- data/lib/action_dispatch/journey.rb +2 -0
- data/lib/action_dispatch/journey/formatter.rb +4 -2
- data/lib/action_dispatch/journey/gtg/builder.rb +2 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +2 -8
- data/lib/action_dispatch/journey/gtg/transition_table.rb +3 -2
- data/lib/action_dispatch/journey/nfa/builder.rb +2 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +12 -10
- data/lib/action_dispatch/journey/nfa/simulator.rb +2 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +2 -0
- data/lib/action_dispatch/journey/nodes/node.rb +2 -0
- 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 +15 -6
- data/lib/action_dispatch/journey/router.rb +3 -1
- data/lib/action_dispatch/journey/router/utils.rb +14 -7
- data/lib/action_dispatch/journey/routes.rb +3 -1
- data/lib/action_dispatch/journey/scanner.rb +1 -0
- data/lib/action_dispatch/journey/visitors.rb +5 -3
- data/lib/action_dispatch/middleware/callbacks.rb +2 -0
- data/lib/action_dispatch/middleware/cookies.rb +148 -91
- data/lib/action_dispatch/middleware/debug_exceptions.rb +4 -2
- data/lib/action_dispatch/middleware/debug_locks.rb +9 -7
- data/lib/action_dispatch/middleware/exception_wrapper.rb +5 -6
- data/lib/action_dispatch/middleware/executor.rb +2 -0
- data/lib/action_dispatch/middleware/flash.rb +4 -2
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -4
- data/lib/action_dispatch/middleware/reloader.rb +2 -0
- data/lib/action_dispatch/middleware/remote_ip.rb +7 -5
- data/lib/action_dispatch/middleware/request_id.rb +3 -1
- data/lib/action_dispatch/middleware/session/abstract_store.rb +17 -1
- data/lib/action_dispatch/middleware/session/cache_store.rb +13 -6
- data/lib/action_dispatch/middleware/session/cookie_store.rb +31 -32
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +3 -1
- data/lib/action_dispatch/middleware/ssl.rb +44 -38
- data/lib/action_dispatch/middleware/stack.rb +4 -2
- data/lib/action_dispatch/middleware/static.rb +14 -12
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +6 -2
- data/lib/action_dispatch/railtie.rb +11 -1
- data/lib/action_dispatch/request/session.rb +16 -5
- data/lib/action_dispatch/request/utils.rb +6 -4
- data/lib/action_dispatch/routing.rb +3 -1
- data/lib/action_dispatch/routing/endpoint.rb +9 -2
- data/lib/action_dispatch/routing/inspector.rb +6 -4
- data/lib/action_dispatch/routing/mapper.rb +64 -52
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
- data/lib/action_dispatch/routing/redirection.rb +7 -5
- data/lib/action_dispatch/routing/route_set.rb +29 -24
- data/lib/action_dispatch/routing/routes_proxy.rb +5 -2
- data/lib/action_dispatch/routing/url_for.rb +25 -5
- data/lib/action_dispatch/system_test_case.rb +22 -6
- data/lib/action_dispatch/system_testing/browser.rb +49 -0
- data/lib/action_dispatch/system_testing/driver.rb +9 -3
- data/lib/action_dispatch/system_testing/server.rb +2 -16
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +12 -14
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +8 -2
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
- data/lib/action_dispatch/testing/assertion_response.rb +2 -0
- data/lib/action_dispatch/testing/assertions.rb +2 -0
- data/lib/action_dispatch/testing/assertions/response.rb +4 -2
- data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
- data/lib/action_dispatch/testing/integration.rb +24 -21
- data/lib/action_dispatch/testing/request_encoder.rb +3 -1
- data/lib/action_dispatch/testing/test_process.rb +2 -0
- data/lib/action_dispatch/testing/test_request.rb +3 -1
- data/lib/action_dispatch/testing/test_response.rb +23 -3
- data/lib/action_pack.rb +3 -1
- data/lib/action_pack/gem_version.rb +5 -3
- data/lib/action_pack/version.rb +2 -0
- metadata +23 -11
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "action_dispatch/http/request"
|
2
4
|
require "active_support/core_ext/uri"
|
3
5
|
require "active_support/core_ext/array/extract_options"
|
@@ -140,13 +142,13 @@ module ActionDispatch
|
|
140
142
|
# get "/stories" => redirect("/posts")
|
141
143
|
#
|
142
144
|
# This will redirect the user, while ignoring certain parts of the request, including query string, etc.
|
143
|
-
#
|
145
|
+
# <tt>/stories</tt>, <tt>/stories?foo=bar</tt>, etc all redirect to <tt>/posts</tt>.
|
144
146
|
#
|
145
147
|
# You can also use interpolation in the supplied redirect argument:
|
146
148
|
#
|
147
149
|
# get 'docs/:article', to: redirect('/wiki/%{article}')
|
148
150
|
#
|
149
|
-
# Note that if you return a path without a leading slash then the
|
151
|
+
# Note that if you return a path without a leading slash then the URL is prefixed with the
|
150
152
|
# current SCRIPT_NAME environment variable. This is typically '/' but may be different in
|
151
153
|
# a mounted engine or where the application is deployed to a subdirectory of a website.
|
152
154
|
#
|
@@ -165,7 +167,7 @@ module ActionDispatch
|
|
165
167
|
# Note that the +do end+ syntax for the redirect block wouldn't work, as Ruby would pass
|
166
168
|
# the block to +get+ instead of +redirect+. Use <tt>{ ... }</tt> instead.
|
167
169
|
#
|
168
|
-
# The options version of redirect allows you to supply only the parts of the
|
170
|
+
# The options version of redirect allows you to supply only the parts of the URL which need
|
169
171
|
# to change, it also supports interpolation of the path similar to the first example.
|
170
172
|
#
|
171
173
|
# get 'stores/:name', to: redirect(subdomain: 'stores', path: '/%{name}')
|
@@ -173,8 +175,8 @@ module ActionDispatch
|
|
173
175
|
# get '/stories', to: redirect(path: '/posts')
|
174
176
|
#
|
175
177
|
# This will redirect the user, while changing only the specified parts of the request,
|
176
|
-
# for example the
|
177
|
-
#
|
178
|
+
# for example the +path+ option in the last example.
|
179
|
+
# <tt>/stories</tt>, <tt>/stories?foo=bar</tt>, redirect to <tt>/posts</tt> and <tt>/posts?foo=bar</tt> respectively.
|
178
180
|
#
|
179
181
|
# Finally, an object which responds to call can be supplied to redirect, allowing you to reuse
|
180
182
|
# common redirect routes. The call method must accept two arguments, params and request, and return
|
@@ -1,6 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "action_dispatch/journey"
|
2
4
|
require "active_support/core_ext/object/to_query"
|
3
5
|
require "active_support/core_ext/hash/slice"
|
6
|
+
require "active_support/core_ext/module/redefine_method"
|
4
7
|
require "active_support/core_ext/module/remove_method"
|
5
8
|
require "active_support/core_ext/array/extract_options"
|
6
9
|
require "action_controller/metal/exceptions"
|
@@ -73,7 +76,6 @@ module ActionDispatch
|
|
73
76
|
@routes = {}
|
74
77
|
@path_helpers = Set.new
|
75
78
|
@url_helpers = Set.new
|
76
|
-
@custom_helpers = Set.new
|
77
79
|
@url_helpers_module = Module.new
|
78
80
|
@path_helpers_module = Module.new
|
79
81
|
end
|
@@ -96,23 +98,9 @@ module ActionDispatch
|
|
96
98
|
@url_helpers_module.send :remove_method, helper
|
97
99
|
end
|
98
100
|
|
99
|
-
@custom_helpers.each do |helper|
|
100
|
-
path_name = :"#{helper}_path"
|
101
|
-
url_name = :"#{helper}_url"
|
102
|
-
|
103
|
-
if @path_helpers_module.method_defined?(path_name)
|
104
|
-
@path_helpers_module.send :remove_method, path_name
|
105
|
-
end
|
106
|
-
|
107
|
-
if @url_helpers_module.method_defined?(url_name)
|
108
|
-
@url_helpers_module.send :remove_method, url_name
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
101
|
@routes.clear
|
113
102
|
@path_helpers.clear
|
114
103
|
@url_helpers.clear
|
115
|
-
@custom_helpers.clear
|
116
104
|
end
|
117
105
|
|
118
106
|
def add(name, route)
|
@@ -158,21 +146,29 @@ module ActionDispatch
|
|
158
146
|
routes.length
|
159
147
|
end
|
160
148
|
|
149
|
+
# Given a +name+, defines name_path and name_url helpers.
|
150
|
+
# Used by 'direct', 'resolve', and 'polymorphic' route helpers.
|
161
151
|
def add_url_helper(name, defaults, &block)
|
162
|
-
@custom_helpers << name
|
163
152
|
helper = CustomUrlHelper.new(name, defaults, &block)
|
153
|
+
path_name = :"#{name}_path"
|
154
|
+
url_name = :"#{name}_url"
|
164
155
|
|
165
156
|
@path_helpers_module.module_eval do
|
166
|
-
define_method(
|
157
|
+
define_method(path_name) do |*args|
|
167
158
|
helper.call(self, args, true)
|
168
159
|
end
|
169
160
|
end
|
170
161
|
|
171
162
|
@url_helpers_module.module_eval do
|
172
|
-
define_method(
|
163
|
+
define_method(url_name) do |*args|
|
173
164
|
helper.call(self, args, false)
|
174
165
|
end
|
175
166
|
end
|
167
|
+
|
168
|
+
@path_helpers << path_name
|
169
|
+
@url_helpers << url_name
|
170
|
+
|
171
|
+
self
|
176
172
|
end
|
177
173
|
|
178
174
|
class UrlHelper
|
@@ -250,7 +246,7 @@ module ActionDispatch
|
|
250
246
|
missing_keys << missing_key
|
251
247
|
}
|
252
248
|
constraints = Hash[@route.requirements.merge(params).sort_by { |k, v| k.to_s }]
|
253
|
-
message = "No route matches #{constraints.inspect}"
|
249
|
+
message = "No route matches #{constraints.inspect}".dup
|
254
250
|
message << ", missing required keys: #{missing_keys.sort.inspect}"
|
255
251
|
|
256
252
|
raise ActionController::UrlGenerationError, message
|
@@ -307,7 +303,7 @@ module ActionDispatch
|
|
307
303
|
end
|
308
304
|
|
309
305
|
private
|
310
|
-
# Create a
|
306
|
+
# Create a URL helper allowing ordered parameters to be associated
|
311
307
|
# with corresponding dynamic segments, so you can do:
|
312
308
|
#
|
313
309
|
# foo_url(bar, baz, bang)
|
@@ -561,7 +557,7 @@ module ActionDispatch
|
|
561
557
|
|
562
558
|
# plus a singleton class method called _routes ...
|
563
559
|
included do
|
564
|
-
|
560
|
+
redefine_singleton_method(:_routes) { routes }
|
565
561
|
end
|
566
562
|
|
567
563
|
# And an instance method _routes. Note that
|
@@ -598,14 +594,14 @@ module ActionDispatch
|
|
598
594
|
if route.segment_keys.include?(:controller)
|
599
595
|
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
600
596
|
Using a dynamic :controller segment in a route is deprecated and
|
601
|
-
will be removed in Rails
|
597
|
+
will be removed in Rails 6.0.
|
602
598
|
MSG
|
603
599
|
end
|
604
600
|
|
605
601
|
if route.segment_keys.include?(:action)
|
606
602
|
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
607
603
|
Using a dynamic :action segment in a route is deprecated and
|
608
|
-
will be removed in Rails
|
604
|
+
will be removed in Rails 6.0.
|
609
605
|
MSG
|
610
606
|
end
|
611
607
|
|
@@ -856,6 +852,10 @@ module ActionDispatch
|
|
856
852
|
end
|
857
853
|
|
858
854
|
req = make_request(env)
|
855
|
+
recognize_path_with_request(req, path, extras)
|
856
|
+
end
|
857
|
+
|
858
|
+
def recognize_path_with_request(req, path, extras, raise_on_missing: true)
|
859
859
|
@router.recognize(req) do |route, params|
|
860
860
|
params.merge!(extras)
|
861
861
|
params.each do |key, value|
|
@@ -874,10 +874,15 @@ module ActionDispatch
|
|
874
874
|
end
|
875
875
|
|
876
876
|
return req.path_parameters
|
877
|
+
elsif app.matches?(req) && app.engine?
|
878
|
+
path_parameters = app.rack_app.routes.recognize_path_with_request(req, path, extras, raise_on_missing: false)
|
879
|
+
return path_parameters if path_parameters
|
877
880
|
end
|
878
881
|
end
|
879
882
|
|
880
|
-
|
883
|
+
if raise_on_missing
|
884
|
+
raise ActionController::RoutingError, "No route matches #{path.inspect}"
|
885
|
+
end
|
881
886
|
end
|
882
887
|
end
|
883
888
|
# :startdoc:
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/array/extract_options"
|
2
4
|
|
3
5
|
module ActionDispatch
|
@@ -20,7 +22,8 @@ module ActionDispatch
|
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
|
25
|
+
private
|
26
|
+
def respond_to_missing?(method, _)
|
24
27
|
super || @helpers.respond_to?(method)
|
25
28
|
end
|
26
29
|
|
@@ -42,7 +45,7 @@ module ActionDispatch
|
|
42
45
|
@helpers.#{method}(*args)
|
43
46
|
end
|
44
47
|
RUBY
|
45
|
-
|
48
|
+
public_send(method, *args)
|
46
49
|
else
|
47
50
|
super
|
48
51
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
4
|
module Routing
|
3
5
|
# In <tt>config/routes.rb</tt> you define URL-to-controller mappings, but the reverse
|
@@ -107,16 +109,16 @@ module ActionDispatch
|
|
107
109
|
end
|
108
110
|
|
109
111
|
# Hook overridden in controller to add request information
|
110
|
-
# with
|
112
|
+
# with +default_url_options+. Application logic should not
|
111
113
|
# go into url_options.
|
112
114
|
def url_options
|
113
115
|
default_url_options
|
114
116
|
end
|
115
117
|
|
116
|
-
# Generate a
|
118
|
+
# Generate a URL based on the options provided, default_url_options and the
|
117
119
|
# routes defined in routes.rb. The following options are supported:
|
118
120
|
#
|
119
|
-
# * <tt>:only_path</tt> - If true, the relative
|
121
|
+
# * <tt>:only_path</tt> - If true, the relative URL is returned. Defaults to +false+.
|
120
122
|
# * <tt>:protocol</tt> - The protocol to connect to. Defaults to 'http'.
|
121
123
|
# * <tt>:host</tt> - Specifies the host the link should be targeted at.
|
122
124
|
# If <tt>:only_path</tt> is false, this option must be
|
@@ -153,7 +155,7 @@ module ActionDispatch
|
|
153
155
|
# Missing routes keys may be filled in from the current request's parameters
|
154
156
|
# (e.g. +:controller+, +:action+, +:id+ and any other parameters that are
|
155
157
|
# placed in the path). Given that the current action has been reached
|
156
|
-
# through
|
158
|
+
# through <tt>GET /users/1</tt>:
|
157
159
|
#
|
158
160
|
# url_for(only_path: true) # => '/users/1'
|
159
161
|
# url_for(only_path: true, action: 'edit') # => '/users/1/edit'
|
@@ -189,7 +191,25 @@ module ActionDispatch
|
|
189
191
|
end
|
190
192
|
end
|
191
193
|
|
192
|
-
|
194
|
+
# Allows calling direct or regular named route.
|
195
|
+
#
|
196
|
+
# resources :buckets
|
197
|
+
#
|
198
|
+
# direct :recordable do |recording|
|
199
|
+
# route_for(:bucket, recording.bucket)
|
200
|
+
# end
|
201
|
+
#
|
202
|
+
# direct :threadable do |threadable|
|
203
|
+
# route_for(:recordable, threadable.parent)
|
204
|
+
# end
|
205
|
+
#
|
206
|
+
# This maintains the context of the original caller on
|
207
|
+
# whether to return a path or full URL, e.g:
|
208
|
+
#
|
209
|
+
# threadable_path(threadable) # => "/buckets/1"
|
210
|
+
# threadable_url(threadable) # => "http://example.com/buckets/1"
|
211
|
+
#
|
212
|
+
def route_for(name, *args)
|
193
213
|
public_send(:"#{name}_url", *args)
|
194
214
|
end
|
195
215
|
|
@@ -1,12 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
gem "capybara", ">= 2.15"
|
2
4
|
|
3
5
|
require "capybara/dsl"
|
4
6
|
require "capybara/minitest"
|
5
7
|
require "action_controller"
|
6
8
|
require "action_dispatch/system_testing/driver"
|
9
|
+
require "action_dispatch/system_testing/browser"
|
7
10
|
require "action_dispatch/system_testing/server"
|
8
11
|
require "action_dispatch/system_testing/test_helpers/screenshot_helper"
|
9
12
|
require "action_dispatch/system_testing/test_helpers/setup_and_teardown"
|
13
|
+
require "action_dispatch/system_testing/test_helpers/undef_methods"
|
10
14
|
|
11
15
|
module ActionDispatch
|
12
16
|
# = System Testing
|
@@ -51,7 +55,7 @@ module ActionDispatch
|
|
51
55
|
# By default, <tt>ActionDispatch::SystemTestCase</tt> is driven by the
|
52
56
|
# Selenium driver, with the Chrome browser, and a browser size of 1400x1400.
|
53
57
|
#
|
54
|
-
# Changing the driver configuration options
|
58
|
+
# Changing the driver configuration options is easy. Let's say you want to use
|
55
59
|
# the Firefox browser instead of Chrome. In your +application_system_test_case.rb+
|
56
60
|
# file add the following:
|
57
61
|
#
|
@@ -66,12 +70,15 @@ module ActionDispatch
|
|
66
70
|
# size of the browser screen. These two options are not applicable for
|
67
71
|
# headless drivers and will be silently ignored if passed.
|
68
72
|
#
|
73
|
+
# Headless browsers such as headless Chrome and headless Firefox are also supported.
|
74
|
+
# You can use these browsers by setting the +:using+ argument to +:headless_chrome+ or +:headless_firefox+.
|
75
|
+
#
|
69
76
|
# To use a headless driver, like Poltergeist, update your Gemfile to use
|
70
77
|
# Poltergeist instead of Selenium and then declare the driver name in the
|
71
|
-
# +application_system_test_case.rb+ file. In this case you would leave out
|
72
|
-
# option because the driver is headless, but you can still use
|
78
|
+
# +application_system_test_case.rb+ file. In this case, you would leave out
|
79
|
+
# the +:using+ option because the driver is headless, but you can still use
|
73
80
|
# +:screen_size+ to change the size of the browser screen, also you can use
|
74
|
-
# +:options+ to pass options supported by the driver. Please
|
81
|
+
# +:options+ to pass options supported by the driver. Please refer to your
|
75
82
|
# driver documentation to learn about supported options.
|
76
83
|
#
|
77
84
|
# require "test_helper"
|
@@ -79,7 +86,7 @@ module ActionDispatch
|
|
79
86
|
#
|
80
87
|
# class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
81
88
|
# driven_by :poltergeist, screen_size: [1400, 1400], options:
|
82
|
-
#
|
89
|
+
# { js_errors: true }
|
83
90
|
# end
|
84
91
|
#
|
85
92
|
# Because <tt>ActionDispatch::SystemTestCase</tt> is a shim between Capybara
|
@@ -90,6 +97,7 @@ module ActionDispatch
|
|
90
97
|
include Capybara::Minitest::Assertions
|
91
98
|
include SystemTesting::TestHelpers::SetupAndTeardown
|
92
99
|
include SystemTesting::TestHelpers::ScreenshotHelper
|
100
|
+
include SystemTesting::TestHelpers::UndefMethods
|
93
101
|
|
94
102
|
def initialize(*) # :nodoc:
|
95
103
|
super
|
@@ -117,14 +125,22 @@ module ActionDispatch
|
|
117
125
|
#
|
118
126
|
# driven_by :poltergeist
|
119
127
|
#
|
128
|
+
# driven_by :selenium, screen_size: [800, 800]
|
129
|
+
#
|
130
|
+
# driven_by :selenium, using: :chrome
|
131
|
+
#
|
132
|
+
# driven_by :selenium, using: :headless_chrome
|
133
|
+
#
|
120
134
|
# driven_by :selenium, using: :firefox
|
121
135
|
#
|
122
|
-
# driven_by :selenium,
|
136
|
+
# driven_by :selenium, using: :headless_firefox
|
123
137
|
def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {})
|
124
138
|
self.driver = SystemTesting::Driver.new(driver, using: using, screen_size: screen_size, options: options)
|
125
139
|
end
|
126
140
|
|
127
141
|
driven_by :selenium
|
142
|
+
|
143
|
+
ActiveSupport.run_load_hooks(:action_dispatch_system_test_case, self)
|
128
144
|
end
|
129
145
|
|
130
146
|
SystemTestCase.start_application
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionDispatch
|
4
|
+
module SystemTesting
|
5
|
+
class Browser # :nodoc:
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(name)
|
9
|
+
@name = name
|
10
|
+
end
|
11
|
+
|
12
|
+
def type
|
13
|
+
case name
|
14
|
+
when :headless_chrome
|
15
|
+
:chrome
|
16
|
+
when :headless_firefox
|
17
|
+
:firefox
|
18
|
+
else
|
19
|
+
name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def options
|
24
|
+
case name
|
25
|
+
when :headless_chrome
|
26
|
+
headless_chrome_browser_options
|
27
|
+
when :headless_firefox
|
28
|
+
headless_firefox_browser_options
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def headless_chrome_browser_options
|
34
|
+
options = Selenium::WebDriver::Chrome::Options.new
|
35
|
+
options.args << "--headless"
|
36
|
+
options.args << "--disable-gpu" if Gem.win_platform?
|
37
|
+
|
38
|
+
options
|
39
|
+
end
|
40
|
+
|
41
|
+
def headless_firefox_browser_options
|
42
|
+
options = Selenium::WebDriver::Firefox::Options.new
|
43
|
+
options.args << "-headless"
|
44
|
+
|
45
|
+
options
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
4
|
module SystemTesting
|
3
5
|
class Driver # :nodoc:
|
4
6
|
def initialize(name, **options)
|
5
7
|
@name = name
|
6
|
-
@browser = options[:using]
|
8
|
+
@browser = Browser.new(options[:using])
|
7
9
|
@screen_size = options[:screen_size]
|
8
10
|
@options = options[:options]
|
9
11
|
end
|
@@ -29,8 +31,12 @@ module ActionDispatch
|
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
34
|
+
def browser_options
|
35
|
+
@options.merge(options: @browser.options).compact
|
36
|
+
end
|
37
|
+
|
32
38
|
def register_selenium(app)
|
33
|
-
Capybara::Selenium::Driver.new(app, { browser: @browser }.merge(
|
39
|
+
Capybara::Selenium::Driver.new(app, { browser: @browser.type }.merge(browser_options)).tap do |driver|
|
34
40
|
driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*@screen_size)
|
35
41
|
end
|
36
42
|
end
|
@@ -41,7 +47,7 @@ module ActionDispatch
|
|
41
47
|
|
42
48
|
def register_webkit(app)
|
43
49
|
Capybara::Webkit::Driver.new(app, Capybara::Webkit::Configuration.to_hash.merge(@options)).tap do |driver|
|
44
|
-
driver.
|
50
|
+
driver.resize_window_to(driver.current_window_handle, *@screen_size)
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionDispatch
|
4
4
|
module SystemTesting
|
@@ -10,31 +10,17 @@ module ActionDispatch
|
|
10
10
|
self.silence_puma = false
|
11
11
|
|
12
12
|
def run
|
13
|
-
register
|
14
13
|
setup
|
15
14
|
end
|
16
15
|
|
17
16
|
private
|
18
|
-
def register
|
19
|
-
Capybara.register_server :rails_puma do |app, port, host|
|
20
|
-
Rack::Handler::Puma.run(
|
21
|
-
app,
|
22
|
-
Port: port,
|
23
|
-
Threads: "0:1",
|
24
|
-
workers: 0,
|
25
|
-
daemon: false,
|
26
|
-
Silent: self.class.silence_puma
|
27
|
-
)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
17
|
def setup
|
32
18
|
set_server
|
33
19
|
set_port
|
34
20
|
end
|
35
21
|
|
36
22
|
def set_server
|
37
|
-
Capybara.server = :
|
23
|
+
Capybara.server = :puma, { Silent: self.class.silence_puma } if Capybara.server == Capybara.servers[:default]
|
38
24
|
end
|
39
25
|
|
40
26
|
def set_port
|