actionpack 6.0.0.beta1 → 6.0.0.beta2

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -10
  3. data/lib/abstract_controller/caching/fragments.rb +0 -1
  4. data/lib/abstract_controller/translation.rb +1 -0
  5. data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
  6. data/lib/action_controller/metal/etag_with_template_digest.rb +1 -1
  7. data/lib/action_controller/metal/exceptions.rb +1 -1
  8. data/lib/action_controller/metal/force_ssl.rb +1 -2
  9. data/lib/action_controller/metal/helpers.rb +1 -1
  10. data/lib/action_controller/metal/implicit_render.rb +2 -2
  11. data/lib/action_controller/metal/live.rb +1 -1
  12. data/lib/action_controller/metal/redirecting.rb +6 -27
  13. data/lib/action_controller/metal/strong_parameters.rb +1 -1
  14. data/lib/action_dispatch/http/upload.rb +4 -1
  15. data/lib/action_dispatch/journey/path/pattern.rb +1 -1
  16. data/lib/action_dispatch/middleware/cookies.rb +2 -7
  17. data/lib/action_dispatch/middleware/debug_view.rb +7 -1
  18. data/lib/action_dispatch/middleware/exception_wrapper.rb +14 -10
  19. data/lib/action_dispatch/middleware/host_authorization.rb +2 -2
  20. data/lib/action_dispatch/middleware/show_exceptions.rb +1 -1
  21. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +2 -2
  22. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +2 -2
  23. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +1 -1
  24. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +1 -1
  25. data/lib/action_dispatch/routing.rb +14 -14
  26. data/lib/action_dispatch/system_test_case.rb +22 -2
  27. data/lib/action_dispatch/system_testing/browser.rb +15 -7
  28. data/lib/action_dispatch/system_testing/driver.rb +8 -1
  29. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +1 -1
  30. data/lib/action_dispatch/testing/assertions/routing.rb +8 -1
  31. data/lib/action_dispatch/testing/integration.rb +2 -2
  32. data/lib/action_pack/gem_version.rb +1 -1
  33. metadata +10 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df5b083c08009f1025bfbf541400a4819b5620f5bb49aa3d4bbe0c056eae44b3
4
- data.tar.gz: '0374579e1273c1d727e0bc94d7a73b3933d8c0f54e7196beedc61ea30d88209f'
3
+ metadata.gz: 88d35424bac0eece534cf329b1ab3b2fdb55d76f9709a047e78ebfaf5fa07374
4
+ data.tar.gz: 8914995ea3644de413b90e94b61c9fa9ed58f0dd2fdf365a3bee4fb355c7184e
5
5
  SHA512:
6
- metadata.gz: cb0e467dc8c10baa42df2d08d79b2f5caedad996d247523abf54713a542f6d49a01f120ca0b0faa6930ea89592bfe074979201adec97d33135a5877391a5d4bb
7
- data.tar.gz: dee5cf35ce9af7e795d65bb2a44d5edb229439f5fbde0dde1c35e8d3cf2564c49ddf929a9d5499b3aa6248c42cf6f61ca2c75c85a623ba51f1dd6106750d3267
6
+ metadata.gz: 8d856ee7c126002bd2a0bb391cb9b1569f18fb766fc2d9ce8203791abf988359e0dce090caa5caee4e8268eb6b5fe4d584c28df9343e028b30e05cb4c0f8dc59
7
+ data.tar.gz: 3132bac5633fb26cb3a5de9995c702964334a9afc979fabceb0310829c5c04f1d9964c6413fa9965c9a035e1fb2f30a3f595fbddd5cc122568b6f345ff728325
@@ -1,3 +1,15 @@
1
+ ## Rails 6.0.0.beta2 (February 25, 2019) ##
2
+
3
+ * Make debug exceptions works in an environment where ActiveStorage is not loaded.
4
+
5
+ *Tomoyuki Kurosawa*
6
+
7
+ * `ActionDispatch::SystemTestCase.driven_by` can now be called with a block
8
+ to define specific browser capabilities.
9
+
10
+ *Edouard Chin*
11
+
12
+
1
13
  ## Rails 6.0.0.beta1 (January 18, 2019) ##
