actionpack 6.0.3 → 6.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +246 -217
  3. data/MIT-LICENSE +1 -1
  4. data/lib/abstract_controller.rb +1 -0
  5. data/lib/abstract_controller/base.rb +35 -2
  6. data/lib/abstract_controller/callbacks.rb +2 -2
  7. data/lib/abstract_controller/helpers.rb +105 -90
  8. data/lib/abstract_controller/rendering.rb +9 -9
  9. data/lib/abstract_controller/translation.rb +8 -2
  10. data/lib/action_controller.rb +2 -3
  11. data/lib/action_controller/api.rb +2 -2
  12. data/lib/action_controller/base.rb +4 -2
  13. data/lib/action_controller/caching.rb +0 -1
  14. data/lib/action_controller/log_subscriber.rb +3 -3
  15. data/lib/action_controller/metal.rb +2 -2
  16. data/lib/action_controller/metal/conditional_get.rb +10 -2
  17. data/lib/action_controller/metal/content_security_policy.rb +1 -1
  18. data/lib/action_controller/metal/data_streaming.rb +1 -1
  19. data/lib/action_controller/metal/etag_with_template_digest.rb +2 -4
  20. data/lib/action_controller/metal/exceptions.rb +33 -0
  21. data/lib/action_controller/metal/feature_policy.rb +46 -0
  22. data/lib/action_controller/metal/head.rb +7 -4
  23. data/lib/action_controller/metal/helpers.rb +11 -1
  24. data/lib/action_controller/metal/http_authentication.rb +4 -2
  25. data/lib/action_controller/metal/implicit_render.rb +1 -1
  26. data/lib/action_controller/metal/instrumentation.rb +11 -9
  27. data/lib/action_controller/metal/live.rb +1 -1
  28. data/lib/action_controller/metal/logging.rb +20 -0
  29. data/lib/action_controller/metal/mime_responds.rb +6 -2
  30. data/lib/action_controller/metal/parameter_encoding.rb +35 -4
  31. data/lib/action_controller/metal/params_wrapper.rb +14 -8
  32. data/lib/action_controller/metal/redirecting.rb +1 -1
  33. data/lib/action_controller/metal/rendering.rb +6 -0
  34. data/lib/action_controller/metal/request_forgery_protection.rb +74 -30
  35. data/lib/action_controller/metal/rescue.rb +1 -1
  36. data/lib/action_controller/metal/strong_parameters.rb +107 -15
  37. data/lib/action_controller/renderer.rb +24 -13
  38. data/lib/action_controller/test_case.rb +62 -56
  39. data/lib/action_dispatch.rb +3 -2
  40. data/lib/action_dispatch/http/cache.rb +12 -10
  41. data/lib/action_dispatch/http/content_disposition.rb +2 -2
  42. data/lib/action_dispatch/http/content_security_policy.rb +5 -1
  43. data/lib/action_dispatch/http/feature_policy.rb +168 -0
  44. data/lib/action_dispatch/http/filter_parameters.rb +1 -1
  45. data/lib/action_dispatch/http/filter_redirect.rb +1 -1
  46. data/lib/action_dispatch/http/headers.rb +3 -2
  47. data/lib/action_dispatch/http/mime_negotiation.rb +20 -8
  48. data/lib/action_dispatch/http/mime_type.rb +28 -15
  49. data/lib/action_dispatch/http/parameters.rb +1 -19
  50. data/lib/action_dispatch/http/request.rb +26 -8
  51. data/lib/action_dispatch/http/response.rb +17 -16
  52. data/lib/action_dispatch/http/url.rb +3 -2
  53. data/lib/action_dispatch/journey.rb +0 -2
  54. data/lib/action_dispatch/journey/formatter.rb +53 -28
  55. data/lib/action_dispatch/journey/gtg/builder.rb +22 -36
  56. data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
  57. data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -4
  58. data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
  59. data/lib/action_dispatch/journey/nodes/node.rb +4 -3
  60. data/lib/action_dispatch/journey/parser.rb +13 -13
  61. data/lib/action_dispatch/journey/parser.y +1 -1
  62. data/lib/action_dispatch/journey/path/pattern.rb +13 -18
  63. data/lib/action_dispatch/journey/route.rb +7 -18
  64. data/lib/action_dispatch/journey/router.rb +26 -30
  65. data/lib/action_dispatch/journey/router/utils.rb +6 -4
  66. data/lib/action_dispatch/middleware/actionable_exceptions.rb +9 -2
  67. data/lib/action_dispatch/middleware/cookies.rb +74 -33
  68. data/lib/action_dispatch/middleware/debug_exceptions.rb +10 -17
  69. data/lib/action_dispatch/middleware/debug_view.rb +1 -1
  70. data/lib/action_dispatch/middleware/exception_wrapper.rb +29 -17
  71. data/lib/action_dispatch/middleware/host_authorization.rb +23 -3
  72. data/lib/action_dispatch/middleware/public_exceptions.rb +1 -1
  73. data/lib/action_dispatch/middleware/remote_ip.rb +5 -4
  74. data/lib/action_dispatch/middleware/request_id.rb +4 -5
  75. data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -2
  76. data/lib/action_dispatch/middleware/session/cookie_store.rb +2 -2
  77. data/lib/action_dispatch/middleware/ssl.rb +9 -6
  78. data/lib/action_dispatch/middleware/stack.rb +18 -0
  79. data/lib/action_dispatch/middleware/static.rb +154 -93
  80. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +18 -0
  81. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +2 -5
  82. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +2 -2
  83. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +2 -2
  84. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +88 -8
  85. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  86. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +12 -1
  87. data/lib/action_dispatch/railtie.rb +3 -2
  88. data/lib/action_dispatch/request/session.rb +2 -8
  89. data/lib/action_dispatch/request/utils.rb +26 -2
  90. data/lib/action_dispatch/routing/inspector.rb +8 -7
  91. data/lib/action_dispatch/routing/mapper.rb +102 -71
  92. data/lib/action_dispatch/routing/polymorphic_routes.rb +12 -11
  93. data/lib/action_dispatch/routing/redirection.rb +3 -3
  94. data/lib/action_dispatch/routing/route_set.rb +49 -41
  95. data/lib/action_dispatch/routing/url_for.rb +1 -0
  96. data/lib/action_dispatch/system_test_case.rb +29 -24
  97. data/lib/action_dispatch/system_testing/browser.rb +33 -27
  98. data/lib/action_dispatch/system_testing/driver.rb +6 -7
  99. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +47 -6
  100. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +4 -7
  101. data/lib/action_dispatch/testing/assertions.rb +1 -1
  102. data/lib/action_dispatch/testing/assertions/response.rb +2 -4
  103. data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
  104. data/lib/action_dispatch/testing/integration.rb +38 -27
  105. data/lib/action_dispatch/testing/test_process.rb +29 -4
  106. data/lib/action_dispatch/testing/test_request.rb +3 -3
  107. data/lib/action_pack.rb +1 -1
  108. data/lib/action_pack/gem_version.rb +3 -3
  109. metadata +20 -21
  110. data/lib/action_controller/metal/force_ssl.rb +0 -58
  111. data/lib/action_dispatch/http/parameter_filter.rb +0 -12
  112. data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
  113. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
  114. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -119
