# frozen_string_literal: true require "abstract_unit" module AbstractController module Testing class ControllerWithCallbacks < AbstractController::Base include AbstractController::Callbacks end class Callback1 < ControllerWithCallbacks set_callback :process_action, :before, :first def first @text = "Hello world" end def index self.response_body = @text end end class TestCallbacks1 < ActiveSupport::TestCase test "basic callbacks work" do controller = Callback1.new controller.process(:index) assert_equal "Hello world", controller.response_body end end class Callback2 < ControllerWithCallbacks before_action :first after_action :second around_action :aroundz def first @text = "Hello world" end def second @second = "Goodbye" end def aroundz @aroundz = "FIRST" yield @aroundz += "SECOND" end def index @text ||= nil self.response_body = @text.to_s end end class Callback2Overwrite < Callback2 before_action :first, except: :index end class TestCallbacks2 < ActiveSupport::TestCase def setup @controller = Callback2.new end test "before_action works" do @controller.process(:index) assert_equal "Hello world", @controller.response_body end test "after_action works" do @controller.process(:index) assert_equal "Goodbye", @controller.instance_variable_get("@second") end test "around_action works" do @controller.process(:index) assert_equal "FIRSTSECOND", @controller.instance_variable_get("@aroundz") end test "before_action with overwritten condition" do @controller = Callback2Overwrite.new @controller.process(:index) assert_equal "", @controller.response_body end end class Callback3 < ControllerWithCallbacks before_action do |c| c.instance_variable_set("@text", "Hello world") end after_action do |c| c.instance_variable_set("@second", "Goodbye") end def index self.response_body = @text end end class TestCallbacks3 < ActiveSupport::TestCase def setup @controller = Callback3.new end test "before_action works with procs" do @controller.process(:index) assert_equal "Hello world", @controller.response_body end test "after_action works with procs" do @controller.process(:index) assert_equal "Goodbye", @controller.instance_variable_get("@second") end end class CallbacksWithConditions < ControllerWithCallbacks before_action :list, only: :index before_action :authenticate, except: :index def index self.response_body = @list.join(", ") end def sekrit_data self.response_body = (@list + [@authenticated]).join(", ") end private def list @list = ["Hello", "World"] end def authenticate @list ||= [] @authenticated = "true" end end class TestCallbacksWithConditions < ActiveSupport::TestCase def setup @controller = CallbacksWithConditions.new end test "when :only is specified, a before action is triggered on that action" do @controller.process(:index) assert_equal "Hello, World", @controller.response_body end test "when :only is specified, a before action is not triggered on other actions" do @controller.process(:sekrit_data) assert_equal "true", @controller.response_body end test "when :except is specified, an after action is not triggered on that action" do @controller.process(:index) assert_not @controller.instance_variable_defined?("@authenticated") end end class CallbacksWithArrayConditions < ControllerWithCallbacks before_action :list, only: [:index, :listy] before_action :authenticate, except: [:index, :listy] def index self.response_body = @list.join(", ") end def sekrit_data self.response_body = (@list + [@authenticated]).join(", ") end private def list @list = ["Hello", "World"] end def authenticate @list = [] @authenticated = "true" end end class TestCallbacksWithArrayConditions < ActiveSupport::TestCase def setup @controller = CallbacksWithArrayConditions.new end test "when :only is specified with an array, a before action is triggered on that action" do @controller.process(:index) assert_equal "Hello, World", @controller.response_body end test "when :only is specified with an array, a before action is not triggered on other actions" do @controller.process(:sekrit_data) assert_equal "true", @controller.response_body end test "when :except is specified with an array, an after action is not triggered on that action" do @controller.process(:index) assert_not @controller.instance_variable_defined?("@authenticated") end end class ChangedConditions < Callback2 before_action :first, only: :index def not_index @text ||= nil self.response_body = @text.to_s end end class TestCallbacksWithChangedConditions < ActiveSupport::TestCase def setup @controller = ChangedConditions.new end test "when a callback is modified in a child with :only, it works for the :only action" do @controller.process(:index) assert_equal "Hello world", @controller.response_body end test "when a callback is modified in a child with :only, it does not work for other actions" do @controller.process(:not_index) assert_equal "", @controller.response_body end end class SetsResponseBody < ControllerWithCallbacks before_action :set_body def index self.response_body = "Fail" end def set_body self.response_body = "Success" end end class TestHalting < ActiveSupport::TestCase test "when a callback sets the response body, the action should not be invoked" do controller = SetsResponseBody.new controller.process(:index) assert_equal "Success", controller.response_body end end class CallbacksWithArgs < ControllerWithCallbacks set_callback :process_action, :before, :first def first @text = "Hello world" end def index(text) self.response_body = @text + text end end class TestCallbacksWithArgs < ActiveSupport::TestCase test "callbacks still work when invoking process with multiple arguments" do controller = CallbacksWithArgs.new controller.process(:index, " Howdy!") assert_equal "Hello world Howdy!", controller.response_body end end end end