2
14
 
3
15
  * Remove deprecated `fragment_cache_key` helper in favor of `combined_fragment_cache_key`.
@@ -11,16 +23,10 @@
11
23
 
12
24
  *Rafael Mendonça França*
13
25
 
14
- * Ensure external redirects are explicitly allowed
15
-
16
- Add `fallback_location` and `allow_other_host` options to `redirect_to`.
17
-
18
- *Gannon McGibbon*
19
-
20
26
  * Introduce ActionDispatch::HostAuthorization
21
27
 
22
28
  This is a new middleware that guards against DNS rebinding attacks by
23
- white-listing the allowed hosts a request can be made to.
29
+ explicitly permitting the hosts a request can be made to.
24
30
 
25
31
  Each host is checked with the case operator (`#===`) to support `RegExp`,
26
32
  `Proc`, `IPAddr` and custom objects as host allowances.
@@ -82,7 +88,7 @@
82
88
  * Apply mapping to symbols returned from dynamic CSP sources
83
89
 
84
90
  Previously if a dynamic source returned a symbol such as :self it
85
- would be converted to a string implicity, e.g:
91
+ would be converted to a string implicitly, e.g:
86
92
 
87
93
  policy.default_src -> { :self }
88
94
 
@@ -135,7 +141,7 @@
135
141
 
136
142
  *Assain Jaleel*
137
143
 
138
- * Raises `ActionController::RespondToMismatchError` with confliciting `respond_to` invocations.
144
+ * Raises `ActionController::RespondToMismatchError` with conflicting `respond_to` invocations.
139
145
 
140
146
  `respond_to` can match multiple types and lead to undefined behavior when
141
147
  multiple invocations are made and the types do not match:
@@ -160,7 +166,7 @@
160
166
 
161
167
  *Aaron Kromer*
162
168
 
163
- * Pass along arguments to underlying `get` method in `follow_redirect!`.
169
+ * Pass along arguments to underlying `get` method in `follow_redirect!`
164
170
 
165
171
  Now all arguments passed to `follow_redirect!` are passed to the underlying
166
172
  `get` method. This for example allows to set custom headers for the
@@ -28,7 +28,6 @@ module AbstractController
28
28
  self.fragment_cache_keys = []
29
29
 
30
30
  if respond_to?(:helper_method)
31
- helper_method :fragment_cache_key
32
31
  helper_method :combined_fragment_cache_key
33
32
  end
34
33
  end
@@ -11,6 +11,7 @@ module AbstractController
11
11
  # to translate many keys within the same controller / action and gives you a
12
12
  # simple framework for scoping them consistently.
13
13
  def translate(key, options = {})
14
+ options = options.dup
14
15
  if key.to_s.first == "."
15
16
  path = controller_path.tr("/", ".")
16
17
  defaults = [:"#{path}#{key}"]
@@ -6,7 +6,7 @@ module ActionController
6
6
  super.tap { default_render unless performed? }
7
7
  end
8
8
 
9
- def default_render(*args)
9
+ def default_render
10
10
  head :no_content
11
11
  end
12
12
  end
@@ -51,7 +51,7 @@ module ActionController
51
51
  end
52
52
 
53
53
  def lookup_and_digest_template(template)
54
- ActionView::Digestor.digest name: template, finder: lookup_context
54
+ ActionView::Digestor.digest name: template, format: nil, finder: lookup_context
55
55
  end
56
56
  end
57
57
  end
@@ -52,7 +52,7 @@ module ActionController
52
52
  end
53
53
 
54
54
  # Raised when a nested respond_to is triggered and the content types of each
55
- # are incompatible. For exampe:
55
+ # are incompatible. For example:
56
56
  #
57
57
  # respond_to do |outer_type|
58
58
  # outer_type.js do
@@ -13,7 +13,7 @@ module ActionController
13
13
 
14
14
  ACTION_OPTIONS = [:only, :except, :if, :unless]
15
15
  URL_OPTIONS = [:protocol, :host, :domain, :subdomain, :port, :path]