@@ -145,6 +145,7 @@ module ActionDispatch
145
145
 
146
146
  %w(edit new).each do |action|
147
147
  module_eval <<-EOT, __FILE__, __LINE__ + 1
148
+ # frozen_string_literal: true
148
149
  def #{action}_polymorphic_url(record_or_hash, options = {})
149
150
  polymorphic_url_for_action("#{action}", record_or_hash, options)
150
151
  end
@@ -173,15 +174,15 @@ module ActionDispatch
173
174
  end
174
175
 
175
176
  class HelperMethodBuilder # :nodoc:
176
- CACHE = { "path" => {}, "url" => {} }
177
+ CACHE = { path: {}, url: {} }
177
178
 
178
179
  def self.get(action, type)
179
- type = type.to_s
180
+ type = type.to_sym
180
181
  CACHE[type].fetch(action) { build action, type }
181
182
  end
182
183
 
183
- def self.url; CACHE["url"][nil]; end
184
- def self.path; CACHE["path"][nil]; end
184
+ def self.url; CACHE[:url][nil]; end
185
+ def self.path; CACHE[:path][nil]; end
185
186
 
186
187
  def self.build(action, type)
187
188
  prefix = action ? "#{action}_" : ""
@@ -227,9 +228,9 @@ module ActionDispatch
227
228
  end
