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.

Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +282 -362
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  5. data/lib/abstract_controller.rb +3 -0
  6. data/lib/abstract_controller/asset_paths.rb +2 -0
  7. data/lib/abstract_controller/base.rb +10 -2
  8. data/lib/abstract_controller/caching.rb +3 -2
  9. data/lib/abstract_controller/caching/fragments.rb +30 -7
  10. data/lib/abstract_controller/callbacks.rb +25 -3
  11. data/lib/abstract_controller/collector.rb +2 -0
  12. data/lib/abstract_controller/error.rb +2 -0
  13. data/lib/abstract_controller/helpers.rb +4 -5
  14. data/lib/abstract_controller/logger.rb +2 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  16. data/lib/abstract_controller/rendering.rb +9 -16
  17. data/lib/abstract_controller/translation.rb +2 -0
  18. data/lib/abstract_controller/url_for.rb +2 -0
  19. data/lib/action_controller.rb +3 -0
  20. data/lib/action_controller/api.rb +2 -0
  21. data/lib/action_controller/api/api_rendering.rb +2 -0
  22. data/lib/action_controller/base.rb +3 -0
  23. data/lib/action_controller/caching.rb +2 -0
  24. data/lib/action_controller/form_builder.rb +2 -0
  25. data/lib/action_controller/log_subscriber.rb +5 -3
  26. data/lib/action_controller/metal.rb +13 -14
  27. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  28. data/lib/action_controller/metal/conditional_get.rb +4 -3
  29. data/lib/action_controller/metal/content_security_policy.rb +52 -0
  30. data/lib/action_controller/metal/cookies.rb +2 -0
  31. data/lib/action_controller/metal/data_streaming.rb +7 -5
  32. data/lib/action_controller/metal/etag_with_flash.rb +2 -0
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +3 -2
  34. data/lib/action_controller/metal/exceptions.rb +2 -3
  35. data/lib/action_controller/metal/flash.rb +3 -2
  36. data/lib/action_controller/metal/force_ssl.rb +4 -2
  37. data/lib/action_controller/metal/head.rb +2 -0
  38. data/lib/action_controller/metal/helpers.rb +4 -3
  39. data/lib/action_controller/metal/http_authentication.rb +8 -9
  40. data/lib/action_controller/metal/implicit_render.rb +2 -0
  41. data/lib/action_controller/metal/instrumentation.rb +4 -6
  42. data/lib/action_controller/metal/live.rb +3 -1
  43. data/lib/action_controller/metal/mime_responds.rb +3 -1
  44. data/lib/action_controller/metal/parameter_encoding.rb +2 -0
  45. data/lib/action_controller/metal/params_wrapper.rb +14 -10
  46. data/lib/action_controller/metal/redirecting.rb +22 -11
  47. data/lib/action_controller/metal/renderers.rb +4 -3
  48. data/lib/action_controller/metal/rendering.rb +2 -2
  49. data/lib/action_controller/metal/request_forgery_protection.rb +62 -10
  50. data/lib/action_controller/metal/rescue.rb +5 -3
  51. data/lib/action_controller/metal/streaming.rb +3 -1
  52. data/lib/action_controller/metal/strong_parameters.rb +36 -25
  53. data/lib/action_controller/metal/testing.rb +2 -6
  54. data/lib/action_controller/metal/url_for.rb +2 -0
  55. data/lib/action_controller/railtie.rb +16 -4
  56. data/lib/action_controller/railties/helpers.rb +2 -0
  57. data/lib/action_controller/renderer.rb +2 -0
  58. data/lib/action_controller/template_assertions.rb +2 -0
  59. data/lib/action_controller/test_case.rb +16 -10
  60. data/lib/action_dispatch.rb +9 -5
  61. data/lib/action_dispatch/http/cache.rb +22 -14
  62. data/lib/action_dispatch/http/content_security_policy.rb +272 -0
  63. data/lib/action_dispatch/http/filter_parameters.rb +4 -2
  64. data/lib/action_dispatch/http/filter_redirect.rb +2 -0
  65. data/lib/action_dispatch/http/headers.rb +2 -0
  66. data/lib/action_dispatch/http/mime_negotiation.rb +4 -8
  67. data/lib/action_dispatch/http/mime_type.rb +15 -13
  68. data/lib/action_dispatch/http/mime_types.rb +17 -2
  69. data/lib/action_dispatch/http/parameter_filter.rb +2 -0
  70. data/lib/action_dispatch/http/parameters.rb +6 -9
  71. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  72. data/lib/action_dispatch/http/request.rb +36 -16
  73. data/lib/action_dispatch/http/response.rb +11 -9
  74. data/lib/action_dispatch/http/upload.rb +2 -0
  75. data/lib/action_dispatch/http/url.rb +5 -6
  76. data/lib/action_dispatch/journey.rb +2 -0
  77. data/lib/action_dispatch/journey/formatter.rb +4 -2
  78. data/lib/action_dispatch/journey/gtg/builder.rb +2 -0
  79. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -8
  80. data/lib/action_dispatch/journey/gtg/transition_table.rb +3 -2
  81. data/lib/action_dispatch/journey/nfa/builder.rb +2 -0
  82. data/lib/action_dispatch/journey/nfa/dot.rb +12 -10
  83. data/lib/action_dispatch/journey/nfa/simulator.rb +2 -0
  84. data/lib/action_dispatch/journey/nfa/transition_table.rb +2 -0
  85. data/lib/action_dispatch/journey/nodes/node.rb +2 -0
  86. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  87. data/lib/action_dispatch/journey/path/pattern.rb +4 -1
  88. data/lib/action_dispatch/journey/route.rb +15 -6
  89. data/lib/action_dispatch/journey/router.rb +3 -1
  90. data/lib/action_dispatch/journey/router/utils.rb +14 -7
  91. data/lib/action_dispatch/journey/routes.rb +3 -1
  92. data/lib/action_dispatch/journey/scanner.rb +1 -0
  93. data/lib/action_dispatch/journey/visitors.rb +5 -3
  94. data/lib/action_dispatch/middleware/callbacks.rb +2 -0
  95. data/lib/action_dispatch/middleware/cookies.rb +148 -91
  96. data/lib/action_dispatch/middleware/debug_exceptions.rb +4 -2
  97. data/lib/action_dispatch/middleware/debug_locks.rb +9 -7
  98. data/lib/action_dispatch/middleware/exception_wrapper.rb +5 -6
  99. data/lib/action_dispatch/middleware/executor.rb +2 -0
  100. data/lib/action_dispatch/middleware/flash.rb +4 -2
  101. data/lib/action_dispatch/middleware/public_exceptions.rb +6 -4
  102. data/lib/action_dispatch/middleware/reloader.rb +2 -0
  103. data/lib/action_dispatch/middleware/remote_ip.rb +7 -5
  104. data/lib/action_dispatch/middleware/request_id.rb +3 -1
  105. data/lib/action_dispatch/middleware/session/abstract_store.rb +17 -1
  106. data/lib/action_dispatch/middleware/session/cache_store.rb +13 -6
  107. data/lib/action_dispatch/middleware/session/cookie_store.rb +31 -32
  108. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -0
  109. data/lib/action_dispatch/middleware/show_exceptions.rb +3 -1
  110. data/lib/action_dispatch/middleware/ssl.rb +44 -38
  111. data/lib/action_dispatch/middleware/stack.rb +4 -2
  112. data/lib/action_dispatch/middleware/static.rb +14 -12
  113. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
  114. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
  115. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
  116. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +6 -2
  117. data/lib/action_dispatch/railtie.rb +11 -1
  118. data/lib/action_dispatch/request/session.rb +16 -5
  119. data/lib/action_dispatch/request/utils.rb +6 -4
  120. data/lib/action_dispatch/routing.rb +3 -1
  121. data/lib/action_dispatch/routing/endpoint.rb +9 -2
  122. data/lib/action_dispatch/routing/inspector.rb +6 -4
  123. data/lib/action_dispatch/routing/mapper.rb +64 -52
  124. data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
  125. data/lib/action_dispatch/routing/redirection.rb +7 -5
  126. data/lib/action_dispatch/routing/route_set.rb +29 -24
  127. data/lib/action_dispatch/routing/routes_proxy.rb +5 -2
  128. data/lib/action_dispatch/routing/url_for.rb +25 -5
  129. data/lib/action_dispatch/system_test_case.rb +22 -6
  130. data/lib/action_dispatch/system_testing/browser.rb +49 -0
  131. data/lib/action_dispatch/system_testing/driver.rb +9 -3
  132. data/lib/action_dispatch/system_testing/server.rb +2 -16
  133. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +12 -14
  134. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +8 -2
  135. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
  136. data/lib/action_dispatch/testing/assertion_response.rb +2 -0
  137. data/lib/action_dispatch/testing/assertions.rb +2 -0
  138. data/lib/action_dispatch/testing/assertions/response.rb +4 -2
  139. data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
  140. data/lib/action_dispatch/testing/integration.rb +24 -21
  141. data/lib/action_dispatch/testing/request_encoder.rb +3 -1
  142. data/lib/action_dispatch/testing/test_process.rb +2 -0
  143. data/lib/action_dispatch/testing/test_request.rb +3 -1
  144. data/lib/action_dispatch/testing/test_response.rb +23 -3
  145. data/lib/action_pack.rb +3 -1
  146. data/lib/action_pack/gem_version.rb +5 -3
  147. data/lib/action_pack/version.rb +2 -0
  148. metadata +23 -11
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionDispatch
2
4
  module Routing