16
- REDIRECT_OPTIONS = [:status, :flash, :alert, :notice, :allow_other_host]
16
+ REDIRECT_OPTIONS = [:status, :flash, :alert, :notice]
17
17
 
18
18
  module ClassMethods # :nodoc:
19
19
  def force_ssl(options = {})
@@ -41,7 +41,6 @@ module ActionController
41
41
  host: request.host,
42
42
  path: request.fullpath,
43
43
  status: :moved_permanently,
44
- allow_other_host: true,
45
44
  }
46
45
 
47
46
  if host_or_options.is_a?(Hash)
@@ -75,7 +75,7 @@ module ActionController
75
75
  # Provides a proxy to access helper methods from outside the view.
76
76
  def helpers
77
77
  @helper_proxy ||= begin
78
- proxy = ActionView::Base.new
78
+ proxy = ActionView::Base.empty
79
79
  proxy.config = config.inheritable_copy
80
80
  proxy.extend(_helpers)
81
81
  end
@@ -30,9 +30,9 @@ module ActionController
30
30
  # :stopdoc:
31
31
  include BasicImplicitRender
32
32
 
33
- def default_render(*args)
33
+ def default_render
34
34
  if template_exists?(action_name.to_s, _prefixes, variants: request.variant)
35
- render(*args)
35
+ render
36
36
  elsif any_templates?(action_name.to_s, _prefixes)
37
37
  message = "#{self.class.name}\##{action_name} is missing a template " \
38
38
  "for this request format and variant.\n" \
@@ -146,7 +146,7 @@ module ActionController
146
146
 
147
147
  def write(string)
148
148
  unless @response.committed?
149
- @response.set_header "Cache-Control", "no-cache"
149
+ @response.headers["Cache-Control"] ||= "no-cache"
150
150
  @response.delete_header "Content-Length"
151
151
  end
152
152
 
@@ -60,7 +60,7 @@ module ActionController
60
60
  raise AbstractController::DoubleRenderError if response_body
61
61
 
62
62
  self.status = _extract_redirect_to_status(options, response_options)
63
- self.location = _compute_safe_redirect_to_location(request, options, response_options)
63
+ self.location = _compute_redirect_to_location(request, options)
64
64
  self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
65
65
  end
66
66
 
@@ -88,13 +88,9 @@ module ActionController
88
88
  # All other options that can be passed to <tt>redirect_to</tt> are accepted as
89
89
  # options and the behavior is identical.
90
90
  def redirect_back(fallback_location:, allow_other_host: true, **args)
91
- referer = request.headers.fetch("Referer", fallback_location)
92
- response_options = {
93
- fallback_location: fallback_location,
94
- allow_other_host: allow_other_host,
95
- **args,
96
- }
97
- redirect_to referer, response_options
91
+ referer = request.headers["Referer"]
92
+ redirect_to_referer = referer && (allow_other_host || _url_host_allowed?(referer))
93
+ redirect_to redirect_to_referer ? referer : fallback_location, **args
98
94
  end
99
95
 
100
96
  def _compute_redirect_to_location(request, options) #:nodoc:
@@ -118,23 +114,6 @@ module ActionController
118
114
  public :_compute_redirect_to_location
119
115
 
120
116
  private
121
- def _compute_safe_redirect_to_location(request, options, response_options)
122
- location = _compute_redirect_to_location(request, options)
123
- location_options = options.is_a?(Hash) ? options : {}
124
- if response_options[:allow_other_host] || _url_host_allowed?(location, location_options)
125
- location
126
- else
127
- fallback_location = response_options.fetch(:fallback_location) do
128
- raise ArgumentError, <<~MSG.squish
129
- Unsafe redirect #{location.inspect},
130
- use :fallback_location to specify a fallback
131
- or :allow_other_host to redirect anyway.
132
- MSG
133
- end
134
- _compute_redirect_to_location(request, fallback_location)
135
- end
136
- end
137
-
138
117
  def _extract_redirect_to_status(options, response_options)
139
118
  if options.is_a?(Hash) && options.key?(:status)
140
119
  Rack::Utils.status_code(options.delete(:status))