228
229
 
229
230
  if options.empty?
230
- recipient.send(method, *args)
231
+ recipient.public_send(method, *args)
231
232
  else
232
- recipient.send(method, *args, options)
233
+ recipient.public_send(method, *args, options)
233
234
  end
234
235
  end
235
236
 
@@ -246,7 +247,7 @@ module ActionDispatch
246
247
  end
247
248
 
248
249
  def handle_string_call(target, str)
249
- target.send get_method_for_string str
250
+ target.public_send get_method_for_string str
250
251
  end
251
252
 
252
253
  def handle_class(klass)
@@ -254,7 +255,7 @@ module ActionDispatch
254
255
  end
255
256
 
256
257
  def handle_class_call(target, klass)
257
- target.send get_method_for_class klass
258
+ target.public_send get_method_for_class klass
258
259
  end
259
260
 
260
261
  def handle_model(record)
@@ -276,7 +277,7 @@ module ActionDispatch
276
277
  mapping.call(target, [record], suffix == "path")
277
278
  else
278
279
  method, args = handle_model(record)
279
- target.send(method, *args)
280
+ target.public_send(method, *args)
280
281
  end
281
282
  end
282
283
 
@@ -340,8 +341,8 @@ module ActionDispatch
340
341
  end
341
342
 
342
343
  [nil, "new", "edit"].each do |action|
343
- CACHE["url"][action] = build action, "url"
344
- CACHE["path"][action] = build action, "path"
344
+ CACHE[:url][action] = build action, "url"
345
+ CACHE[:path][action] = build action, "path"
345
346
  end
346
347
  end
347
348
  end
@@ -65,15 +65,15 @@ module ActionDispatch
65
65
  end
66
66
 
67
67
  def escape(params)
68
- Hash[params.map { |k, v| [k, Rack::Utils.escape(v)] }]
68
+ params.transform_values { |v| Rack::Utils.escape(v) }
69
69
  end
70
70
 
71
71
  def escape_fragment(params)
72
- Hash[params.map { |k, v| [k, Journey::Router::Utils.escape_fragment(v)] }]
72
+ params.transform_values { |v| Journey::Router::Utils.escape_fragment(v) }
73
73
  end
74
74
 
75
75
  def escape_path(params)
76
- Hash[params.map { |k, v| [k, Journey::Router::Utils.escape_path(v)] }]
76
+ params.transform_values { |v| Journey::Router::Utils.escape_path(v) }
77
77
  end
78
78
  end
79
79
 
@@ -110,8 +110,10 @@ module ActionDispatch
110
110
  @url_helpers_module.undef_method url_name
111
111
  end
112
112
  routes[key] = route
113
- define_url_helper @path_helpers_module, route, path_name, route.defaults, name, PATH
114
- define_url_helper @url_helpers_module, route, url_name, route.defaults, name, UNKNOWN
113
+
114
+ helper = UrlHelper.create(route, route.defaults, name)
115
+ define_url_helper @path_helpers_module, path_name, helper, PATH
116
+ define_url_helper @url_helpers_module, url_name, helper, UNKNOWN
115
117
 
