# ==== Public API # Merb::AbstractController.before(filter, opts) # Merb::AbstractController.after(filter, opts) # Merb::AbstractController.skip_before(filter) # Merb::AbstractController.skip_after(filter) # # ==== Semipublic API # Merb::AbstractController#_body # Merb::AbstractController#_dispatch(action<~to_s>) require File.join(File.dirname(__FILE__), "spec_helper") startup_merb AbstractControllers = Merb::Test::Fixtures::Abstract describe Merb::AbstractController, " should support before and after filters" do it "should support before filters" do dispatch_should_make_body("TestBeforeFilter", "foo filter") end it "should support after filters" do dispatch_should_make_body("TestAfterFilter", "foo filter") end it "should support skipping filters that were defined in a superclass" do dispatch_should_make_body("TestSkipFilter", "") end it "should append before filters when added" do dispatch_should_make_body("TestBeforeFilterOrder", "bar filter") end it "should append after filters when added" do dispatch_should_make_body("TestAfterFilterOrder", "bar filter") end it "should support proc arguments to filters evaluated in the controller's instance" do dispatch_should_make_body("TestProcFilter", "proc filter1 proc filter2") end it "should support proc arguments to filters when called inside a class method" do dispatch_should_make_body("TestProcFilterViaMethod", "onetwo") end it "should support filters that skip specific actions via :exclude" do dispatch_should_make_body("TestExcludeFilter", " ", :index) dispatch_should_make_body("TestExcludeFilter", "foo filter bar filter", :show) end it "should support filters that work only on specific actions via :only" do dispatch_should_make_body("TestOnlyFilter", "foo filter bar filter", :index) dispatch_should_make_body("TestOnlyFilter", " ", :show) end it "should throw an error if both :exclude and :only are passed to a filter" do running { Merb::Test::Fixtures::Abstract.class_eval do class TestErrorFilter < Merb::Test::Fixtures::Abstract::Testing before :foo, :only => :index, :exclude => :show end end }.should raise_error(ArgumentError, /either :only or :exclude/) end it "should support filters that work only when a condition is met via :if" do dispatch_should_make_body("TestConditionalFilterWithMethod", "foo filter", :index, :presets => {:bar= => true}) dispatch_should_make_body("TestConditionalFilterWithMethod", "", :index, :presets => {:bar= => false}) end it "should support filters that work only when a condition is met via :unless" do dispatch_should_make_body("TestConditionalFilterWithProc", "foo filter", :index, :presets => {:bar= => 'baz'}) dispatch_should_make_body("TestConditionalFilterWithProc", "index action", :index, :presets => {:bar= => 'bar'}) end it "should throw an error if both :if and :unless are passed to a filter" do running { Merb::Test::Fixtures::Abstract.class_eval do class TestErrorFilter < Merb::Test::Fixtures::Abstract::Testing before :foo, :if => :index, :unless => :show end end }.should raise_error(ArgumentError, /either :if or :unless/) end it "should throw an error" do running { dispatch_should_make_body("TestConditionalFilterWithNoProcOrSymbol", "") }.should raise_error(ArgumentError, /a Symbol or a Proc/) end it "should throw an error if an unknown option is passed to a filter" do running { Merb::Test::Fixtures::Abstract.class_eval do class TestErrorFilter < Merb::Test::Fixtures::Abstract::Testing before :foo, :except => :index end end }.should raise_error(ArgumentError, /known filter options/) end it "should support passing an argument to a before filter method" do dispatch_should_make_body("TestBeforeFilterWithArgument", "index action") end it "should support passing arguments to a before filter method" do dispatch_should_make_body("TestBeforeFilterWithArguments", "index action") end it "should support throwing :halt to block a filter chain" do dispatch_should_make_body("BeforeFilterWithThrowHalt", "Halt thrown") end it "should support throwing :halt to block an action" do dispatch_should_make_body("ActionWithThrowHalt", "Halt thrown") end it "should support throwing :halt in an action method" do dispatch_should_make_body("ActionWithHaltInMethod", "Halt thrown") end it "should support throwing a proc in filters" do dispatch_should_make_body("BeforeFilterWithThrowProc", "Proc thrown") end it "should raise an InternalServerError if :halt is thrown with unexpected type" do calling { dispatch_to(AbstractControllers::FilterChainError, :index) }.should( raise_error(ArgumentError, /Threw :halt, Merb. Expected String/)) end it "should print useful HTML if throw :halt is called with nil" do dispatch_should_make_body("ThrowNil", "

Filter Chain Halted!

") end it "should inherit before filters" do dispatch_should_make_body("FilterChild2", "Before Limited", :limited) end it "should provide benchmarks" do controller = dispatch_to(AbstractControllers::Benchmarking, :index) controller._benchmarks[:before_filters_time].should be_kind_of(Numeric) controller._benchmarks[:after_filters_time].should be_kind_of(Numeric) end it "should not get contaminated by cousins" do dispatch_should_make_body("FilterChild2", "Before Index") dispatch_should_make_body("FilterChild1", "Before Limited", :limited) dispatch_should_make_body("FilterChild1", " Index") end # #611 in merb-core it "doesn't override existing filters by filters with similar names" do dispatch_should_make_body("HasFiltersWithSimilarNames", "Befilter Bef Index") end end