@@ -145,8 +124,8 @@ module ActionController
145
124
  end
146
125
  end
147
126
 
148
- def _url_host_allowed?(url, options = {})
149
- URI(url.to_s).host.in?([request.host, options[:host]])
127
+ def _url_host_allowed?(url)
128
+ URI(url.to_s).host == request.host
150
129
  rescue ArgumentError, URI::Error
151
130
  false
152
131
  end
@@ -795,7 +795,7 @@ module ActionController
795
795
  @permitted = coder.map["ivars"][:@permitted]
796
796
  when "!ruby/object:ActionController::Parameters"
797
797
  # YAML's Object format. Only needed because of the format
798
- # backwardscompability above, otherwise equivalent to YAML's initialization.
798
+ # backwards compatibility above, otherwise equivalent to YAML's initialization.
799
799
  @parameters, @permitted = coder.map["parameters"], coder.map["permitted"]
800
800
  end
801
801
  end
@@ -20,7 +20,6 @@ module ActionDispatch
20
20
  # A +Tempfile+ object with the actual uploaded file. Note that some of
21
21
  # its interface is available directly.
22
22
  attr_accessor :tempfile
23
- alias :to_io :tempfile
24
23
 
25
24
  # A string with the headers of the multipart request.
26
25
  attr_accessor :headers
@@ -84,6 +83,10 @@ module ActionDispatch
84
83
  def eof?
85
84
  @tempfile.eof?
86
85
  end
86
+
87
+ def to_io
88
+ @tempfile.to_io
89
+ end
87
90
  end
88
91
  end
89
92
  end
@@ -119,7 +119,7 @@ module ActionDispatch
119
119
 
120
120
  class UnanchoredRegexp < AnchoredRegexp # :nodoc:
121
121
  def accept(node)