116
118
  @path_helpers << path_name
117
119
  @url_helpers << url_name
@@ -169,30 +171,30 @@ module ActionDispatch
169
171
  end
170
172
 
171
173
  class UrlHelper
172
- def self.create(route, options, route_name, url_strategy)
174
+ def self.create(route, options, route_name)
173
175
  if optimize_helper?(route)
174
- OptimizedUrlHelper.new(route, options, route_name, url_strategy)
176
+ OptimizedUrlHelper.new(route, options, route_name)
175
177
  else
176
- new route, options, route_name, url_strategy
178
+ new(route, options, route_name)
177
179
  end
178
180
  end
179
181
 
180
182
  def self.optimize_helper?(route)
181
- !route.glob? && route.path.requirements.empty?
183
+ route.path.requirements.empty? && !route.glob?
182
184
  end
183
185
 
184
- attr_reader :url_strategy, :route_name
186
+ attr_reader :route_name
185
187
 
186
188
  class OptimizedUrlHelper < UrlHelper
187
189
  attr_reader :arg_size
188
190
 
189
- def initialize(route, options, route_name, url_strategy)
191
+ def initialize(route, options, route_name)
190
192
  super
191
193
  @required_parts = @route.required_parts
192
194
  @arg_size = @required_parts.size
193
195
  end
194
196
 
195
- def call(t, args, inner_options)
197
+ def call(t, method_name, args, inner_options, url_strategy)
196
198
  if args.size == arg_size && !inner_options && optimize_routes_generation?(t)
197
199
  options = t.url_options.merge @options
198
200
  options[:path] = optimized_helper(args)
@@ -249,15 +251,14 @@ module ActionDispatch
249
251
  end
250
252
  end
251
253
 
252
- def initialize(route, options, route_name, url_strategy)
254
+ def initialize(route, options, route_name)
253
255
  @options = options
254
256
  @segment_keys = route.segment_keys.uniq
255
257
  @route = route
256
- @url_strategy = url_strategy
257
258
  @route_name = route_name
258
259
  end
259
260
 
260
- def call(t, args, inner_options)
261
+ def call(t, method_name, args, inner_options, url_strategy)
261
262
  controller_options = t.url_options
262
263
  options = controller_options.merge @options
263
264
  hash = handle_positional_args(controller_options,
@@ -266,7 +267,7 @@ module ActionDispatch
266
267
  options,
267
268
  @segment_keys)
268
269
 
269
- t._routes.url_for(hash, route_name, url_strategy)
270
+ t._routes.url_for(hash, route_name, url_strategy, method_name)
270
271
  end
271
272
 
272
273
  def handle_positional_args(controller_options, inner_options, args, result, path_params)
@@ -312,8 +313,7 @@ module ActionDispatch
312
313
  #
313
314
  # foo_url(bar, baz, bang, sort_by: 'baz')
314
315
  #
315
- def define_url_helper(mod, route, name, opts, route_key, url_strategy)
316
- helper = UrlHelper.create(route, opts, route_key, url_strategy)
316
+ def define_url_helper(mod, name, helper, url_strategy)
317
317
  mod.define_method(name) do |*args|
318
318
  last = args.last
319
319
  options = \
@@ -323,7 +323,7 @@ module ActionDispatch
323
323
  when ActionController::Parameters
324
324
  args.pop.to_h
325
325
  end
326
- helper.call self, args, options
326
+ helper.call(self, name, args, options, url_strategy)
327
327
  end
328
328
  end
329
329
  end
@@ -334,7 +334,7 @@ module ActionDispatch
334
334
 
335
335
  attr_accessor :formatter, :set, :named_routes, :default_scope, :router
336
336
  attr_accessor :disable_clear_and_finalize, :resources_path_names
337
- attr_accessor :default_url_options
337
+ attr_accessor :default_url_options, :draw_paths
338
338
  attr_reader :env_key, :polymorphic_mappings
339
339
 
