require 'test_helper' class StrainerUnitTest < Minitest::Test include Liquid module AccessScopeFilters def public_filter "public" end def private_filter "private" end private :private_filter end Strainer.global_filter(AccessScopeFilters) def test_strainer strainer = Strainer.create(nil) assert_equal 5, strainer.invoke('size', 'input') assert_equal "public", strainer.invoke("public_filter") end def test_stainer_raises_argument_error strainer = Strainer.create(nil) assert_raises(Liquid::ArgumentError) do strainer.invoke("public_filter", 1) end end def test_stainer_argument_error_contains_backtrace strainer = Strainer.create(nil) begin strainer.invoke("public_filter", 1) rescue Liquid::ArgumentError => e assert_match( /\ALiquid error: wrong number of arguments \((1 for 0|given 1, expected 0)\)\z/, e.message) assert_equal e.backtrace[0].split(':')[0], __FILE__ end end def test_strainer_only_invokes_public_filter_methods strainer = Strainer.create(nil) assert_equal false, strainer.class.invokable?('__test__') assert_equal false, strainer.class.invokable?('test') assert_equal false, strainer.class.invokable?('instance_eval') assert_equal false, strainer.class.invokable?('__send__') assert_equal true, strainer.class.invokable?('size') # from the standard lib end def test_strainer_returns_nil_if_no_filter_method_found strainer = Strainer.create(nil) assert_nil strainer.invoke("private_filter") assert_nil strainer.invoke("undef_the_filter") end def test_strainer_returns_first_argument_if_no_method_and_arguments_given strainer = Strainer.create(nil) assert_equal "password", strainer.invoke("undef_the_method", "password") end def test_strainer_only_allows_methods_defined_in_filters strainer = Strainer.create(nil) assert_equal "1 + 1", strainer.invoke("instance_eval", "1 + 1") assert_equal "puts", strainer.invoke("__send__", "puts", "Hi Mom") assert_equal "has_method?", strainer.invoke("invoke", "has_method?", "invoke") end def test_strainer_uses_a_class_cache_to_avoid_method_cache_invalidation a = Module.new b = Module.new strainer = Strainer.create(nil, [a, b]) assert_kind_of Strainer, strainer assert_kind_of a, strainer assert_kind_of b, strainer assert_kind_of Liquid::StandardFilters, strainer end def test_add_filter_when_wrong_filter_class c = Context.new s = c.strainer wrong_filter = ->(v) { v.reverse } assert_raises ArgumentError do s.class.add_filter(wrong_filter) end end module PrivateMethodOverrideFilter private def public_filter "overriden as private" end end def test_add_filter_raises_when_module_privately_overrides_registered_public_methods strainer = Context.new.strainer error = assert_raises(Liquid::MethodOverrideError) do strainer.class.add_filter(PrivateMethodOverrideFilter) end assert_equal 'Liquid error: Filter overrides registered public methods as non public: public_filter', error.message end module ProtectedMethodOverrideFilter protected def public_filter "overriden as protected" end end def test_add_filter_raises_when_module_overrides_registered_public_method_as_protected strainer = Context.new.strainer error = assert_raises(Liquid::MethodOverrideError) do strainer.class.add_filter(ProtectedMethodOverrideFilter) end assert_equal 'Liquid error: Filter overrides registered public methods as non public: public_filter', error.message end module PublicMethodOverrideFilter def public_filter "public" end end def test_add_filter_does_not_raise_when_module_overrides_previously_registered_method strainer = Context.new.strainer strainer.class.add_filter(PublicMethodOverrideFilter) assert strainer.class.filter_methods.include?('public_filter') end module LateAddedFilter def late_added_filter(input) "filtered" end end def test_global_filter_clears_cache assert_equal 'input', Strainer.create(nil).invoke('late_added_filter', 'input') Strainer.global_filter(LateAddedFilter) assert_equal 'filtered', Strainer.create(nil).invoke('late_added_filter', 'input') end end # StrainerTest