3
5
  # Polymorphic URL helpers are methods for smart resolution to a named route call when
@@ -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
- # `/stories`, `/stories?foo=bar`, etc all redirect to `/posts`.
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 url is prefixed with 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 url which need
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 `path` option in the last example.
177
- # `/stories`, `/stories?foo=bar`, redirect to `/posts` and `/posts?foo=bar` respectively.
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(:"#{name}_path") do |*args|
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(:"#{name}_url") do |*args|
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 url helper allowing ordered parameters to be associated
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
- singleton_class.send(:redefine_method, :_routes) { routes }
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 5.2.
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 5.2.
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
- raise ActionController::RoutingError, "No route matches #{path.inspect}"
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
- def respond_to_missing?(method, include_private = false)
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
- send(method, *args)
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 `default_url_options`. Application logic should not
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 url based on the options provided, default_url_options and the
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 url is returned. Defaults to +false+.
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 `GET /users/1`:
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
- def route_for(name, *args) # :nodoc:
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 are easy. Let's say you want to use
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 the +:using+
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 refeer to your
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
- # { js_errors: true }
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, screen_size: [800, 800]
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(@options)).tap do |driver|
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.resize_window(*@screen_size)
50
+ driver.resize_window_to(driver.current_window_handle, *@screen_size)
45
51
  end
46
52
  end
47
53
 
@@ -1,4 +1,4 @@
1
- require "rack/handler/puma"
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 = :rails_puma
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