340
340
  alias :routes :set
@@ -366,6 +366,7 @@ module ActionDispatch
366
366
  self.named_routes = NamedRouteCollection.new
367
367
  self.resources_path_names = self.class.default_resources_path_names
368
368
  self.default_url_options = {}
369
+ self.draw_paths = []
369
370
 
370
371
  @config = config
371
372
  @append = []
@@ -476,6 +477,14 @@ module ActionDispatch
476
477
  end
477
478
 
478
479
  def url_helpers(supports_path = true)
480
+ if supports_path
481
+ @url_helpers_with_paths ||= generate_url_helpers(true)
482
+ else
483
+ @url_helpers_without_paths ||= generate_url_helpers(false)
484
+ end
485
+ end
486
+
487
+ def generate_url_helpers(supports_path)
479
488
  routes = self
480
489
 
481
490
  Module.new do
@@ -588,14 +597,14 @@ module ActionDispatch
588
597
  if route.segment_keys.include?(:controller)
589
598
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
590
599
  Using a dynamic :controller segment in a route is deprecated and
591
- will be removed in Rails 6.1.
600
+ will be removed in Rails 6.2.
592
601
  MSG
593
602
  end
594
603
 
595
604
  if route.segment_keys.include?(:action)
596
605
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
597
606
  Using a dynamic :action segment in a route is deprecated and
598
- will be removed in Rails 6.1.
607
+ will be removed in Rails 6.2.
599
608
  MSG
600
609
  end
601
610
 
@@ -641,14 +650,6 @@ module ActionDispatch
641
650
  end
642
651
 
643
652
  class Generator
644
- PARAMETERIZE = lambda do |name, value|
645
- if name == :controller
646
- value
647
- else
648
- value.to_param
649
- end
650
- end
651
-
652
653
  attr_reader :options, :recall, :set, :named_route
653
654
 
654
655
  def initialize(named_route, options, recall, set)
@@ -732,10 +733,10 @@ module ActionDispatch
732
733
  end
733
734
  end
734
735
 
735
- # Generates a path from routes, returns [path, params].
736
- # If no route is generated the formatter will raise ActionController::UrlGenerationError
736
+ # Generates a path from routes, returns a RouteWithParams or MissingRoute.
737
+ # MissingRoute will raise ActionController::UrlGenerationError.
737
738
  def generate
738
- @set.formatter.generate(named_route, options, recall, PARAMETERIZE)
739
+ @set.formatter.generate(named_route, options, recall)
739
740
  end
740
741
 
741
742
  def different_controller?
@@ -760,13 +761,18 @@ module ActionDispatch
760
761
  end
761
762
 
762
763
  def generate_extras(options, recall = {})
763
- route_key = options.delete :use_route
764
- path, params = generate(route_key, options, recall)
765
- return path, params.keys
764
+ if recall
765
+ options = options.merge(_recall: recall)
766
+ end
767
+
768
+ route_name = options.delete :use_route
769
+ generator = generate(route_name, options, recall)
770
+ path_info = path_for(options, route_name, [])
771
+ [URI(path_info).path, generator.params.except(:_recall).keys]
766
772
  end
767
773
 
768
- def generate(route_key, options, recall = {})
769
- Generator.new(route_key, options, recall, self).generate
774
+ def generate(route_name, options, recall = {}, method_name = nil)
775
+ Generator.new(route_name, options, recall, self).generate
770
776
  end
771
777
  private :generate
772
778
 
@@ -786,12 +792,12 @@ module ActionDispatch
786
792
  options.delete(:relative_url_root) || relative_url_root
787
793
  end
788
794
 
789
- def path_for(options, route_name = nil)
790
- url_for(options, route_name, PATH)
795
+ def path_for(options, route_name = nil, reserved = RESERVED_OPTIONS)
796
+ url_for(options, route_name, PATH, nil, reserved)
791
797
  end
792
798
 
793
799
  # The +options+ argument must be a hash whose keys are *symbols*.
