test: cover BaseWithFiltersController, stamp_base
This commit is contained in:
1 parent
a4701cba33
commit
daa6632b39
2 files changed
+165
No files matched your search
@@ -40,6 +40,48 @@ class FilterApp < Prism::Application
|
|||||||
get '/public', to: 'filter#public_action'
|
get '/public', to: 'filter#public_action'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class BaseWithFiltersController < Prism::Controller
|
||||||
|
before_action :stamp_base, only: %i[index]
|
||||||
|
after_action :stamp_base_after, only: %i[index]
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def stamp_base
|
||||||
|
@trail = (@trail || []) << 'base-before'
|
||||||
|
end
|
||||||
|
|
||||||
|
def stamp_base_after
|
||||||
|
self.class.trail_after << 'base-before-runs-first?'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class InheritedFiltersController < BaseWithFiltersController
|
||||||
|
before_action :stamp_sub, only: %i[index]
|
||||||
|
|
||||||
|
def self.trail_after
|
||||||
|
@trail_after ||= []
|
||||||
|
end
|
||||||
|
|
||||||
|
def index
|
||||||
|
json(trail: @trail)
|
||||||
|
end
|
||||||
|
|
||||||
|
def other
|
||||||
|
json(trail: @trail)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def stamp_sub
|
||||||
|
@trail << 'sub-before'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class InheritedFiltersApp < Prism::Application
|
||||||
|
get '/inherited', to: 'inherited_filters#index'
|
||||||
|
get '/inherited-other', to: 'inherited_filters#other'
|
||||||
|
end
|
||||||
|
|
||||||
class ControllerFiltersTest < Minitest::Test
|
class ControllerFiltersTest < Minitest::Test
|
||||||
include TestSupport
|
include TestSupport
|
||||||
|
|
||||||
@@ -51,6 +93,10 @@ class ControllerFiltersTest < Minitest::Test
|
|||||||
FilterApp.call(env_for(method, path, **opts))
|
FilterApp.call(env_for(method, path, **opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def call_inherited(method, path, **opts)
|
||||||
|
InheritedFiltersApp.call(env_for(method, path, **opts))
|
||||||
|
end
|
||||||
|
|
||||||
def test_inline_before_action_block_runs_and_scoped_to_only
|
def test_inline_before_action_block_runs_and_scoped_to_only
|
||||||
_, _, body = call('GET', '/index?token=ok')
|
_, _, body = call('GET', '/index?token=ok')
|
||||||
assert_equal ['inline-before'], JSON.parse(body.join)['log']
|
assert_equal ['inline-before'], JSON.parse(body.join)['log']
|
||||||
@@ -83,4 +129,19 @@ class ControllerFiltersTest < Minitest::Test
|
|||||||
call('GET', '/public')
|
call('GET', '/public')
|
||||||
refute_includes FilterController.after_log, 'public_action'
|
refute_includes FilterController.after_log, 'public_action'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_before_action_declared_on_a_superclass_runs_for_a_subclass_action
|
||||||
|
_, _, body = call_inherited('GET', '/inherited')
|
||||||
|
assert_equal %w[base-before sub-before], JSON.parse(body.join)['trail']
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_after_action_declared_on_a_superclass_runs_for_a_subclass_action
|
||||||
|
call_inherited('GET', '/inherited')
|
||||||
|
assert_includes InheritedFiltersController.trail_after, 'base-before-runs-first?'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_inherited_before_action_only_option_still_scopes_to_the_declared_action
|
||||||
|
_, _, body = call_inherited('GET', '/inherited-other')
|
||||||
|
assert_nil JSON.parse(body.join)['trail']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
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
|
||||||
Reference in new issue
Block a user