122
- %r{\A#{visit node}}
122
+ %r{\A#{visit node}(?:\b|\Z)}
123
123
  end
124
124
  end
125
125
 
@@ -488,13 +488,8 @@ module ActionDispatch
488
488
  end
489
489
 
490
490
  def cookie_metadata(name, options)
491
- if request.use_cookies_with_metadata
492
- metadata = expiry_options(options)
493
- metadata[:purpose] = "cookie.#{name}"
494
-
495
- metadata
496
- else
497
- {}
491
+ expiry_options(options).tap do |metadata|
492
+ metadata[:purpose] = "cookie.#{name}" if request.use_cookies_with_metadata
498
493
  end
499
494
  end
500
495
 
@@ -10,7 +10,13 @@ module ActionDispatch
10
10
  RESCUES_TEMPLATE_PATH = File.expand_path("templates", __dir__)
11
11
 
12
12
  def initialize(assigns)
13
- super([RESCUES_TEMPLATE_PATH], assigns)
13
+ paths = [RESCUES_TEMPLATE_PATH]
14
+ lookup_context = ActionView::LookupContext.new(paths)
15
+ super(lookup_context, assigns)
16
+ end
17
+
18
+ def compiled_method_container
19
+ self.class
14
20
  end
15
21
 
16
22
  def debug_params(params)
@@ -31,22 +31,34 @@ module ActionDispatch
31
31
  "ActionController::MissingExactTemplate" => "missing_exact_template",
32
32
  )
33
33
 
34
+ cattr_accessor :wrapper_exceptions, default: [
35
+ "ActionView::Template::Error"
36
+ ]
37
+
34
38
  attr_reader :backtrace_cleaner, :exception, :wrapped_causes, :line_number, :file
35
39
 
36
40
  def initialize(backtrace_cleaner, exception)
37
41
  @backtrace_cleaner = backtrace_cleaner
38
- @exception = original_exception(exception)
42
+ @exception = exception
39
43
  @wrapped_causes = wrapped_causes_for(exception, backtrace_cleaner)
40
44
 
41
45
  expand_backtrace if exception.is_a?(SyntaxError) || exception.cause.is_a?(SyntaxError)
42
46
  end
43
47
 
48
+ def unwrapped_exception
49
+ if wrapper_exceptions.include?(exception.class.to_s)
50
+ exception.cause
51
+ else
52
+ exception
53
+ end
54
+ end
55
+
44
56
  def rescue_template
45
57
  @@rescue_templates[@exception.class.name]
46
58
  end
47
59
 
48
60
  def status_code
49
- self.class.status_code_for_exception(@exception.class.name)
61
+ self.class.status_code_for_exception(unwrapped_exception.class.name)
50
62
  end
51
63
 
52
64
  def application_trace
@@ -122,14 +134,6 @@ module ActionDispatch
122
134
  Array(@exception.backtrace)
123
135
  end
124
136
 
125
- def original_exception(exception)
126
- if @@rescue_responses.has_key?(exception.cause.class.name)
127
- exception.cause
128
- else
129
- exception
130
- end
131
- end
132
-
133
137
  def causes_for(exception)
134
138
  return enum_for(__method__, exception) unless block_given?
135
139
 
@@ -3,8 +3,8 @@
3
3
  require "action_dispatch/http/request"
4
4
 
5
5
  module ActionDispatch
6
- # This middleware guards from DNS rebinding attacks by white-listing the
7
- # hosts a request can be sent to.
6
+ # This middleware guards from DNS rebinding attacks by explicitly permitting
7
+ # the hosts a request can be sent to.
8
8
  #
9
9
  # When a request comes to an unauthorized host, the +response_app+
10
10
  # application will be executed and rendered. If no +response_app+ is given, a
@@ -45,7 +45,7 @@ module ActionDispatch
45
45
  backtrace_cleaner = request.get_header "action_dispatch.backtrace_cleaner"
46
46
  wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
47
47
  status = wrapper.status_code
48
- request.set_header "action_dispatch.exception", wrapper.exception
48
+ request.set_header "action_dispatch.exception", wrapper.unwrapped_exception
49
49
  request.set_header "action_dispatch.original_path", request.path_info
50
50
  request.path_info = "/#{status}"
51
51
  response = @exceptions_app.call(request.env)
@@ -2,6 +2,6 @@
2
2
  <h1>Blocked host: <%= @host %></h1>
3
3
  </header>
4
4
  <div id="container">
5
- <h2>To allow requests to <%= @host %>, add the following configuration:</h2>
6
- <pre>Rails.application.config.hosts &lt;&lt; "<%= @host %>"</pre>
5
+ <h2>To allow requests to <%= @host %>, add the following to your environment configuration:</h2>
6
+ <pre>config.hosts &lt;&lt; "<%= @host %>"</pre>
7
7
  </div>
@@ -1,5 +1,5 @@
1
1
  Blocked host: <%= @host %>
2
2
 
3
- To allow requests to <%= @host %>, add the following configuration:
3
+ To allow requests to <%= @host %>, add the following to your environment configuration:
4
4
 
5
- Rails.application.config.hosts << "<%= @host %>"
5
+ config.hosts << "<%= @host %>"
@@ -10,7 +10,7 @@
10
10
  <div id="container">
11
11
  <h2>
12
12
  <%= h @exception.message %>
13
- <% if @exception.message.match? %r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}} %>
13
+ <% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
14
14
  <br />To resolve this issue run: rails active_storage:install
15
15
  <% end %>
16
16
  </h2>
@@ -4,7 +4,7 @@
4
4
  <% end %>
5
5
 
6
6
  <%= @exception.message %>
7
- <% if @exception.message.match? %r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}} %>
7
+ <% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
8
8
  To resolve this issue run: rails active_storage:install
9
9
  <% end %>
10
10
 
@@ -74,8 +74,8 @@ module ActionDispatch
74
74
  # For routes that don't fit the <tt>resources</tt> mold, you can use the HTTP helper
75
75
  # methods <tt>get</tt>, <tt>post</tt>, <tt>patch</tt>, <tt>put</tt> and <tt>delete</tt>.
76
76
  #
77
- # get 'post/:id' => 'posts#show'
78
- # post 'post/:id' => 'posts#create_comment'
77
+ # get 'post/:id', to: 'posts#show'
78
+ # post 'post/:id', to: 'posts#create_comment'
79
79
  #
