Files
prism/test/test_controller_rescue_from.rb
T

105 lines
2.9 KiB
Ruby

require 'minitest/autorun'
require 'prism'
require 'support'
class RescueFromMissingRecordError < StandardError; end
class RescueFromSpecificError < RescueFromMissingRecordError; end
class RescueFromBaseController < Prism::Controller
rescue_from StandardError, with: :handle_any_error
private
def handle_any_error(exception)
halt(500, "base handled #{exception.class}")
end
end
# Declares a MORE specific handler than its superclass's catch-all - proves
# subclass handlers win even though the superclass's StandardError handler
# would also match.
class RescueFromController < RescueFromBaseController
rescue_from RescueFromMissingRecordError, with: :handle_missing_record
rescue_from ArgumentError do |exception|
halt(400, "block handled #{exception.message}")
end
def boom_missing
raise RescueFromMissingRecordError, 'gone'
end
def boom_specific_subclass
raise RescueFromSpecificError, 'gone'
end
def boom_argument
raise ArgumentError, 'bad input'
end
def boom_unhandled
raise ZeroDivisionError, 'nope'
end
def before_action_boom
raise RescueFromMissingRecordError, 'blocked before the action ran'
end
before_action :before_action_boom, only: %i[protected_action]
def protected_action
halt(200, 'should never reach here')
end
private
def handle_missing_record(exception)
halt(404, "missing #{exception.message}")
end
end
class RescueFromApp < Prism::Application
get '/missing', to: 'rescue_from#boom_missing'
get '/missing_subclass', to: 'rescue_from#boom_specific_subclass'
get '/argument', to: 'rescue_from#boom_argument'
get '/unhandled', to: 'rescue_from#boom_unhandled'
get '/protected', to: 'rescue_from#protected_action'
end
class ControllerRescueFromTest < Minitest::Test
include TestSupport
def call(method, path, **opts)
RescueFromApp.call(env_for(method, path, **opts))
end
def test_specific_handler_declared_on_the_subclass_wins_over_the_superclass_catch_all
status, _, body = call('GET', '/missing')
assert_equal 404, status
assert_equal 'missing gone', body.join
end
def test_is_a_matching_catches_a_subclass_of_the_registered_exception
status, _, body = call('GET', '/missing_subclass')
assert_equal 404, status
assert_equal 'missing gone', body.join
end
def test_block_handler_runs_with_the_controller_as_self
status, _, body = call('GET', '/argument')
assert_equal 400, status
assert_equal 'block handled bad input', body.join
end
def test_falls_back_to_the_superclass_catch_all_when_no_specific_handler_matches
status, _, body = call('GET', '/unhandled')
assert_equal 500, status
assert_equal 'base handled ZeroDivisionError', body.join
end
def test_rescue_from_also_catches_exceptions_raised_inside_before_actions
status, _, body = call('GET', '/protected')
assert_equal 404, status
assert_equal 'missing blocked before the action ran', body.join
end
end