require 'contest' require 'tilt' require 'tempfile' class TiltTemplateTest < Test::Unit::TestCase class MockTemplate < Tilt::Template def prepare end end test "needs a file or block" do assert_raise(ArgumentError) { Tilt::Template.new } end test "initializing with a file" do inst = MockTemplate.new('foo.erb') {} assert_equal 'foo.erb', inst.file end test "initializing with a file and line" do inst = MockTemplate.new('foo.erb', 55) {} assert_equal 'foo.erb', inst.file assert_equal 55, inst.line end test "initializing with a tempfile" do tempfile = Tempfile.new('tilt_template_test') inst = MockTemplate.new(tempfile) assert_equal File.basename(tempfile.path), inst.basename end test "uses correct eval_file" do inst = MockTemplate.new('foo.erb', 55) {} assert_equal 'foo.erb', inst.eval_file end test "uses a default filename for #eval_file when no file provided" do inst = MockTemplate.new { 'Hi' } assert_not_nil inst.eval_file assert !inst.eval_file.include?("\n") end test "calculating template's #basename" do inst = MockTemplate.new('/tmp/templates/foo.html.erb') {} assert_equal 'foo.html.erb', inst.basename end test "calculating the template's #name" do inst = MockTemplate.new('/tmp/templates/foo.html.erb') {} assert_equal 'foo', inst.name end test "initializing with a data loading block" do MockTemplate.new { |template| "Hello World!" } end class InitializingMockTemplate < Tilt::Template @@initialized_count = 0 def self.initialized_count @@initialized_count end def initialize_engine @@initialized_count += 1 end def prepare end end test "one-time template engine initialization" do assert_nil InitializingMockTemplate.engine_initialized assert_equal 0, InitializingMockTemplate.initialized_count InitializingMockTemplate.new { "Hello World!" } assert InitializingMockTemplate.engine_initialized assert_equal 1, InitializingMockTemplate.initialized_count InitializingMockTemplate.new { "Hello World!" } assert_equal 1, InitializingMockTemplate.initialized_count end class PreparingMockTemplate < Tilt::Template include Test::Unit::Assertions def prepare assert !data.nil? @prepared = true end def prepared? ; @prepared ; end end test "raises NotImplementedError when #prepare not defined" do assert_raise(NotImplementedError) { Tilt::Template.new { |template| "Hello World!" } } end test "raises NotImplementedError when #evaluate or #template_source not defined" do inst = PreparingMockTemplate.new { |t| "Hello World!" } assert_raise(NotImplementedError) { inst.render } assert inst.prepared? end class SimpleMockTemplate < PreparingMockTemplate include Test::Unit::Assertions def evaluate(scope, locals, &block) assert prepared? assert !scope.nil? assert !locals.nil? "#{@data}" end end test "prepares and evaluates the template on #render" do inst = SimpleMockTemplate.new { |t| "Hello World!" } assert_equal "Hello World!", inst.render assert inst.prepared? end class SourceGeneratingMockTemplate < PreparingMockTemplate def precompiled_template(locals) "foo = [] ; foo << %Q{#{data}} ; foo.join" end end test "template_source with locals" do inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{name}!' } assert_equal "Hey Joe!", inst.render(Object.new, :name => 'Joe') assert inst.prepared? end test "template_source with locals of strings" do inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{name}!' } assert_equal "Hey Joe!", inst.render(Object.new, 'name' => 'Joe') assert inst.prepared? end test "template_source with locals having non-variable keys raises error" do inst = SourceGeneratingMockTemplate.new { |t| '1 + 2 = #{_answer}' } err = assert_raise(RuntimeError) { inst.render(Object.new, 'ANSWER' => 3) } assert_equal "invalid locals key: \"ANSWER\" (keys must be variable names)", err.message assert_equal "1 + 2 = 3", inst.render(Object.new, '_answer' => 3) end class Person CONSTANT = "Bob" attr_accessor :name def initialize(name) @name = name end end test "template_source with an object scope" do inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{@name}!' } scope = Person.new('Joe') assert_equal "Hey Joe!", inst.render(scope) end test "template_source with a block for yield" do inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{yield}!' } assert_equal "Hey Joe!", inst.render(Object.new){ 'Joe' } end test "template which accesses a constant" do inst = SourceGeneratingMockTemplate.new { |t| 'Hey #{CONSTANT}!' } assert_equal "Hey Bob!", inst.render(Person.new("Joe")) end end