80
80
  # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same
81
81
  # URL will route to the <tt>show</tt> action.
@@ -83,7 +83,7 @@ module ActionDispatch
83
83
  # If your route needs to respond to more than one HTTP method (or all methods) then using the
84
84
  # <tt>:via</tt> option on <tt>match</tt> is preferable.
85
85
  #
86
- # match 'post/:id' => 'posts#show', via: [:get, :post]
86
+ # match 'post/:id', to: 'posts#show', via: [:get, :post]
87
87
  #
88
88
  # == Named routes
89
89
  #
@@ -94,7 +94,7 @@ module ActionDispatch
94
94
  # Example:
95
95
  #
96
96
  # # In config/routes.rb
97
- # get '/login' => 'accounts#login', as: 'login'
97
+ # get '/login', to: 'accounts#login', as: 'login'
98
98
  #
99
99
  # # With render, redirect_to, tests, etc.
100
100
  # redirect_to login_url
@@ -120,9 +120,9 @@ module ActionDispatch
120
120
  #
121
121
  # # In config/routes.rb
122
122
  # controller :blog do
123
- # get 'blog/show' => :list
124
- # get 'blog/delete' => :delete
125
- # get 'blog/edit' => :edit
123
+ # get 'blog/show', to: :list
124
+ # get 'blog/delete', to: :delete
125
+ # get 'blog/edit', to: :edit
126
126
  # end
127
127
  #
128
128
  # # provides named routes for show, delete, and edit
@@ -132,7 +132,7 @@ module ActionDispatch
132
132
  #
133
133
  # Routes can generate pretty URLs. For example:
134
134
  #
135
- # get '/articles/:year/:month/:day' => 'articles#find_by_id', constraints: {
135
+ # get '/articles/:year/:month/:day', to: 'articles#find_by_id', constraints: {
136
136
  # year: /\d{4}/,
137
137
  # month: /\d{1,2}/,
138
138
  # day: /\d{1,2}/
@@ -147,7 +147,7 @@ module ActionDispatch
147
147
  # You can specify a regular expression to define a format for a parameter.
148
148
  #
149
149
  # controller 'geocode' do
150
- # get 'geocode/:postalcode' => :show, constraints: {
150
+ # get 'geocode/:postalcode', to: :show, constraints: {
151
151
  # postalcode: /\d{5}(-\d{4})?/
152
152
  # }
153
153
  # end
@@ -156,13 +156,13 @@ module ActionDispatch
156
156
  # expression modifiers:
157
157
  #
158
158
  # controller 'geocode' do
159
- # get 'geocode/:postalcode' => :show, constraints: {
159
+ # get 'geocode/:postalcode', to: :show, constraints: {
160
160
  # postalcode: /hx\d\d\s\d[a-z]{2}/i
161
161
  # }
162
162
  # end
163
163
  #
164
164
  # controller 'geocode' do
165
- # get 'geocode/:postalcode' => :show, constraints: {
165
+ # get 'geocode/:postalcode', to: :show, constraints: {
166
166
  # postalcode: /# Postalcode format
167
167
  # \d{5} #Prefix
168
168
  # (-\d{4})? #Suffix
@@ -178,13 +178,13 @@ module ActionDispatch
178
178
  #
179
179
  # You can redirect any path to another path using the redirect helper in your router:
180
180
  #
181
- # get "/stories" => redirect("/posts")
181
+ # get "/stories", to: redirect("/posts")
182
182
  #
183
183
  # == Unicode character routes
184
184
  #
185
185
  # You can specify unicode character routes in your router:
186
186
  #
187
- # get "こんにちは" => "welcome#index"
187
+ # get "こんにちは", to: "welcome#index"
188
188
  #
189
189
  # == Routing to Rack Applications
190
190
  #
@@ -192,7 +192,7 @@ module ActionDispatch
192
192
  # index action in the PostsController, you can specify any Rack application
193
193
  # as the endpoint for a matcher:
194
194
  #
195
- # get "/application.js" => Sprockets
195
+ # get "/application.js", to: Sprockets
196
196
  #
