1 require 'abstract_unit'
3 class RescueController
< ActionController
::Base
4 class NotAuthorized
< StandardError
6 class NotAuthorizedToRescueAsString
< StandardError
9 class RecordInvalid
< StandardError
11 class RecordInvalidToRescueAsString
< StandardError
14 class NotAllowed
< StandardError
16 class NotAllowedToRescueAsString
< StandardError
19 class InvalidRequest
< StandardError
21 class InvalidRequestToRescueAsString
< StandardError
24 class BadGateway
< StandardError
26 class BadGatewayToRescueAsString
< StandardError
29 class ResourceUnavailable
< StandardError
31 class ResourceUnavailableToRescueAsString
< StandardError
34 # We use a fully-qualified name in some strings, and a relative constant
35 # name in some other to test correct handling of both cases.
37 rescue_from NotAuthorized
, :with => :deny_access
38 rescue_from
'RescueController::NotAuthorizedToRescueAsString', :with => :deny_access
40 rescue_from RecordInvalid
, :with => :show_errors
41 rescue_from
'RescueController::RecordInvalidToRescueAsString', :with => :show_errors
43 rescue_from NotAllowed
, :with => proc
{ head
:forbidden }
44 rescue_from
'RescueController::NotAllowedToRescueAsString', :with => proc
{ head
:forbidden }
46 rescue_from InvalidRequest
, :with => proc
{ |exception
| render
:text => exception
.message
}
47 rescue_from
'InvalidRequestToRescueAsString', :with => proc
{ |exception
| render
:text => exception
.message
}
49 rescue_from BadGateway
do
52 rescue_from
'BadGatewayToRescueAsString' do
56 rescue_from ResourceUnavailable
do |exception
|
57 render
:text => exception
.message
59 rescue_from
'ResourceUnavailableToRescueAsString' do |exception
|
60 render
:text => exception
.message
63 # This is a Dispatcher exception and should be in ApplicationController.
64 rescue_from ActionController
::RoutingError do
65 render
:text => 'no way'
68 before_filter(:only => :before_filter_raises) { raise 'umm nice' }
70 def before_filter_raises
74 render
:text => 'already rendered'
78 def method_not_allowed
79 raise ActionController
::MethodNotAllowed.new(:get, :head, :put)
83 raise ActionController
::NotImplemented.new(:get, :put)
89 def not_authorized_raise_as_string
90 raise NotAuthorizedToRescueAsString
96 def not_allowed_raise_as_string
97 raise NotAllowedToRescueAsString
103 def invalid_request_raise_as_string
104 raise InvalidRequestToRescueAsString
110 def record_invalid_raise_as_string
111 raise RecordInvalidToRescueAsString
117 def bad_gateway_raise_as_string
118 raise BadGatewayToRescueAsString
121 def resource_unavailable
122 raise ResourceUnavailable
124 def resource_unavailable_raise_as_string
125 raise ResourceUnavailableToRescueAsString
136 def show_errors(exception
)
137 head
:unprocessable_entity
141 class RescueControllerTest
< ActionController
::TestCase
142 FIXTURE_PUBLIC
= "#{File.dirname(__FILE__)}/../fixtures".freeze
144 setup
:set_all_requests_local
145 setup
:populate_exception_object
147 def set_all_requests_local
148 RescueController
.consider_all_requests_local
= true
149 @request.remote_addr
= '1.2.3.4'
150 @request.host
= 'example.com'
153 def populate_exception_object
160 def test_rescue_exceptions_raised_by_filters
161 with_rails_root FIXTURE_PUBLIC
do
162 with_all_requests_local
false do
163 get
:before_filter_raises
167 assert_response
:internal_server_error
170 def test_rescue_action_locally_if_all_requests_local
171 @controller.expects(:local_request?).never
172 @controller.expects(:rescue_action_locally).with(@exception)
173 @controller.expects(:rescue_action_in_public).never
175 with_all_requests_local
do
176 @controller.send
:rescue_action, @exception
180 def test_rescue_action_locally_if_remote_addr_is_localhost
181 @controller.expects(:local_request?).returns(true)
182 @controller.expects(:rescue_action_locally).with(@exception)
183 @controller.expects(:rescue_action_in_public).never
185 with_all_requests_local
false do
186 @controller.send
:rescue_action, @exception
190 def test_rescue_action_in_public_otherwise
191 @controller.expects(:local_request?).returns(false)
192 @controller.expects(:rescue_action_locally).never
193 @controller.expects(:rescue_action_in_public).with(@exception)
195 with_all_requests_local
false do
196 @controller.send
:rescue_action, @exception
200 def test_rescue_action_in_public_with_localized_error_file
202 old_locale
= I18n
.locale
205 with_rails_root FIXTURE_PUBLIC
do
206 with_all_requests_local
false do
211 assert_response
:internal_server_error
212 body
= File
.read("#{FIXTURE_PUBLIC}/public/500.da.html")
213 assert_equal body
, @response.body
215 I18n
.locale
= old_locale
218 def test_rescue_action_in_public_with_error_file
219 with_rails_root FIXTURE_PUBLIC
do
220 with_all_requests_local
false do
225 assert_response
:internal_server_error
226 body
= File
.read("#{FIXTURE_PUBLIC}/public/500.html")
227 assert_equal body
, @response.body
230 def test_rescue_action_in_public_without_error_file
231 with_rails_root
'/tmp' do
232 with_all_requests_local
false do
237 assert_response
:internal_server_error
238 assert_equal
' ', @response.body
241 def test_rescue_unknown_action_in_public_with_error_file
242 with_rails_root FIXTURE_PUBLIC
do
243 with_all_requests_local
false do
244 get
:foobar_doesnt_exist
248 assert_response
:not_found
249 body
= File
.read("#{FIXTURE_PUBLIC}/public/404.html")
250 assert_equal body
, @response.body
253 def test_rescue_unknown_action_in_public_without_error_file
254 with_rails_root
'/tmp' do
255 with_all_requests_local
false do
256 get
:foobar_doesnt_exist
260 assert_response
:not_found
261 assert_equal
' ', @response.body
264 def test_rescue_missing_template_in_public
265 with_rails_root FIXTURE_PUBLIC
do
266 with_all_requests_local
true do
267 get
:missing_template
271 assert_response
:internal_server_error
272 assert
@response.body
.include?('missing_template'), "Response should include the template name."
275 def test_rescue_action_locally
277 assert_response
:internal_server_error
278 assert_template
'diagnostics.erb'
279 assert
@response.body
.include?('RescueController#raises'), "Response should include controller and action."
280 assert
@response.body
.include?("don't panic"), "Response should include exception message."
283 def test_local_request_when_remote_addr_is_localhost
284 @controller.expects(:request).returns(@request).at_least_once
285 with_remote_addr
'127.0.0.1' do
286 assert
@controller.send(:local_request?)
290 def test_local_request_when_remote_addr_isnt_locahost
291 @controller.expects(:request).returns(@request)
292 with_remote_addr
'1.2.3.4' do
293 assert
!@controller.send(:local_request?)
297 def test_rescue_responses
298 responses
= ActionController
::Base.rescue_responses
300 assert_equal ActionController
::Rescue::DEFAULT_RESCUE_RESPONSE, responses
.default
301 assert_equal ActionController
::Rescue::DEFAULT_RESCUE_RESPONSE, responses
[Exception
.new
]
303 assert_equal
:not_found, responses
[ActionController
::RoutingError.name
]
304 assert_equal
:not_found, responses
[ActionController
::UnknownAction.name
]
305 assert_equal
:not_found, responses
['ActiveRecord::RecordNotFound']
306 assert_equal
:conflict, responses
['ActiveRecord::StaleObjectError']
307 assert_equal
:unprocessable_entity, responses
['ActiveRecord::RecordInvalid']
308 assert_equal
:unprocessable_entity, responses
['ActiveRecord::RecordNotSaved']
309 assert_equal
:method_not_allowed, responses
['ActionController::MethodNotAllowed']
310 assert_equal
:not_implemented, responses
['ActionController::NotImplemented']
313 def test_rescue_templates
314 templates
= ActionController
::Base.rescue_templates
316 assert_equal ActionController
::Rescue::DEFAULT_RESCUE_TEMPLATE, templates
.default
317 assert_equal ActionController
::Rescue::DEFAULT_RESCUE_TEMPLATE, templates
[Exception
.new
]
319 assert_equal
'missing_template', templates
[ActionView
::MissingTemplate.name
]
320 assert_equal
'routing_error', templates
[ActionController
::RoutingError.name
]
321 assert_equal
'unknown_action', templates
[ActionController
::UnknownAction.name
]
322 assert_equal
'template_error', templates
[ActionView
::TemplateError.name
]
325 def test_not_implemented
326 with_all_requests_local
false do
327 with_rails_public_path(".") do
328 head
:not_implemented
331 assert_response
:not_implemented
332 assert_equal
"GET, PUT", @response.headers
['Allow']
335 def test_method_not_allowed
336 with_all_requests_local
false do
337 with_rails_public_path(".") do
338 get
:method_not_allowed
341 assert_response
:method_not_allowed
342 assert_equal
"GET, HEAD, PUT", @response.headers
['Allow']
345 def test_rescue_handler
347 assert_response
:forbidden
349 def test_rescue_handler_string
350 get
:not_authorized_raise_as_string
351 assert_response
:forbidden
354 def test_rescue_handler_with_argument
355 @controller.expects(:show_errors).once
.with
{ |e
| e
.is_a
?(Exception
) }
358 def test_rescue_handler_with_argument_as_string
359 @controller.expects(:show_errors).once
.with
{ |e
| e
.is_a
?(Exception
) }
360 get
:record_invalid_raise_as_string
363 def test_proc_rescue_handler
365 assert_response
:forbidden
367 def test_proc_rescue_handler_as_string
368 get
:not_allowed_raise_as_string
369 assert_response
:forbidden
372 def test_proc_rescue_handle_with_argument
374 assert_equal
"RescueController::InvalidRequest", @response.body
376 def test_proc_rescue_handle_with_argument_as_string
377 get
:invalid_request_raise_as_string
378 assert_equal
"RescueController::InvalidRequestToRescueAsString", @response.body
381 def test_block_rescue_handler
385 def test_block_rescue_handler_as_string
386 get
:bad_gateway_raise_as_string
390 def test_block_rescue_handler_with_argument
391 get
:resource_unavailable
392 assert_equal
"RescueController::ResourceUnavailable", @response.body
395 def test_block_rescue_handler_with_argument_as_string
396 get
:resource_unavailable_raise_as_string
397 assert_equal
"RescueController::ResourceUnavailableToRescueAsString", @response.body
400 def test_rescue_dispatcher_exceptions
402 env["action_controller.rescue.request"] = @request
403 env["action_controller.rescue.response"] = @response
405 RescueController
.call_with_exception(env, ActionController
::RoutingError.new("Route not found"))
406 assert_equal
"no way", @response.body
409 def test_rescue_dispatcher_exceptions_without_request_set
410 @request.env['REQUEST_URI'] = '/no_way'
411 response
= RescueController
.call_with_exception(@request.env, ActionController
::RoutingError.new("Route not found"))
412 assert_kind_of ActionController
::Response, response
413 assert_equal
"no way", response
.body
417 def with_all_requests_local(local
= true)
418 old_local
, ActionController
::Base.consider_all_requests_local
=
419 ActionController
::Base.consider_all_requests_local
, local
422 ActionController
::Base.consider_all_requests_local
= old_local
425 def with_remote_addr(addr
)
426 old_remote_addr
, @request.remote_addr
= @request.remote_addr
, addr
429 @request.remote_addr
= old_remote_addr
432 def with_rails_public_path(rails_root
)
433 old_rails
= Object
.const_get(:Rails) rescue nil
434 mod
= Object
.const_set(:Rails, Module
.new
)
435 (class << mod
; self; end).instance_eval
do
436 define_method(:public_path) { "#{rails_root}/public" }
440 Object
.module_eval
{ remove_const(:Rails) } if defined?(Rails
)
441 Object
.const_set(:Rails, old_rails
) if old_rails
444 def with_rails_root(path
= nil,&block
)
445 old_rails_root
= RAILS_ROOT
if defined?(RAILS_ROOT
)
447 silence_warnings
{ Object
.const_set(:RAILS_ROOT, path
) }
449 Object
.remove_const(:RAILS_ROOT) rescue nil
452 with_rails_public_path(path
, &block
)
456 silence_warnings
{ Object
.const_set(:RAILS_ROOT, old_rails_root
) }
458 Object
.remove_const(:RAILS_ROOT) rescue nil
463 class ExceptionInheritanceRescueController
< ActionController
::Base
465 class ParentException
< StandardError
468 class ChildException
< ParentException
471 class GrandchildException
< ChildException
474 rescue_from ChildException
, :with => lambda
{ head
:ok }
475 rescue_from ParentException
, :with => lambda
{ head
:created }
476 rescue_from GrandchildException
, :with => lambda
{ head
:no_content }
478 def raise_parent_exception
479 raise ParentException
482 def raise_child_exception
486 def raise_grandchild_exception
487 raise GrandchildException
491 class ExceptionInheritanceRescueControllerTest
< ActionController
::TestCase
492 def test_bottom_first
493 get
:raise_grandchild_exception
494 assert_response
:no_content
497 def test_inheritance_works
498 get
:raise_child_exception
499 assert_response
:created
503 class ControllerInheritanceRescueController
< ExceptionInheritanceRescueController
504 class FirstExceptionInChildController
< StandardError
507 class SecondExceptionInChildController
< StandardError
510 rescue_from FirstExceptionInChildController
, 'SecondExceptionInChildController', :with => lambda
{ head
:gone }
512 def raise_first_exception_in_child_controller
513 raise FirstExceptionInChildController
516 def raise_second_exception_in_child_controller
517 raise SecondExceptionInChildController
521 class ControllerInheritanceRescueControllerTest
< ActionController
::TestCase
522 def test_first_exception_in_child_controller
523 get
:raise_first_exception_in_child_controller
524 assert_response
:gone
527 def test_second_exception_in_child_controller
528 get
:raise_second_exception_in_child_controller
529 assert_response
:gone
532 def test_exception_in_parent_controller
533 get
:raise_parent_exception
534 assert_response
:created