794
- def url_for(options, route_name = nil, url_strategy = UNKNOWN)
800
+ def url_for(options, route_name = nil, url_strategy = UNKNOWN, method_name = nil, reserved = RESERVED_OPTIONS)
795
801
  options = default_url_options.merge options
796
802
 
797
803
  user = password = nil
@@ -811,9 +817,11 @@ module ActionDispatch
811
817
  end
812
818
 
813
819
  path_options = options.dup
814
- RESERVED_OPTIONS.each { |ro| path_options.delete ro }
820
+ reserved.each { |ro| path_options.delete ro }
815
821
 
816
- path, params = generate(route_name, path_options, recall)
822
+ route_with_params = generate(route_name, path_options, recall)
823
+ path = route_with_params.path(method_name)
824
+ params = route_with_params.params
817
825
 
818
826
  if options.key? :params
819
827
  params.merge! options[:params]
@@ -855,7 +863,7 @@ module ActionDispatch
855
863
  params.each do |key, value|
856
864
  if value.is_a?(String)
857
865
  value = value.dup.force_encoding(Encoding::BINARY)
858
- params[key] = URI.parser.unescape(value)
866
+ params[key] = URI::DEFAULT_PARSER.unescape(value)
859
867
  end
860
868
  end
861
869
  req.path_parameters = params
@@ -107,6 +107,7 @@ module ActionDispatch
107
107
  @_routes = nil
108
108
  super
109
109
  end
110
+ ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
110
111
 
111
112
  # Hook overridden in controller to add request information
112
113
  # with +default_url_options+. Application logic should not
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- gem "capybara", ">= 2.15"
3
+ gem "capybara", ">= 3.26"
4
4
 
5
5
  require "capybara/dsl"
6
6
  require "capybara/minitest"
7
- require "selenium/webdriver"
8
7
  require "action_controller"
9
8
  require "action_dispatch/system_testing/driver"
10
9
  require "action_dispatch/system_testing/browser"
@@ -27,7 +26,7 @@ module ActionDispatch
27
26
  #
28
27
  # Here is an example system test:
29
28
  #
30
- # require 'application_system_test_case'
29
+ # require "application_system_test_case"
31
30
  #
32
31
  # class Users::CreateTest < ApplicationSystemTestCase
33
32
  # test "adding a new user" do
@@ -120,18 +119,6 @@ module ActionDispatch
120
119
  super
121
120
  self.class.driven_by(:selenium) unless self.class.driver?
122
121
  self.class.driver.use
123
- @proxy_route = if ActionDispatch.test_app
124
- Class.new do
125
- include ActionDispatch.test_app.routes.url_helpers
126
- include ActionDispatch.test_app.routes.mounted_helpers
127
-
128
- def url_options
129
- default_url_options.merge(host: Capybara.app_host)
130
- end
131
- end.new
132
- else
133
- nil
134
- end
135
122
  end
136
123
 
137
124
  def self.start_application # :nodoc:
@@ -170,16 +157,34 @@ module ActionDispatch
170
157
  self.driver = SystemTesting::Driver.new(driver, **driver_options, &capabilities)
171
158
  end
172
159
 
173
- def method_missing(method, *args, &block)
174
- if @proxy_route.respond_to?(method)
175
- @proxy_route.send(method, *args, &block)
176
- else
177
- super
160
+ private
161
+ def url_helpers
162
+ @url_helpers ||=
163
+ if ActionDispatch.test_app
164
+ Class.new do
165
+ include ActionDispatch.test_app.routes.url_helpers
166
+ include ActionDispatch.test_app.routes.mounted_helpers
167
+
168
+ def url_options
169
+ default_url_options.reverse_merge(host: Capybara.app_host || Capybara.current_session.server_url)
170
+ end
171
+ end.new
172
+ end
178
173
  end
179
- end
180
174
 
