rails--rails/actionpack/test/controller/filters_test.rb

1069 lines
32 KiB
Ruby

# frozen_string_literal: true
require "abstract_unit"
class ActionController::Base
class << self
%w(append_around_action prepend_after_action prepend_around_action prepend_before_action skip_after_action skip_before_action).each do |pending|
define_method(pending) do |*args|
$stderr.puts "#{pending} unimplemented: #{args.inspect}"
end unless method_defined?(pending)
end
def before_actions
filters = _process_action_callbacks.select { |c| c.kind == :before }
filters.map!(&:filter)
end
end
end
class FilterTest < ActionController::TestCase
class TestController < ActionController::Base
before_action :ensure_login
after_action :clean_up
def show
render inline: "ran action"
end
private
def ensure_login
@ran_filter ||= []
@ran_filter << "ensure_login"
end
def clean_up
@ran_after_action ||= []
@ran_after_action << "clean_up"
end
end
class ChangingTheRequirementsController < TestController
before_action :ensure_login, except: [:go_wild]
def go_wild
render plain: "gobble"
end
end
class TestMultipleFiltersController < ActionController::Base
before_action :try_1
before_action :try_2
before_action :try_3
(1..3).each do |i|
define_method "fail_#{i}" do
render plain: i.to_s
end
end
private
(1..3).each do |i|
define_method "try_#{i}" do
instance_variable_set :@try, i
if action_name == "fail_#{i}"
head(404)
end
end
end
end
class RenderingController < ActionController::Base
before_action :before_action_rendering
after_action :unreached_after_action
def show
@ran_action = true
render inline: "ran action"
end
private
def before_action_rendering
@ran_filter ||= []
@ran_filter << "before_action_rendering"
render inline: "something else"
end
def unreached_after_action
@ran_filter << "unreached_after_action_after_render"
end
end
class RenderingForPrependAfterActionController < RenderingController
prepend_after_action :unreached_prepend_after_action
private
def unreached_prepend_after_action
@ran_filter << "unreached_prepend_after_action_after_render"
end
end
class BeforeActionRedirectionController < ActionController::Base
before_action :before_action_redirects
after_action :unreached_after_action
def show
@ran_action = true
render inline: "ran show action"
end
def target_of_redirection
@ran_target_of_redirection = true
render inline: "ran target_of_redirection action"
end
private
def before_action_redirects
@ran_filter ||= []
@ran_filter << "before_action_redirects"
redirect_to(action: "target_of_redirection")
end
def unreached_after_action
@ran_filter << "unreached_after_action_after_redirection"
end
end
class BeforeActionRedirectionForPrependAfterActionController < BeforeActionRedirectionController
prepend_after_action :unreached_prepend_after_action_after_redirection
private
def unreached_prepend_after_action_after_redirection
@ran_filter << "unreached_prepend_after_action_after_redirection"
end
end
class ConditionalFilterController < ActionController::Base
def show
render inline: "ran action"
end
def another_action
render inline: "ran action"
end
def show_without_action
render inline: "ran action without action"
end
private
def ensure_login
@ran_filter ||= []
@ran_filter << "ensure_login"
end
def clean_up_tmp
@ran_filter ||= []
@ran_filter << "clean_up_tmp"
end
end
class ConditionalCollectionFilterController < ConditionalFilterController
before_action :ensure_login, except: [ :show_without_action, :another_action ]
end
class OnlyConditionSymController < ConditionalFilterController
before_action :ensure_login, only: :show
end
class ExceptConditionSymController < ConditionalFilterController
before_action :ensure_login, except: :show_without_action
end
class BeforeAndAfterConditionController < ConditionalFilterController
before_action :ensure_login, only: :show
after_action :clean_up_tmp, only: :show
end
class OnlyConditionProcController < ConditionalFilterController
before_action(only: :show) { |c| c.instance_variable_set(:"@ran_proc_action", true) }
end
class ExceptConditionProcController < ConditionalFilterController
before_action(except: :show_without_action) { |c| c.instance_variable_set(:"@ran_proc_action", true) }
end
class ConditionalClassFilter
def self.before(controller) controller.instance_variable_set(:"@ran_class_action", true) end
end
class OnlyConditionClassController < ConditionalFilterController
before_action ConditionalClassFilter, only: :show
end
class ExceptConditionClassController < ConditionalFilterController
before_action ConditionalClassFilter, except: :show_without_action
end
class AnomalousYetValidConditionController < ConditionalFilterController
before_action(ConditionalClassFilter, :ensure_login, Proc.new { |c| c.instance_variable_set(:"@ran_proc_action1", true) }, except: :show_without_action) { |c| c.instance_variable_set(:"@ran_proc_action2", true) }
end
class OnlyConditionalOptionsFilter < ConditionalFilterController
before_action :ensure_login, only: :index, if: Proc.new { |c| c.instance_variable_set(:"@ran_conditional_index_proc", true) }
end
class ConditionalOptionsFilter < ConditionalFilterController
before_action :ensure_login, if: Proc.new { |c| true }
before_action :clean_up_tmp, if: Proc.new { |c| false }
end
class ConditionalOptionsSkipFilter < ConditionalFilterController
before_action :ensure_login
before_action :clean_up_tmp
skip_before_action :ensure_login, if: -> { false }
skip_before_action :clean_up_tmp, if: -> { true }
end
class SkipFilterUsingOnlyAndIf < ConditionalFilterController
before_action :clean_up_tmp
before_action :ensure_login
skip_before_action :ensure_login, only: :login, if: -> { false }
skip_before_action :clean_up_tmp, only: :login, if: -> { true }
def login
render plain: "ok"
end
end
class SkipFilterUsingIfAndExcept < ConditionalFilterController
before_action :clean_up_tmp
before_action :ensure_login
skip_before_action :ensure_login, if: -> { false }, except: :login
skip_before_action :clean_up_tmp, if: -> { true }, except: :login
def login
render plain: "ok"
end
end
class ClassController < ConditionalFilterController
before_action ConditionalClassFilter
end
class PrependingController < TestController
prepend_before_action :wonderful_life
# skip_before_action :fire_flash
private
def wonderful_life
@ran_filter ||= []
@ran_filter << "wonderful_life"
end
end
class SkippingAndLimitedController < TestController
skip_before_action :ensure_login
before_action :ensure_login, only: :index
def index
render plain: "ok"
end
def public
render plain: "ok"
end
end
class SkippingAndReorderingController < TestController
skip_before_action :ensure_login
before_action :find_record
before_action :ensure_login
def index
render plain: "ok"
end
private
def find_record
@ran_filter ||= []
@ran_filter << "find_record"
end
end
class ConditionalSkippingController < TestController
skip_before_action :ensure_login, only: [ :login ]
skip_after_action :clean_up, only: [ :login ]
before_action :find_user, only: [ :change_password ]
def login
render inline: "ran action"
end
def change_password
render inline: "ran action"
end
private
def find_user
@ran_filter ||= []
@ran_filter << "find_user"
end
end
class ConditionalParentOfConditionalSkippingController < ConditionalFilterController
before_action :conditional_in_parent_before, only: [:show, :another_action]
after_action :conditional_in_parent_after, only: [:show, :another_action]
private
def conditional_in_parent_before
@ran_filter ||= []
@ran_filter << "conditional_in_parent_before"
end
def conditional_in_parent_after
@ran_filter ||= []
@ran_filter << "conditional_in_parent_after"
end
end
class ChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController
skip_before_action :conditional_in_parent_before, only: :another_action
skip_after_action :conditional_in_parent_after, only: :another_action
end
class AnotherChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController
skip_before_action :conditional_in_parent_before, only: :show
end
class ProcController < PrependingController
before_action(proc { |c| c.instance_variable_set(:"@ran_proc_action", true) })
end
class ImplicitProcController < PrependingController
before_action { |c| c.instance_variable_set(:"@ran_proc_action", true) }
end
class AuditFilter
def self.before(controller)
controller.instance_variable_set(:"@was_audited", true)
end
end
class AroundFilter
def before(controller)
@execution_log = "before"
controller.class.execution_log += " before aroundfilter " if controller.respond_to? :execution_log
controller.instance_variable_set(:"@before_ran", true)
end
def after(controller)
controller.instance_variable_set(:"@execution_log", @execution_log + " and after")
controller.instance_variable_set(:"@after_ran", true)
controller.class.execution_log << " after aroundfilter " if controller.respond_to? :execution_log
end
def around(controller)
before(controller)
yield
after(controller)
end
end
class AppendedAroundFilter
def before(controller)
controller.class.execution_log << " before appended aroundfilter "
end
def after(controller)
controller.class.execution_log << " after appended aroundfilter "
end
def around(controller)
before(controller)
yield
after(controller)
end
end
class AuditController < ActionController::Base
before_action(AuditFilter)
def show
render plain: "hello"
end
end
class AroundFilterController < PrependingController
around_action AroundFilter.new
end
class BeforeAfterClassFilterController < PrependingController
filter = AroundFilter.new
before_action filter
after_action filter
end
class MixedFilterController < PrependingController
cattr_accessor :execution_log
def initialize
@@execution_log = ""
super()
end
before_action { |c| c.class.execution_log << " before procfilter " }
prepend_around_action AroundFilter.new
after_action { |c| c.class.execution_log << " after procfilter " }
append_around_action AppendedAroundFilter.new
end
class MixedSpecializationController < ActionController::Base
class OutOfOrder < StandardError; end
before_action :first
before_action :second, only: :foo
def foo
render plain: "foo"
end
def bar
render plain: "bar"
end
private
def first
@first = true
end
def second
raise OutOfOrder unless @first
end
end
class DynamicDispatchController < ActionController::Base
before_action :choose
%w(foo bar baz).each do |action|
define_method(action) { render plain: action }
end
private
def choose
self.action_name = params[:choose]
end
end
class PrependingBeforeAndAfterController < ActionController::Base
prepend_before_action :before_all
prepend_after_action :after_all
before_action :between_before_all_and_after_all
after_action :between_before_all_and_after_all
def before_all
@ran_filter ||= []
@ran_filter << "before_all"
end
def after_all
@ran_filter ||= []
@ran_filter << "after_all"
end
def between_before_all_and_after_all
@ran_filter ||= []
@ran_filter << "between_before_all_and_after_all"
end
def show
render plain: "hello"
end
end
class ErrorToRescue < Exception; end
class RescuingAroundFilterWithBlock
def around(controller)
yield
rescue ErrorToRescue => ex
controller.__send__ :render, plain: "I rescued this: #{ex.inspect}"
end
end
class RescuedController < ActionController::Base
around_action RescuingAroundFilterWithBlock.new
def show
raise ErrorToRescue.new("Something made the bad noise.")
end
end
class NonYieldingAroundFilterController < ActionController::Base
before_action :filter_one
around_action :non_yielding_action
before_action :action_two
after_action :action_three
def index
render inline: "index"
end
private
def filter_one
@filters ||= []
@filters << "filter_one"
end
def action_two
@filters << "action_two"
end
def non_yielding_action
@filters << "it didn't yield"
end
def action_three
@filters << "action_three"
end
end
class ImplicitActionsController < ActionController::Base
before_action :find_only, only: :edit
before_action :find_except, except: :edit
private
def find_only
@only = "Only"
end
def find_except
@except = "Except"
end
end
def test_non_yielding_around_actions_do_not_raise
controller = NonYieldingAroundFilterController.new
assert_nothing_raised do
test_process(controller, "index")
end
end
def test_around_action_can_use_yield_inline_with_passed_action
controller = Class.new(ActionController::Base) do
around_action do |c, a|
c.values << "before"
a.call
c.values << "after"
end
def index
values << "action"
render inline: "index"
end
def values
@values ||= []
end
end.new
assert_nothing_raised do
test_process(controller, "index")
end
assert_equal ["before", "action", "after"], controller.values
end
def test_after_actions_are_not_run_if_around_action_does_not_yield
controller = NonYieldingAroundFilterController.new
test_process(controller, "index")
assert_equal ["filter_one", "it didn't yield"], controller.instance_variable_get(:@filters)
end
def test_added_action_to_inheritance_graph
assert_equal [ :ensure_login ], TestController.before_actions
end
def test_base_class_in_isolation
assert_equal [ ], ActionController::Base.before_actions
end
def test_prepending_action
assert_equal [ :wonderful_life, :ensure_login ], PrependingController.before_actions
end
def test_running_actions
test_process(PrependingController)
assert_equal %w( wonderful_life ensure_login ),
@controller.instance_variable_get(:@ran_filter)
end
def test_running_actions_with_proc
test_process(ProcController)
assert @controller.instance_variable_get(:@ran_proc_action)
end
def test_running_actions_with_implicit_proc
test_process(ImplicitProcController)
assert @controller.instance_variable_get(:@ran_proc_action)
end
def test_running_actions_with_class
test_process(AuditController)
assert @controller.instance_variable_get(:@was_audited)
end
def test_running_anomalous_yet_valid_condition_actions
test_process(AnomalousYetValidConditionController)
assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter)
assert @controller.instance_variable_get(:@ran_class_action)
assert @controller.instance_variable_get(:@ran_proc_action1)
assert @controller.instance_variable_get(:@ran_proc_action2)
test_process(AnomalousYetValidConditionController, "show_without_action")
assert_not @controller.instance_variable_defined?(:@ran_filter)
assert_not @controller.instance_variable_defined?(:@ran_class_action)
assert_not @controller.instance_variable_defined?(:@ran_proc_action1)
assert_not @controller.instance_variable_defined?(:@ran_proc_action2)
end
def test_running_conditional_options
test_process(ConditionalOptionsFilter)
assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter)
end
def test_running_conditional_skip_options
test_process(ConditionalOptionsSkipFilter)
assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter)
end
def test_if_is_ignored_when_used_with_only
test_process(SkipFilterUsingOnlyAndIf, "login")
assert_not @controller.instance_variable_defined?(:@ran_filter)
end
def test_except_is_ignored_when_used_with_if
test_process(SkipFilterUsingIfAndExcept, "login")
assert_equal %w(ensure_login), @controller.instance_variable_get(:@ran_filter)
end
def test_skipping_class_actions
test_process(ClassController)
assert_equal true, @controller.instance_variable_get(:@ran_class_action)
skipping_class_controller = Class.new(ClassController) do
skip_before_action ConditionalClassFilter
end
test_process(skipping_class_controller)
assert_not @controller.instance_variable_defined?(:@ran_class_action)
end
def test_running_collection_condition_actions
test_process(ConditionalCollectionFilterController)
assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter)
test_process(ConditionalCollectionFilterController, "show_without_action")
assert_not @controller.instance_variable_defined?(:@ran_filter)
test_process(ConditionalCollectionFilterController, "another_action")
assert_not @controller.instance_variable_defined?(:@ran_filter)
end
def test_running_only_condition_actions
test_process(OnlyConditionSymController)
assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter)
test_process(OnlyConditionSymController, "show_without_action")
assert_not @controller.instance_variable_defined?(:@ran_filter)
test_process(OnlyConditionProcController)
assert @controller.instance_variable_get(:@ran_proc_action)
test_process(OnlyConditionProcController, "show_without_action")
assert_not @controller.instance_variable_defined?(:@ran_proc_action)
test_process(OnlyConditionClassController)
assert @controller.instance_variable_get(:@ran_class_action)
test_process(OnlyConditionClassController, "show_without_action")
assert_not @controller.instance_variable_defined?(:@ran_class_action)
end
def test_running_except_condition_actions
test_process(ExceptConditionSymController)
assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter)
test_process(ExceptConditionSymController, "show_without_action")
assert_not @controller.instance_variable_defined?(:@ran_filter)
test_process(ExceptConditionProcController)
assert @controller.instance_variable_get(:@ran_proc_action)
test_process(ExceptConditionProcController, "show_without_action")
assert_not @controller.instance_variable_defined?(:@ran_proc_action)
test_process(ExceptConditionClassController)
assert @controller.instance_variable_get(:@ran_class_action)
test_process(ExceptConditionClassController, "show_without_action")
assert_not @controller.instance_variable_defined?(:@ran_class_action)
end
def test_running_only_condition_and_conditional_options
test_process(OnlyConditionalOptionsFilter, "show")
assert_not @controller.instance_variable_defined?(:@ran_conditional_index_proc)
end
def test_running_before_and_after_condition_actions
test_process(BeforeAndAfterConditionController)
assert_equal %w( ensure_login clean_up_tmp), @controller.instance_variable_get(:@ran_filter)
test_process(BeforeAndAfterConditionController, "show_without_action")
assert_not @controller.instance_variable_defined?(:@ran_filter)
end
def test_around_action
test_process(AroundFilterController)
assert @controller.instance_variable_get(:@before_ran)
assert @controller.instance_variable_get(:@after_ran)
end
def test_before_after_class_action
test_process(BeforeAfterClassFilterController)
assert @controller.instance_variable_get(:@before_ran)
assert @controller.instance_variable_get(:@after_ran)
end
def test_having_properties_in_around_action
test_process(AroundFilterController)
assert_equal "before and after", @controller.instance_variable_get(:@execution_log)
end
def test_prepending_and_appending_around_action
test_process(MixedFilterController)
assert_equal " before aroundfilter before procfilter before appended aroundfilter " \
" after appended aroundfilter after procfilter after aroundfilter ",
MixedFilterController.execution_log
end
def test_rendering_breaks_actioning_chain
response = test_process(RenderingController)
assert_equal "something else", response.body
assert_not @controller.instance_variable_defined?(:@ran_action)
end
def test_before_action_rendering_breaks_actioning_chain_for_after_action
test_process(RenderingController)
assert_equal %w( before_action_rendering ), @controller.instance_variable_get(:@ran_filter)
assert_not @controller.instance_variable_defined?(:@ran_action)
end
def test_before_action_redirects_breaks_actioning_chain_for_after_action
test_process(BeforeActionRedirectionController)
assert_response :redirect
assert_equal "http://test.host/filter_test/before_action_redirection/target_of_redirection", redirect_to_url
assert_equal %w( before_action_redirects ), @controller.instance_variable_get(:@ran_filter)
end
def test_before_action_rendering_breaks_actioning_chain_for_prepend_after_action
test_process(RenderingForPrependAfterActionController)
assert_equal %w( before_action_rendering ), @controller.instance_variable_get(:@ran_filter)
assert_not @controller.instance_variable_defined?(:@ran_action)
end
def test_before_action_redirects_breaks_actioning_chain_for_prepend_after_action
test_process(BeforeActionRedirectionForPrependAfterActionController)
assert_response :redirect
assert_equal "http://test.host/filter_test/before_action_redirection_for_prepend_after_action/target_of_redirection", redirect_to_url
assert_equal %w( before_action_redirects ), @controller.instance_variable_get(:@ran_filter)
end
def test_actions_with_mixed_specialization_run_in_order
assert_nothing_raised do
response = test_process(MixedSpecializationController, "bar")
assert_equal "bar", response.body
end
assert_nothing_raised do
response = test_process(MixedSpecializationController, "foo")
assert_equal "foo", response.body
end
end
def test_dynamic_dispatch
%w(foo bar baz).each do |action|
@request.query_parameters[:choose] = action
response = DynamicDispatchController.action(action).call(@request.env).last
assert_equal action, response.body
end
end
def test_running_prepended_before_and_after_action
test_process(PrependingBeforeAndAfterController)
assert_equal %w( before_all between_before_all_and_after_all between_before_all_and_after_all after_all ), @controller.instance_variable_get(:@ran_filter)
end
def test_skipping_and_limiting_controller
test_process(SkippingAndLimitedController, "index")
assert_equal %w( ensure_login ), @controller.instance_variable_get(:@ran_filter)
test_process(SkippingAndLimitedController, "public")
assert_not @controller.instance_variable_defined?(:@ran_filter)
end
def test_skipping_and_reordering_controller
test_process(SkippingAndReorderingController, "index")
assert_equal %w( find_record ensure_login ), @controller.instance_variable_get(:@ran_filter)
end
def test_conditional_skipping_of_actions
test_process(ConditionalSkippingController, "login")
assert_not @controller.instance_variable_defined?(:@ran_filter)
test_process(ConditionalSkippingController, "change_password")
assert_equal %w( ensure_login find_user ), @controller.instance_variable_get(:@ran_filter)
test_process(ConditionalSkippingController, "login")
assert_not @controller.instance_variable_defined?("@ran_after_action")
test_process(ConditionalSkippingController, "change_password")
assert_equal %w( clean_up ), @controller.instance_variable_get("@ran_after_action")
end
def test_conditional_skipping_of_actions_when_parent_action_is_also_conditional
test_process(ChildOfConditionalParentController)
assert_equal %w( conditional_in_parent_before conditional_in_parent_after ), @controller.instance_variable_get(:@ran_filter)
test_process(ChildOfConditionalParentController, "another_action")
assert_not @controller.instance_variable_defined?(:@ran_filter)
end
def test_condition_skipping_of_actions_when_siblings_also_have_conditions
test_process(ChildOfConditionalParentController)
assert_equal %w( conditional_in_parent_before conditional_in_parent_after ), @controller.instance_variable_get(:@ran_filter)
test_process(AnotherChildOfConditionalParentController)
assert_equal %w( conditional_in_parent_after ), @controller.instance_variable_get(:@ran_filter)
test_process(ChildOfConditionalParentController)
assert_equal %w( conditional_in_parent_before conditional_in_parent_after ), @controller.instance_variable_get(:@ran_filter)
end
def test_changing_the_requirements
test_process(ChangingTheRequirementsController, "go_wild")
assert_not @controller.instance_variable_defined?(:@ran_filter)
end
def test_a_rescuing_around_action
response = nil
assert_nothing_raised do
response = test_process(RescuedController)
end
assert_predicate response, :successful?
assert_equal("I rescued this: #<FilterTest::ErrorToRescue: Something made the bad noise.>", response.body)
end
def test_actions_obey_only_and_except_for_implicit_actions
test_process(ImplicitActionsController, "show")
assert_equal "Except", @controller.instance_variable_get(:@except)
assert_not @controller.instance_variable_defined?(:@only)
assert_equal "show", response.body
test_process(ImplicitActionsController, "edit")
assert_equal "Only", @controller.instance_variable_get(:@only)
assert_not @controller.instance_variable_defined?(:@except)
assert_equal "edit", response.body
end
private
def test_process(controller, action = "show")
@controller = controller.is_a?(Class) ? controller.new : controller
process(action)
end
end
class PostsController < ActionController::Base
module AroundExceptions
class Error < StandardError ; end
class Before < Error ; end
class After < Error ; end
end
include AroundExceptions
class DefaultFilter
include AroundExceptions
end
module_eval %w(raises_before raises_after raises_both no_raise no_action).map { |action| "def #{action}; default_action end" }.join("\n")
private
def default_action
render inline: "#{action_name} called"
end
end
class ControllerWithSymbolAsFilter < PostsController
around_action :raise_before, only: :raises_before
around_action :raise_after, only: :raises_after
around_action :without_exception, only: :no_raise
private
def raise_before
raise Before
yield
end
def raise_after
yield
raise After
end
def without_exception
# Do stuff...
wtf = 1 + 1
yield
# Do stuff...
wtf + 1
end
end
class ControllerWithFilterClass < PostsController
class YieldingFilter < DefaultFilter
def self.around(controller)
yield
raise After
end
end
around_action YieldingFilter, only: :raises_after
end
class ControllerWithFilterInstance < PostsController
class YieldingFilter < DefaultFilter
def around(controller)
yield
raise After
end
end
around_action YieldingFilter.new, only: :raises_after
end
class ControllerWithProcFilter < PostsController
around_action(only: :no_raise) do |c, b|
c.instance_variable_set(:"@before", true)
b.call
c.instance_variable_set(:"@after", true)
end
end
class ControllerWithNestedFilters < ControllerWithSymbolAsFilter
around_action :raise_before, :raise_after, :without_exception, only: :raises_both
end
class ControllerWithAllTypesOfFilters < PostsController
before_action :before
around_action :around
after_action :after
around_action :around_again
private
def before
@ran_filter ||= []
@ran_filter << "before"
end
def around
@ran_filter << "around (before yield)"
yield
@ran_filter << "around (after yield)"
end
def after
@ran_filter << "after"
end
def around_again
@ran_filter << "around_again (before yield)"
yield
@ran_filter << "around_again (after yield)"
end
end
class ControllerWithTwoLessFilters < ControllerWithAllTypesOfFilters
skip_around_action :around_again
skip_after_action :after
end
class YieldingAroundFiltersTest < ActionController::TestCase
include PostsController::AroundExceptions
def test_base
controller = PostsController
assert_nothing_raised { test_process(controller, "no_raise") }
assert_nothing_raised { test_process(controller, "raises_before") }
assert_nothing_raised { test_process(controller, "raises_after") }
assert_nothing_raised { test_process(controller, "no_action") }
end
def test_with_symbol
controller = ControllerWithSymbolAsFilter
assert_nothing_raised { test_process(controller, "no_raise") }
assert_raise(Before) { test_process(controller, "raises_before") }
assert_raise(After) { test_process(controller, "raises_after") }
assert_nothing_raised { test_process(controller, "no_raise") }
end
def test_with_class
controller = ControllerWithFilterClass
assert_nothing_raised { test_process(controller, "no_raise") }
assert_raise(After) { test_process(controller, "raises_after") }
end
def test_with_instance
controller = ControllerWithFilterInstance
assert_nothing_raised { test_process(controller, "no_raise") }
assert_raise(After) { test_process(controller, "raises_after") }
end
def test_with_proc
test_process(ControllerWithProcFilter, "no_raise")
assert @controller.instance_variable_get(:@before)
assert @controller.instance_variable_get(:@after)
end
def test_nested_actions
controller = ControllerWithNestedFilters
assert_nothing_raised do
test_process(controller, "raises_both")
rescue Before, After
end
assert_raise Before do
test_process(controller, "raises_both")
rescue After
end
end
def test_action_order_with_all_action_types
test_process(ControllerWithAllTypesOfFilters, "no_raise")
assert_equal "before around (before yield) around_again (before yield) around_again (after yield) after around (after yield)", @controller.instance_variable_get(:@ran_filter).join(" ")
end
def test_action_order_with_skip_action_method
test_process(ControllerWithTwoLessFilters, "no_raise")
assert_equal "before around (before yield) around (after yield)", @controller.instance_variable_get(:@ran_filter).join(" ")
end
def test_first_action_in_multiple_before_action_chain_halts
controller = ::FilterTest::TestMultipleFiltersController.new
response = test_process(controller, "fail_1")
assert_equal "", response.body
assert_equal 1, controller.instance_variable_get(:@try)
end
def test_second_action_in_multiple_before_action_chain_halts
controller = ::FilterTest::TestMultipleFiltersController.new
response = test_process(controller, "fail_2")
assert_equal "", response.body
assert_equal 2, controller.instance_variable_get(:@try)
end
def test_last_action_in_multiple_before_action_chain_halts
controller = ::FilterTest::TestMultipleFiltersController.new
response = test_process(controller, "fail_3")
assert_equal "", response.body
assert_equal 3, controller.instance_variable_get(:@try)
end
private
def test_process(controller, action = "show")
@controller = controller.is_a?(Class) ? controller.new : controller
process(action)
end
end