require File.expand_path('../helper', __FILE__) describe Cutaneous do let(:template_root) { File.expand_path("../fixtures", __FILE__) } let(:engine) { Cutaneous::Engine.new(template_root, Cutaneous::FirstPassSyntax, "html") } it "Will parse & execute a simple template with expressions" do context = ContextHash(right: "right", code: "<tag/>") result = engine.render("expressions", context) result.must_equal "This is right <tag/>\n" end it "Will parse & execute a simple template with statements" do context = ContextHash(right: "right") result = engine.render("statements", context) result.must_equal "\nThis is right 0\n\nThis is right 1\n\nThis is right 2\n\n" end it "Will parse & execute a simple template with comments" do context = ContextHash(right: "right") result = engine.render("comments", context) result.must_equal "\n" end it "Will remove whitespace after tags with a closing '-'" do context = ContextHash(right: "right") result = engine.render("whitespace", context) expected = ["aa", "here 0", "here 1", "here 2\n", "ac\n", "ad\n", "ae\n", "af\n", "ag\n"].join("\n") result.must_equal expected end it "Allows you to include other templates and pass them parameters" do context = ContextHash(right: "right") result = engine.render("include", context) result.must_equal "right = right\nright = wrong\nright = left\n" end it "Honors the format parameter" do context = ContextHash(right: "right") result = engine.render("include", context, "rss") result.must_equal "right = rss\nwrong = rss\nleft = rss\n" end it "Passes instance variables onto includes" do context = ContextHash(right: "right") result = engine.render("instance", context) result.must_equal "left = wrong\n" end it "Allows you to render a template string" do context = ContextHash(right: "left") result = engine.render_string("${ right }", context) result.must_equal "left" end it "Lets you mix template tags" do context = ContextHash(right: "left") result = engine.render_string("${ right } = {{ result }}", context) result.must_equal "left = {{ result }}" end it "Has a configurable lexer class" do engine = Cutaneous::Engine.new(template_root, Cutaneous::SecondPassSyntax) context = ContextHash(right: "wrong") result = engine.render_string("${ left } = {{ right }}", context) result.must_equal "${ left } = wrong" end it "Allows for multiple template roots" do roots = Array(template_root) roots.push File.join(template_root, "other") engine = Cutaneous::Engine.new(roots, Cutaneous::FirstPassSyntax) context = ContextHash(right: "wrong") result = engine.render_string('%{ include "different" }', context) result.must_equal "wrong\n" end it "Throws a resonable error if asked to include a non-existant file" do context = ContextHash(right: "wrong") test = proc { engine.render_string('%{ include "different" }', context) } test.must_raise Cutaneous::UnknownTemplateError end it "Maintains source line numbers for exceptions" do context = ContextHash(right: "wrong") test = proc { engine.render("error", context) } test.must_raise RuntimeError backtrace = message = nil begin test.call rescue RuntimeError => e message = e.message backtrace = e.backtrace end filename, line = backtrace.first.split(":") filename.must_equal File.join(template_root, "error.html.cut") line.must_equal message end it "Maintains source line numbers for exceptions raised by includes" do context = ContextHash(right: "wrong") test = proc { engine.render("included_error", context) } test.must_raise RuntimeError backtrace = message = nil begin test.call rescue RuntimeError => e message = e.message backtrace = e.backtrace end filename, line = backtrace.first.split(":") filename.must_equal File.join(template_root, "other/error.html.cut") line.must_equal message end it "Renders proc instances as strings" do context = ContextHash(right: "wrong") template = proc { "right" } result = engine.render(template, context, "rss") result.must_equal "right" end it "Allows for configuration of the engine's default format" do engine.default_format = "rss" context = ContextHash(right: "right") result = engine.render("include", context) result.must_equal "right = rss\nwrong = rss\nleft = rss\n" end it "Accepts absolute template paths" do context = ContextHash(right: "right", code: "<tag/>") result = engine.render(File.join(template_root, "expressions"), context) result.must_equal "This is right <tag/>\n" end it "Tests for the existence of a template file for a certain format" do assert engine.template_exists?(template_root, "expressions", "html") assert engine.template_exists?(template_root, "other/error", "html") assert engine.template_exists?(template_root, "include", "rss") refute engine.template_exists?(template_root, "missing", "rss") end it "Passes any instance variables & locals between contexts" do context = ContextHash(right: "left") result1 = engine.render("instance", context) context = ContextHash(context) result2 = engine.render("instance", context) result2.must_equal result1 end it "Silently discards missing variables" do context = ContextHash(right: "left") result1 = engine.render("missing", context) result1.must_equal "missing: \n" end it "Overwrites object methods with parameters" do klass = Class.new(Object) do def monkey; "see"; end end context = TestContext.new(klass.new) result = engine.render_string("${ monkey }", context) result.must_equal "see" context = TestContext.new(klass.new, monkey: "magic") result = engine.render_string("${ monkey }", context) result.must_equal "magic" end end