181
- ActiveSupport.run_load_hooks(:action_dispatch_system_test_case, self)
182
- end
175
+ def method_missing(name, *args, &block)
176
+ if url_helpers.respond_to?(name)
177
+ url_helpers.public_send(name, *args, &block)
178
+ else
179
+ super
180
+ end
181
+ end
183
182
 
184
- SystemTestCase.start_application
183
+ def respond_to_missing?(name, include_private = false)
184
+ url_helpers.respond_to?(name)
185
+ end
186
+ end
185
187
  end
188
+
189
+ ActiveSupport.run_load_hooks :action_dispatch_system_test_case, ActionDispatch::SystemTestCase
190
+ ActionDispatch::SystemTestCase.start_application
@@ -3,10 +3,11 @@
3
3
  module ActionDispatch
4
4
  module SystemTesting
5
5
  class Browser # :nodoc:
6
- attr_reader :name
6
+ attr_reader :name, :options
7
7
 
8
8
  def initialize(name)
9
9
  @name = name
10
+ set_default_options
10
11
  end
11
12
 
12
13
  def type
@@ -20,23 +21,9 @@ module ActionDispatch
20
21
  end
21
22
  end
22
23
 
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
- def capabilities
33
- @option ||=
34
- case type
35
- when :chrome
36
- ::Selenium::WebDriver::Chrome::Options.new
37
- when :firefox
38
- ::Selenium::WebDriver::Firefox::Options.new
39
- end
24
+ def configure
25
+ initialize_options
26
+ yield options if block_given? && options
40
27
  end
41
28
 
42
29
  # driver_path can be configured as a proc. The webdrivers gem uses this
@@ -47,14 +34,14 @@ module ActionDispatch
47
34
  case type
48
35
  when :chrome
49
36
  if ::Selenium::WebDriver::Service.respond_to? :driver_path=
50
- ::Selenium::WebDriver::Chrome::Service.driver_path.try(:call)
37
+ ::Selenium::WebDriver::Chrome::Service.driver_path&.call
51
38
  else
52
39
  # Selenium <= v3.141.0
53
40
  ::Selenium::WebDriver::Chrome.driver_path
54
41
  end
55
42
  when :firefox
56
43
  if ::Selenium::WebDriver::Service.respond_to? :driver_path=
57
- ::Selenium::WebDriver::Firefox::Service.driver_path.try(:call)
44
+ ::Selenium::WebDriver::Firefox::Service.driver_path&.call
58
45
  else
59
46
  # Selenium <= v3.141.0
60
47
  ::Selenium::WebDriver::Firefox.driver_path
@@ -63,17 +50,36 @@ module ActionDispatch
63
50
  end
64
51
 
65
52
  private
66
- def headless_chrome_browser_options
67
- capabilities.args << "--headless"
68
- capabilities.args << "--disable-gpu" if Gem.win_platform?
53
+ def initialize_options
54
+ @options ||=
55
+ case type
56
+ when :chrome
57
+ ::Selenium::WebDriver::Chrome::Options.new
58
+ when :firefox
59
+ ::Selenium::WebDriver::Firefox::Options.new
60
+ end
61
+ end
69
62
 
70
- capabilities
63
+ def set_default_options
64
+ case name
65
+ when :headless_chrome
66
+ set_headless_chrome_browser_options
67
+ when :headless_firefox
68
+ set_headless_firefox_browser_options
69
+ end
71
70
  end
72
71
 
73
- def headless_firefox_browser_options
74
- capabilities.args << "-headless"
72
+ def set_headless_chrome_browser_options
73
+ configure do |capabilities|
74
+ capabilities.args << "--headless"
75
+ capabilities.args << "--disable-gpu" if Gem.win_platform?
76
+ end
77
+ end
75
78
 
76
- capabilities
79
+ def set_headless_firefox_browser_options
80
+ configure do |capabilities|
81
+ capabilities.args << "-headless"
82
+ end
77
83
  end
78
84
  end
79
85
  end