197
197
  # == Reloading routes
198
198
  #
@@ -89,6 +89,24 @@ module ActionDispatch
89
89
  # { js_errors: true }
90
90
  # end
91
91
  #
92
+ # Some drivers require browser capabilities to be passed as a block instead
93
+ # of through the +options+ hash.
94
+ #
95
+ # As an example, if you want to add mobile emulation on chrome, you'll have to
96
+ # create an instance of selenium's +Chrome::Options+ object and add
97
+ # capabilities with a block.
98
+ #
99
+ # The block will be passed an instance of <tt><Driver>::Options</tt> where you can
100
+ # define the capabilities you want. Please refer to your driver documentation
101
+ # to learn about supported options.
102
+ #
103
+ # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
104
+ # driven_by :selenium, using: :chrome, screen_size: [1024, 768] do |driver_option|
105
+ # driver_option.add_emulation(device_name: 'iPhone 6')
106
+ # driver_option.add_extension('path/to/chrome_extension.crx')
107
+ # end
108
+ # end
109
+ #
92
110
  # Because <tt>ActionDispatch::SystemTestCase</tt> is a shim between Capybara
93
111
  # and Rails, any driver that is supported by Capybara is supported by system
94
112
  # tests as long as you include the required gems and files.
@@ -134,8 +152,10 @@ module ActionDispatch
134
152
  # driven_by :selenium, using: :firefox
135
153
  #
136
154
  # driven_by :selenium, using: :headless_firefox
137
- def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {})
138
- self.driver = SystemTesting::Driver.new(driver, using: using, screen_size: screen_size, options: options)
155
+ def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {}, &capabilities)
156
+ driver_options = { using: using, screen_size: screen_size, options: options }
157
+
158
+ self.driver = SystemTesting::Driver.new(driver, driver_options, &capabilities)
139
159
  end
140
160
 
141
161
  driven_by :selenium
@@ -29,20 +29,28 @@ module ActionDispatch
29
29
  end
30
30
  end
31
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
40
+ end
41
+
32
42
  private
33
43
  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?
44
+ capabilities.args << "--headless"
45
+ capabilities.args << "--disable-gpu" if Gem.win_platform?
37
46
 
38
- options
47
+ capabilities
39
48
  end
40
49
 
41
50
  def headless_firefox_browser_options
42
- options = Selenium::WebDriver::Firefox::Options.new
43
- options.args << "-headless"
51
+ capabilities.args << "-headless"
44
52
 
45
- options
53
+ capabilities
46
54
  end
47
55
  end
48
56
  end
@@ -3,11 +3,12 @@
3
3
  module ActionDispatch
4
4
  module SystemTesting
5
5
  class Driver # :nodoc:
6
- def initialize(name, **options)
6
+ def initialize(name, **options, &capabilities)
7
7
  @name = name
8
8
  @browser = Browser.new(options[:using])
9
9
  @screen_size = options[:screen_size]
10
10
  @options = options[:options]
11
+ @capabilities = capabilities
11
12
  end
12
13
 
13
14
  def use
@@ -22,6 +23,8 @@ module ActionDispatch
22
23
  end
23
24
 
24
25
  def register
26
+ define_browser_capabilities(@browser.capabilities)
27
+
25
28
  Capybara.register_driver @name do |app|
26
29
  case @name
27
30
  when :selenium then register_selenium(app)
@@ -31,6 +34,10 @@ module ActionDispatch
31
34
  end
32
35
  end
33
36
 
37
+ def define_browser_capabilities(capabilities)
38
+ @capabilities.call(capabilities) if @capabilities
39
+ end
40
+
34
41
  def browser_options
35
42
  @options.merge(options: @browser.options).compact
36
43
  end
@@ -20,7 +20,7 @@ module ActionDispatch
20
20
  # * [+inline+] Display the screenshot in the terminal using the
21
21
  # iTerm image protocol (https://iterm2.com/documentation-images.html).
22
22
  # * [+artifact+] Display the screenshot in the terminal, using the terminal
23
- # artifact format (https://buildkite.github.io/terminal/inline-images/).
23
+ # artifact format (https://buildkite.github.io/terminal-to-html/inline-images/).
24
24
  def take_screenshot
25
25
  save_image
26
26
  puts display_image
@@ -160,9 +160,16 @@ module ActionDispatch
160
160
  @controller.singleton_class.include(_routes.url_helpers)
161
161
 
162
162
  if @controller.respond_to? :view_context_class
163
- @controller.view_context_class = Class.new(@controller.view_context_class) do
163
+ view_context_class = Class.new(@controller.view_context_class) do
164
164
  include _routes.url_helpers
165
165
  end
166
+
167
+ custom_view_context = Module.new {
168
+ define_method(:view_context_class) do
169
+ view_context_class
170
+ end
171
+ }
172
+ @controller.extend(custom_view_context)
166
173
  end
167
174
  end
168
175
  yield @routes
@@ -194,7 +194,7 @@ module ActionDispatch
194
194
  # Adds request headers characteristic of XMLHttpRequest e.g. HTTP_X_REQUESTED_WITH.
195
195
  # The headers will be merged into the Rack env hash.
196
196
  # - +as+: Used for encoding the request with different content type.
197
- # Supports `:json` by default and will set the approriate request headers.
197
+ # Supports `:json` by default and will set the appropriate request headers.
198
198
  # The headers will be merged into the Rack env hash.
199
199
  #
200
200
  # This method is rarely used directly. Use +#get+, +#post+, or other standard
@@ -335,7 +335,7 @@ module ActionDispatch
335
335
  klass = APP_SESSIONS[app] ||= Class.new(Integration::Session) {
336
336
  # If the app is a Rails app, make url_helpers available on the session.
337
337
  # This makes app.url_for and app.foo_path available in the console.
338
- if app.respond_to?(:routes)
338
+ if app.respond_to?(:routes) && app.routes.is_a?(ActionDispatch::Routing::RouteSet)
339
339
  include app.routes.url_helpers
340
340
  include app.routes.mounted_helpers
341
341
  end
@@ -10,7 +10,7 @@ module ActionPack
10
10
  MAJOR = 6
11
11
  MINOR = 0
12
12
  TINY = 0
13
- PRE = "beta1"
13
+ PRE = "beta2"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.0.beta1
4
+ version: 6.0.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-18 00:00:00.000000000 Z
11
+ date: 2019-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 6.0.0.beta1
19
+ version: 6.0.0.beta2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 6.0.0.beta1
26
+ version: 6.0.0.beta2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rack
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -92,28 +92,28 @@ dependencies:
92
92
  requirements:
93
93
  - - '='
94
94
  - !ruby/object:Gem::Version
95
- version: 6.0.0.beta1
95
+ version: 6.0.0.beta2
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - '='
101
101
  - !ruby/object:Gem::Version
102
- version: 6.0.0.beta1
102
+ version: 6.0.0.beta2
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: activemodel
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - '='
108
108
  - !ruby/object:Gem::Version
109
- version: 6.0.0.beta1
109
+ version: 6.0.0.beta2
110
110
  type: :development
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - '='
115
115
  - !ruby/object:Gem::Version
116
- version: 6.0.0.beta1
116
+ version: 6.0.0.beta2
117
117
  description: Web apps on Rails. Simple, battle-tested conventions for building and
118
118
  testing MVC web applications. Works with any Rack-compatible server.
119
119
  email: david@loudthinking.com
@@ -301,8 +301,8 @@ homepage: http://rubyonrails.org
301
301
  licenses:
302
302
  - MIT
303
303
  metadata:
304
- source_code_uri: https://github.com/rails/rails/tree/v6.0.0.beta1/actionpack
305
- changelog_uri: https://github.com/rails/rails/blob/v6.0.0.beta1/actionpack/CHANGELOG.md
304
+ source_code_uri: https://github.com/rails/rails/tree/v6.0.0.beta2/actionpack
305
+ changelog_uri: https://github.com/rails/rails/blob/v6.0.0.beta2/actionpack/CHANGELOG.md
306
306
  post_install_message:
307
307
  rdoc_options: []
308
308
  require_paths: