cmlenz@1: # -*- coding: utf-8 -*-
cmlenz@1: #
cmlenz@66: # Copyright (C) 2006 Edgewall Software
cmlenz@1: # All rights reserved.
cmlenz@1: #
cmlenz@1: # This software is licensed as described in the file COPYING, which
cmlenz@1: # you should have received as part of this distribution. The terms
cmlenz@66: # are also available at http://markup.edgewall.org/wiki/License.
cmlenz@1: #
cmlenz@1: # This software consists of voluntary contributions made by many
cmlenz@1: # individuals. For the exact contribution history, see the revision
cmlenz@66: # history and logs, available at http://markup.edgewall.org/log/.
cmlenz@1:
cmlenz@1: import doctest
cmlenz@152: import os
cmlenz@1: import unittest
cmlenz@152: import shutil
cmlenz@1: import sys
cmlenz@152: import tempfile
cmlenz@1:
cmlenz@54: from markup.core import Markup, Stream
cmlenz@152: from markup.template import BadDirectiveError, Template, TemplateLoader, \
cmlenz@152: TemplateSyntaxError
cmlenz@1:
cmlenz@1:
cmlenz@50: class AttrsDirectiveTestCase(unittest.TestCase):
cmlenz@50: """Tests for the `py:attrs` template directive."""
cmlenz@50:
cmlenz@50: def test_combined_with_loop(self):
cmlenz@50: """
cmlenz@50: Verify that the directive has access to the loop variables.
cmlenz@50: """
cmlenz@61: tmpl = Template("""
cmlenz@50:
cmlenz@50: """)
cmlenz@50: items = [{'id': 1, 'class': 'foo'}, {'id': 2, 'class': 'bar'}]
cmlenz@50: self.assertEqual("""
cmlenz@50:
cmlenz@149: """, str(tmpl.generate(items=items)))
cmlenz@50:
cmlenz@54: def test_update_existing_attr(self):
cmlenz@54: """
cmlenz@54: Verify that an attribute value that evaluates to `None` removes an
cmlenz@54: existing attribute of that name.
cmlenz@54: """
cmlenz@61: tmpl = Template("""
cmlenz@54:
cmlenz@54: """)
cmlenz@54: self.assertEqual("""
cmlenz@54:
cmlenz@54: """, str(tmpl.generate()))
cmlenz@54:
cmlenz@54: def test_remove_existing_attr(self):
cmlenz@54: """
cmlenz@54: Verify that an attribute value that evaluates to `None` removes an
cmlenz@54: existing attribute of that name.
cmlenz@54: """
cmlenz@61: tmpl = Template("""
cmlenz@54:
cmlenz@54: """)
cmlenz@54: self.assertEqual("""
cmlenz@54:
cmlenz@54: """, str(tmpl.generate()))
cmlenz@54:
cmlenz@50:
cmlenz@53: class ChooseDirectiveTestCase(unittest.TestCase):
cmlenz@53: """Tests for the `py:choose` template directive and the complementary
cmlenz@53: directives `py:when` and `py:otherwise`."""
cmlenz@53:
cmlenz@53: def test_multiple_true_whens(self):
cmlenz@53: """
cmlenz@53: Verify that, if multiple `py:when` bodies match, only the first is
cmlenz@53: output.
cmlenz@53: """
cmlenz@61: tmpl = Template("""
cmlenz@53: 1
cmlenz@53: 2
cmlenz@53: 3
cmlenz@53:
""")
cmlenz@53: self.assertEqual("""
cmlenz@53: 1
cmlenz@53:
""", str(tmpl.generate()))
cmlenz@53:
cmlenz@53: def test_otherwise(self):
cmlenz@61: tmpl = Template("""
cmlenz@53: hidden
cmlenz@53: hello
cmlenz@53:
""")
cmlenz@53: self.assertEqual("""
cmlenz@53: hello
cmlenz@53:
""", str(tmpl.generate()))
cmlenz@53:
cmlenz@53: def test_nesting(self):
cmlenz@53: """
cmlenz@53: Verify that `py:choose` blocks can be nested:
cmlenz@53: """
cmlenz@61: tmpl = Template("""
cmlenz@53:
cmlenz@53:
cmlenz@53: 2
cmlenz@53: 3
cmlenz@53:
cmlenz@53:
cmlenz@53: """)
cmlenz@53: self.assertEqual("""
cmlenz@53:
cmlenz@53:
cmlenz@53: 3
cmlenz@53:
cmlenz@53:
cmlenz@53: """, str(tmpl.generate()))
cmlenz@53:
cmlenz@202: def test_complex_nesting(self):
cmlenz@202: """
cmlenz@202: Verify more complex nesting.
cmlenz@202: """
cmlenz@202: tmpl = Template("""
cmlenz@202:
cmlenz@202:
cmlenz@202: OK
cmlenz@202: FAIL
cmlenz@202:
cmlenz@202:
cmlenz@202: """)
cmlenz@202: self.assertEqual("""
cmlenz@202:
cmlenz@202:
cmlenz@202: OK
cmlenz@202:
cmlenz@202:
cmlenz@202: """, str(tmpl.generate()))
cmlenz@202:
cmlenz@202: def test_complex_nesting_otherwise(self):
cmlenz@202: """
cmlenz@202: Verify more complex nesting using otherwise.
cmlenz@202: """
cmlenz@202: tmpl = Template("""
cmlenz@202:
cmlenz@202:
cmlenz@202: FAIL
cmlenz@202: OK
cmlenz@202:
cmlenz@202:
cmlenz@202: """)
cmlenz@202: self.assertEqual("""
cmlenz@202:
cmlenz@202:
cmlenz@202: OK
cmlenz@202:
cmlenz@202:
cmlenz@202: """, str(tmpl.generate()))
cmlenz@202:
cmlenz@53: def test_when_with_strip(self):
cmlenz@53: """
cmlenz@53: Verify that a when directive with a strip directive actually strips of
cmlenz@53: the outer element.
cmlenz@53: """
cmlenz@61: tmpl = Template("""
cmlenz@53:
cmlenz@53: foo
cmlenz@53:
cmlenz@53: """)
cmlenz@53: self.assertEqual("""
cmlenz@53: foo
cmlenz@53: """, str(tmpl.generate()))
cmlenz@53:
cmlenz@166: def test_when_outside_choose(self):
cmlenz@166: """
cmlenz@166: Verify that a `when` directive outside of a `choose` directive is
cmlenz@166: reported as an error.
cmlenz@166: """
cmlenz@166: tmpl = Template("""
cmlenz@166:
cmlenz@166: """)
cmlenz@166: self.assertRaises(TemplateSyntaxError, str, tmpl.generate())
cmlenz@166:
cmlenz@181: def test_otherwise_outside_choose(self):
cmlenz@166: """
cmlenz@166: Verify that an `otherwise` directive outside of a `choose` directive is
cmlenz@166: reported as an error.
cmlenz@166: """
cmlenz@166: tmpl = Template("""
cmlenz@166:
cmlenz@166: """)
cmlenz@166: self.assertRaises(TemplateSyntaxError, str, tmpl.generate())
cmlenz@166:
cmlenz@181: def test_when_without_test(self):
cmlenz@181: """
cmlenz@181: Verify that an `when` directive that doesn't have a `test` attribute
cmlenz@181: is reported as an error.
cmlenz@181: """
cmlenz@181: tmpl = Template("""
cmlenz@181:
cmlenz@181:
foo
cmlenz@181:
cmlenz@181: """)
cmlenz@181: self.assertRaises(TemplateSyntaxError, str, tmpl.generate())
cmlenz@181:
cmlenz@181: def test_otherwise_without_test(self):
cmlenz@181: """
cmlenz@181: Verify that an `otherwise` directive can be used without a `test`
cmlenz@181: attribute.
cmlenz@181: """
cmlenz@181: tmpl = Template("""
cmlenz@181:
cmlenz@181:
foo
cmlenz@181:
cmlenz@181: """)
cmlenz@181: self.assertEqual("""
cmlenz@181: foo
cmlenz@181: """, str(tmpl.generate()))
cmlenz@181:
cmlenz@65: def test_as_element(self):
cmlenz@65: """
cmlenz@65: Verify that the directive can also be used as an element.
cmlenz@65: """
cmlenz@65: tmpl = Template("""
cmlenz@65:
cmlenz@65: 1
cmlenz@65: 2
cmlenz@65: 3
cmlenz@65:
cmlenz@65: """)
cmlenz@65: self.assertEqual("""
cmlenz@65: 1
cmlenz@65: """, str(tmpl.generate()))
cmlenz@65:
cmlenz@53:
cmlenz@50: class DefDirectiveTestCase(unittest.TestCase):
cmlenz@50: """Tests for the `py:def` template directive."""
cmlenz@50:
cmlenz@50: def test_function_with_strip(self):
cmlenz@50: """
cmlenz@53: Verify that a named template function with a strip directive actually
cmlenz@53: strips of the outer element.
cmlenz@50: """
cmlenz@61: tmpl = Template("""
cmlenz@50:
cmlenz@50: ${what}
cmlenz@50:
cmlenz@50: ${echo('foo')}
cmlenz@50: """)
cmlenz@50: self.assertEqual("""
cmlenz@50: foo
cmlenz@50: """, str(tmpl.generate()))
cmlenz@50:
cmlenz@90: def test_exec_in_replace(self):
cmlenz@90: tmpl = Template("""
cmlenz@90:
cmlenz@90: ${greeting}, ${name}!
cmlenz@90:
cmlenz@90:
cmlenz@90:
""")
cmlenz@90: self.assertEqual("""
cmlenz@90:
cmlenz@90: hello, world!
cmlenz@90:
cmlenz@90:
""", str(tmpl.generate()))
cmlenz@90:
cmlenz@65: def test_as_element(self):
cmlenz@65: """
cmlenz@65: Verify that the directive can also be used as an element.
cmlenz@65: """
cmlenz@65: tmpl = Template("""
cmlenz@65:
cmlenz@65: ${what}
cmlenz@65:
cmlenz@65: ${echo('foo')}
cmlenz@65: """)
cmlenz@65: self.assertEqual("""
cmlenz@65: foo
cmlenz@65: """, str(tmpl.generate()))
cmlenz@65:
cmlenz@154: def test_nested_defs(self):
cmlenz@154: """
cmlenz@154: Verify that a template function defined inside a conditional block can
cmlenz@154: be called from outside that block.
cmlenz@154: """
cmlenz@154: tmpl = Template("""
cmlenz@154:
cmlenz@154: ${what}
cmlenz@154:
cmlenz@154:
cmlenz@154: ${what}
cmlenz@154:
cmlenz@154: ${echo('foo')}
cmlenz@154: """)
cmlenz@154: self.assertEqual("""
cmlenz@154: foo
cmlenz@154: """, str(tmpl.generate(semantic=True)))
cmlenz@154:
cmlenz@165: def test_function_with_default_arg(self):
cmlenz@165: """
cmlenz@165: Verify that keyword arguments work with `py:def` directives.
cmlenz@165: """
cmlenz@165: tmpl = Template("""
cmlenz@165: ${what}
cmlenz@165: ${echo('foo')}
cmlenz@165: """)
cmlenz@165: self.assertEqual("""
cmlenz@165: foo
cmlenz@165: """, str(tmpl.generate()))
cmlenz@165:
cmlenz@185: def test_invocation_in_attribute(self):
cmlenz@185: tmpl = Template("""
cmlenz@185: ${what or 'something'}
cmlenz@185: bar
cmlenz@185: """)
cmlenz@185: self.assertEqual("""
cmlenz@185: bar
cmlenz@185: """, str(tmpl.generate()))
cmlenz@185:
cmlenz@185: def test_invocation_in_attribute_none(self):
cmlenz@185: tmpl = Template("""
cmlenz@185: ${None}
cmlenz@185: bar
cmlenz@185: """)
cmlenz@185: self.assertEqual("""
cmlenz@185: bar
cmlenz@185: """, str(tmpl.generate()))
cmlenz@185:
cmlenz@206: def test_function_raising_typeerror(self):
cmlenz@206: def badfunc():
cmlenz@206: raise TypeError
cmlenz@206: tmpl = Template("""
cmlenz@206:
cmlenz@206: ${badfunc()}
cmlenz@206:
cmlenz@206:
cmlenz@206: """)
cmlenz@206: self.assertRaises(TypeError, list, tmpl.generate(badfunc=badfunc))
cmlenz@206:
cmlenz@208: def test_def_in_matched(self):
cmlenz@208: tmpl = Template("""
cmlenz@208: ${select('*')}
cmlenz@208:
cmlenz@208:
cmlenz@208: ${maketitle(True)}
cmlenz@208:
cmlenz@208: """)
cmlenz@208: self.assertEqual("""
cmlenz@208: True
cmlenz@208: """, str(tmpl.generate()))
cmlenz@208:
cmlenz@50:
cmlenz@51: class ForDirectiveTestCase(unittest.TestCase):
cmlenz@53: """Tests for the `py:for` template directive."""
cmlenz@51:
cmlenz@51: def test_loop_with_strip(self):
cmlenz@51: """
cmlenz@53: Verify that the combining the `py:for` directive with `py:strip` works
cmlenz@53: correctly.
cmlenz@51: """
cmlenz@61: tmpl = Template("""
cmlenz@51:
cmlenz@51: ${item}
cmlenz@51:
cmlenz@51: """)
cmlenz@51: self.assertEqual("""
cmlenz@51: 1
cmlenz@51: 2
cmlenz@51: 3
cmlenz@51: 4
cmlenz@51: 5
cmlenz@149: """, str(tmpl.generate(items=range(1, 6))))
cmlenz@51:
cmlenz@65: def test_as_element(self):
cmlenz@65: """
cmlenz@65: Verify that the directive can also be used as an element.
cmlenz@65: """
cmlenz@65: tmpl = Template("""
cmlenz@65:
cmlenz@65: ${item}
cmlenz@65:
cmlenz@65: """)
cmlenz@65: self.assertEqual("""
cmlenz@65: 1
cmlenz@65: 2
cmlenz@65: 3
cmlenz@65: 4
cmlenz@65: 5
cmlenz@149: """, str(tmpl.generate(items=range(1, 6))))
cmlenz@65:
cmlenz@65:
cmlenz@65: class IfDirectiveTestCase(unittest.TestCase):
cmlenz@65: """Tests for the `py:if` template directive."""
cmlenz@65:
cmlenz@65: def test_loop_with_strip(self):
cmlenz@65: """
cmlenz@65: Verify that the combining the `py:if` directive with `py:strip` works
cmlenz@65: correctly.
cmlenz@65: """
cmlenz@65: tmpl = Template("""
cmlenz@65: ${bar}
cmlenz@65: """)
cmlenz@65: self.assertEqual("""
cmlenz@65: Hello
cmlenz@149: """, str(tmpl.generate(foo=True, bar='Hello')))
cmlenz@65:
cmlenz@65: def test_as_element(self):
cmlenz@65: """
cmlenz@65: Verify that the directive can also be used as an element.
cmlenz@65: """
cmlenz@65: tmpl = Template("""
cmlenz@65: ${bar}
cmlenz@65: """)
cmlenz@65: self.assertEqual("""
cmlenz@65: Hello
cmlenz@149: """, str(tmpl.generate(foo=True, bar='Hello')))
cmlenz@65:
cmlenz@51:
cmlenz@36: class MatchDirectiveTestCase(unittest.TestCase):
cmlenz@36: """Tests for the `py:match` template directive."""
cmlenz@36:
cmlenz@50: def test_with_strip(self):
cmlenz@50: """
cmlenz@50: Verify that a match template can produce the same kind of element that
cmlenz@50: it matched without entering an infinite recursion.
cmlenz@50: """
cmlenz@61: tmpl = Template("""
cmlenz@50:
cmlenz@216: ${select('text()')}
cmlenz@50:
cmlenz@50: Hey Joe
cmlenz@50: """)
cmlenz@50: self.assertEqual("""
cmlenz@50: Hey Joe
cmlenz@50: """, str(tmpl.generate()))
cmlenz@50:
cmlenz@36: def test_without_strip(self):
cmlenz@36: """
cmlenz@36: Verify that a match template can produce the same kind of element that
cmlenz@36: it matched without entering an infinite recursion.
cmlenz@36: """
cmlenz@61: tmpl = Template("""
cmlenz@36:
cmlenz@216: ${select('text()')}
cmlenz@36:
cmlenz@36: Hey Joe
cmlenz@37: """)
cmlenz@36: self.assertEqual("""
cmlenz@36:
cmlenz@36: Hey Joe
cmlenz@36:
cmlenz@36: """, str(tmpl.generate()))
cmlenz@36:
cmlenz@65: def test_as_element(self):
cmlenz@65: """
cmlenz@65: Verify that the directive can also be used as an element.
cmlenz@65: """
cmlenz@65: tmpl = Template("""
cmlenz@65:
cmlenz@216: ${select('text()')}
cmlenz@65:
cmlenz@65: Hey Joe
cmlenz@65: """)
cmlenz@65: self.assertEqual("""
cmlenz@65: Hey Joe
cmlenz@65: """, str(tmpl.generate()))
cmlenz@65:
cmlenz@36: def test_recursive_match_1(self):
cmlenz@36: """
cmlenz@36: Match directives are applied recursively, meaning that they are also
cmlenz@36: applied to any content they may have produced themselves:
cmlenz@36: """
cmlenz@61: tmpl = Template("""
cmlenz@36:
cmlenz@36:
cmlenz@216: ${select('*')}
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@37: """)
cmlenz@36: self.assertEqual("""
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36: """, str(tmpl.generate()))
cmlenz@36:
cmlenz@36: def test_recursive_match_2(self):
cmlenz@36: """
cmlenz@36: When two or more match templates match the same element and also
cmlenz@36: themselves output the element they match, avoiding recursion is even
cmlenz@36: more complex, but should work.
cmlenz@36: """
cmlenz@61: tmpl = Template("""
cmlenz@36:
cmlenz@36:
cmlenz@216: ${select('*')}
cmlenz@36:
cmlenz@36:
cmlenz@216: ${select('*')}
cmlenz@36:
cmlenz@36:
cmlenz@36:
cmlenz@36: Foo
cmlenz@36:
cmlenz@37: """)
cmlenz@36: self.assertEqual("""
cmlenz@36:
cmlenz@36: Foo
cmlenz@36:
cmlenz@36:
cmlenz@36: """, str(tmpl.generate()))
cmlenz@36:
cmlenz@77: def test_select_all_attrs(self):
cmlenz@77: tmpl = Template("""
cmlenz@77:
cmlenz@216: ${select('text()')}
cmlenz@77:
cmlenz@77: Hey Joe
cmlenz@77: """)
cmlenz@77: self.assertEqual("""
cmlenz@77:
cmlenz@77: Hey Joe
cmlenz@77:
cmlenz@77: """, str(tmpl.generate()))
cmlenz@77:
cmlenz@77: def test_select_all_attrs_empty(self):
cmlenz@77: tmpl = Template("""
cmlenz@77:
cmlenz@216: ${select('text()')}
cmlenz@77:
cmlenz@77: Hey Joe
cmlenz@77: """)
cmlenz@77: self.assertEqual("""
cmlenz@77:
cmlenz@77: Hey Joe
cmlenz@77:
cmlenz@77: """, str(tmpl.generate()))
cmlenz@77:
cmlenz@77: def test_select_all_attrs_in_body(self):
cmlenz@77: tmpl = Template("""
cmlenz@77:
cmlenz@77: Hey ${select('text()')} ${select('@*')}
cmlenz@77:
cmlenz@77: Joe
cmlenz@77: """)
cmlenz@77: self.assertEqual("""
cmlenz@77:
cmlenz@77: Hey Joe Cool
cmlenz@77:
cmlenz@77: """, str(tmpl.generate()))
cmlenz@77:
cmlenz@172: def test_def_in_match(self):
cmlenz@172: tmpl = Template("""
cmlenz@172:
cmlenz@172: ${select('*')}
cmlenz@172: ${maketitle(True)}
cmlenz@172: """)
cmlenz@172: self.assertEqual("""
cmlenz@172: True
cmlenz@172: """, str(tmpl.generate()))
cmlenz@172:
cmlenz@179: def test_match_with_xpath_variable(self):
cmlenz@179: tmpl = Template("""
cmlenz@179:
cmlenz@179: Hello ${select('@name')}
cmlenz@179:
cmlenz@179:
cmlenz@179:
""")
cmlenz@179: self.assertEqual("""
cmlenz@179:
cmlenz@179: Hello Dude
cmlenz@179:
cmlenz@179:
""", str(tmpl.generate(tagname='greeting')))
cmlenz@179: self.assertEqual("""
cmlenz@179:
cmlenz@179:
""", str(tmpl.generate(tagname='sayhello')))
cmlenz@179:
cmlenz@210: def test_content_directive_in_match(self):
cmlenz@210: tmpl = Template("""
cmlenz@210: I said something
.
cmlenz@210: bar
cmlenz@210: """)
cmlenz@210: self.assertEqual("""
cmlenz@210: I said bar
.
cmlenz@210: """, str(tmpl.generate()))
cmlenz@210:
cmlenz@211: def test_cascaded_matches(self):
cmlenz@211: tmpl = Template("""
cmlenz@211: ${select('*')}
cmlenz@211: ${select('title')}
cmlenz@211: ${select('*')}
cmlenz@211: Welcome to Markup
cmlenz@211: Are you ready to mark up?
cmlenz@211: """)
cmlenz@211: self.assertEqual("""
cmlenz@211: Welcome to Markup
cmlenz@211: Are you ready to mark up?
cmlenz@211: """, str(tmpl.generate()))
cmlenz@211:
cmlenz@184: # FIXME
cmlenz@184: #def test_match_after_step(self):
cmlenz@184: # tmpl = Template("""
cmlenz@184: #
cmlenz@184: # Hello ${select('@name')}
cmlenz@184: #
cmlenz@184: #
cmlenz@184: #
""")
cmlenz@184: # self.assertEqual("""
cmlenz@184: #
cmlenz@184: # Hello Dude
cmlenz@184: #
cmlenz@184: #
""", str(tmpl.generate()))
cmlenz@184:
cmlenz@36:
cmlenz@37: class StripDirectiveTestCase(unittest.TestCase):
cmlenz@37: """Tests for the `py:strip` template directive."""
cmlenz@37:
cmlenz@37: def test_strip_false(self):
cmlenz@61: tmpl = Template("""
cmlenz@37:
foo
cmlenz@37:
""")
cmlenz@37: self.assertEqual("""
cmlenz@37:
foo
cmlenz@37:
""", str(tmpl.generate()))
cmlenz@37:
cmlenz@37: def test_strip_empty(self):
cmlenz@61: tmpl = Template("""
cmlenz@37:
foo
cmlenz@37:
""")
cmlenz@37: self.assertEqual("""
cmlenz@37: foo
cmlenz@37:
""", str(tmpl.generate()))
cmlenz@37:
cmlenz@37:
cmlenz@104: class WithDirectiveTestCase(unittest.TestCase):
cmlenz@104: """Tests for the `py:with` template directive."""
cmlenz@104:
cmlenz@104: def test_shadowing(self):
cmlenz@104: tmpl = Template("""
cmlenz@104: ${x}
cmlenz@104:
cmlenz@104: ${x}
cmlenz@104:
""")
cmlenz@104: self.assertEqual("""
cmlenz@104: 42
cmlenz@104: 84
cmlenz@104: 42
cmlenz@149:
""", str(tmpl.generate(x=42)))
cmlenz@104:
cmlenz@104: def test_as_element(self):
cmlenz@104: tmpl = Template("""
cmlenz@104:
${x}
cmlenz@104:
""")
cmlenz@104: self.assertEqual("""
cmlenz@104: 84
cmlenz@149:
""", str(tmpl.generate(x=42)))
cmlenz@104:
cmlenz@190: def test_multiple_vars_same_name(self):
cmlenz@190: tmpl = Template("""
cmlenz@190:
cmlenz@190: $foo
cmlenz@190:
cmlenz@190:
""")
cmlenz@190: self.assertEqual("""
cmlenz@190: baz
cmlenz@190:
""", str(tmpl.generate(x=42)))
cmlenz@190:
cmlenz@190: def test_multiple_vars_single_assignment(self):
cmlenz@190: tmpl = Template("""
cmlenz@190:
${x} ${y} ${z}
cmlenz@190:
""")
cmlenz@190: self.assertEqual("""
cmlenz@190: 1 1 1
cmlenz@190:
""", str(tmpl.generate(x=42)))
cmlenz@190:
cmlenz@190: def test_multiple_vars_trailing_semicolon(self):
cmlenz@190: tmpl = Template("""
cmlenz@190:
${x} ${y}
cmlenz@190:
""")
cmlenz@190: self.assertEqual("""
cmlenz@190: 84 42
cmlenz@190:
""", str(tmpl.generate(x=42)))
cmlenz@190:
cmlenz@190: def test_semicolon_escape(self):
cmlenz@190: tmpl = Template("""
cmlenz@190:
cmlenz@190: ${x}
cmlenz@190: ${y}
cmlenz@190:
cmlenz@190:
""")
cmlenz@190: self.assertEqual("""
cmlenz@190: here is a semicolon: ;
cmlenz@190: here are two semicolons: ;;
cmlenz@190:
""", str(tmpl.generate()))
cmlenz@190:
cmlenz@104:
cmlenz@1: class TemplateTestCase(unittest.TestCase):
cmlenz@36: """Tests for basic template processing, expression evaluation and error
cmlenz@36: reporting.
cmlenz@36: """
cmlenz@1:
cmlenz@1: def test_interpolate_string(self):
cmlenz@1: parts = list(Template._interpolate('bla'))
cmlenz@1: self.assertEqual(1, len(parts))
cmlenz@1: self.assertEqual(Stream.TEXT, parts[0][0])
cmlenz@1: self.assertEqual('bla', parts[0][1])
cmlenz@1:
cmlenz@1: def test_interpolate_simple(self):
cmlenz@1: parts = list(Template._interpolate('${bla}'))
cmlenz@1: self.assertEqual(1, len(parts))
cmlenz@10: self.assertEqual(Template.EXPR, parts[0][0])
cmlenz@1: self.assertEqual('bla', parts[0][1].source)
cmlenz@1:
cmlenz@1: def test_interpolate_escaped(self):
cmlenz@1: parts = list(Template._interpolate('$${bla}'))
cmlenz@1: self.assertEqual(1, len(parts))
cmlenz@1: self.assertEqual(Stream.TEXT, parts[0][0])
cmlenz@1: self.assertEqual('${bla}', parts[0][1])
cmlenz@1:
cmlenz@1: def test_interpolate_short(self):
cmlenz@1: parts = list(Template._interpolate('$bla'))
cmlenz@1: self.assertEqual(1, len(parts))
cmlenz@10: self.assertEqual(Template.EXPR, parts[0][0])
cmlenz@1: self.assertEqual('bla', parts[0][1].source)
cmlenz@1:
cmlenz@1: def test_interpolate_mixed1(self):
cmlenz@1: parts = list(Template._interpolate('$foo bar $baz'))
cmlenz@1: self.assertEqual(3, len(parts))
cmlenz@10: self.assertEqual(Template.EXPR, parts[0][0])
cmlenz@1: self.assertEqual('foo', parts[0][1].source)
cmlenz@1: self.assertEqual(Stream.TEXT, parts[1][0])
cmlenz@1: self.assertEqual(' bar ', parts[1][1])
cmlenz@10: self.assertEqual(Template.EXPR, parts[2][0])
cmlenz@1: self.assertEqual('baz', parts[2][1].source)
cmlenz@1:
cmlenz@1: def test_interpolate_mixed2(self):
cmlenz@1: parts = list(Template._interpolate('foo $bar baz'))
cmlenz@1: self.assertEqual(3, len(parts))
cmlenz@1: self.assertEqual(Stream.TEXT, parts[0][0])
cmlenz@1: self.assertEqual('foo ', parts[0][1])
cmlenz@10: self.assertEqual(Template.EXPR, parts[1][0])
cmlenz@1: self.assertEqual('bar', parts[1][1].source)
cmlenz@1: self.assertEqual(Stream.TEXT, parts[2][0])
cmlenz@1: self.assertEqual(' baz', parts[2][1])
cmlenz@1:
cmlenz@74: def test_interpolate_mixed3(self):
cmlenz@74: tmpl = Template(' ${var} $var')
cmlenz@149: self.assertEqual(' 42 42', str(tmpl.generate(var=42)))
cmlenz@74:
cmlenz@191: def test_interpolate_leading_trailing_space(self):
cmlenz@191: tmpl = Template('${ foo }')
cmlenz@191: self.assertEqual('bar', str(tmpl.generate(foo='bar')))
cmlenz@191:
cmlenz@184: def test_interpolate_multiline(self):
cmlenz@184: tmpl = Template("""${dict(
cmlenz@184: bar = 'baz'
cmlenz@184: )[foo]}""")
cmlenz@184: self.assertEqual('baz', str(tmpl.generate(foo='bar')))
cmlenz@184:
mgood@48: def test_interpolate_non_string_attrs(self):
mgood@48: tmpl = Template('')
cmlenz@75: self.assertEqual('', str(tmpl.generate()))
cmlenz@75:
cmlenz@145: def test_interpolate_list_result(self):
cmlenz@145: tmpl = Template('$foo')
cmlenz@149: self.assertEqual('buzz', str(tmpl.generate(foo=('buzz',))))
cmlenz@145:
cmlenz@75: def test_empty_attr(self):
cmlenz@75: tmpl = Template('')
cmlenz@75: self.assertEqual('', str(tmpl.generate()))
mgood@48:
cmlenz@1: def test_bad_directive_error(self):
cmlenz@61: xml = ''
cmlenz@1: try:
cmlenz@21: tmpl = Template(xml, filename='test.html')
cmlenz@1: except BadDirectiveError, e:
cmlenz@1: self.assertEqual('test.html', e.filename)
cmlenz@1: if sys.version_info[:2] >= (2, 4):
cmlenz@1: self.assertEqual(1, e.lineno)
cmlenz@1:
cmlenz@1: def test_directive_value_syntax_error(self):
cmlenz@81: xml = """"""
cmlenz@1: try:
cmlenz@81: tmpl = Template(xml, filename='test.html')
cmlenz@1: self.fail('Expected SyntaxError')
cmlenz@1: except TemplateSyntaxError, e:
cmlenz@1: self.assertEqual('test.html', e.filename)
cmlenz@1: if sys.version_info[:2] >= (2, 4):
cmlenz@1: self.assertEqual(1, e.lineno)
cmlenz@1:
cmlenz@1: def test_expression_syntax_error(self):
cmlenz@81: xml = """
cmlenz@81: Foo ${bar"}
cmlenz@81:
"""
cmlenz@1: try:
cmlenz@81: tmpl = Template(xml, filename='test.html')
cmlenz@1: self.fail('Expected SyntaxError')
cmlenz@1: except TemplateSyntaxError, e:
cmlenz@1: self.assertEqual('test.html', e.filename)
cmlenz@1: if sys.version_info[:2] >= (2, 4):
cmlenz@1: self.assertEqual(2, e.lineno)
cmlenz@1:
cmlenz@134: def test_expression_syntax_error_multi_line(self):
cmlenz@134: xml = """
cmlenz@134:
cmlenz@134: ${bar"}
cmlenz@134:
cmlenz@134:
"""
cmlenz@134: try:
cmlenz@134: tmpl = Template(xml, filename='test.html')
cmlenz@134: self.fail('Expected SyntaxError')
cmlenz@134: except TemplateSyntaxError, e:
cmlenz@134: self.assertEqual('test.html', e.filename)
cmlenz@134: if sys.version_info[:2] >= (2, 4):
cmlenz@134: self.assertEqual(3, e.lineno)
cmlenz@134:
cmlenz@54: def test_markup_noescape(self):
cmlenz@54: """
cmlenz@54: Verify that outputting context data that is a `Markup` instance is not
cmlenz@54: escaped.
cmlenz@54: """
cmlenz@61: tmpl = Template("""
cmlenz@54: $myvar
cmlenz@54:
""")
cmlenz@54: self.assertEqual("""
cmlenz@54: foo
cmlenz@149:
""", str(tmpl.generate(myvar=Markup('foo'))))
cmlenz@54:
cmlenz@54: def test_text_noescape_quotes(self):
cmlenz@54: """
cmlenz@54: Verify that outputting context data in text nodes doesn't escape quotes.
cmlenz@54: """
cmlenz@61: tmpl = Template("""
cmlenz@54: $myvar
cmlenz@54:
""")
cmlenz@54: self.assertEqual("""
cmlenz@54: "foo"
cmlenz@149:
""", str(tmpl.generate(myvar='"foo"')))
cmlenz@54:
cmlenz@54: def test_attr_escape_quotes(self):
cmlenz@54: """
cmlenz@54: Verify that outputting context data in attribtes escapes quotes.
cmlenz@54: """
cmlenz@61: tmpl = Template("""
cmlenz@54:
cmlenz@54:
""")
cmlenz@54: self.assertEqual("""
cmlenz@54:
cmlenz@149:
""", str(tmpl.generate(myvar='"foo"')))
cmlenz@54:
cmlenz@65: def test_directive_element(self):
cmlenz@65: tmpl = Template("""
cmlenz@65:
bar
cmlenz@65:
""")
cmlenz@65: self.assertEqual("""
cmlenz@65: bar
cmlenz@149:
""", str(tmpl.generate(myvar='"foo"')))
cmlenz@65:
cmlenz@89: def test_normal_comment(self):
cmlenz@89: tmpl = Template("""
cmlenz@89:
cmlenz@89:
""")
cmlenz@89: self.assertEqual("""
cmlenz@89:
cmlenz@89:
""", str(tmpl.generate()))
cmlenz@89:
cmlenz@89: def test_template_comment(self):
cmlenz@89: tmpl = Template("""
cmlenz@89:
cmlenz@89:
cmlenz@89:
""")
cmlenz@89: self.assertEqual("""
cmlenz@89:
""", str(tmpl.generate()))
cmlenz@89:
cmlenz@1:
cmlenz@152: class TemplateLoaderTestCase(unittest.TestCase):
cmlenz@152: """Tests for the template loader."""
cmlenz@152:
cmlenz@152: def setUp(self):
cmlenz@152: self.dirname = tempfile.mkdtemp(suffix='markup_test')
cmlenz@152:
cmlenz@152: def tearDown(self):
cmlenz@152: shutil.rmtree(self.dirname)
cmlenz@152:
cmlenz@152: def test_relative_include_samedir(self):
cmlenz@152: file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
cmlenz@152: try:
cmlenz@152: file1.write("""Included
""")
cmlenz@152: finally:
cmlenz@152: file1.close()
cmlenz@152:
cmlenz@152: file2 = open(os.path.join(self.dirname, 'tmpl2.html'), 'w')
cmlenz@152: try:
cmlenz@152: file2.write("""
cmlenz@158:
cmlenz@158: """)
cmlenz@152: finally:
cmlenz@152: file2.close()
cmlenz@152:
cmlenz@152: loader = TemplateLoader([self.dirname])
cmlenz@152: tmpl = loader.load('tmpl2.html')
cmlenz@152: self.assertEqual("""
cmlenz@158: Included
cmlenz@158: """, tmpl.generate().render())
cmlenz@152:
cmlenz@152: def test_relative_include_subdir(self):
cmlenz@152: os.mkdir(os.path.join(self.dirname, 'sub'))
cmlenz@152: file1 = open(os.path.join(self.dirname, 'sub', 'tmpl1.html'), 'w')
cmlenz@152: try:
cmlenz@152: file1.write("""Included
""")
cmlenz@152: finally:
cmlenz@152: file1.close()
cmlenz@152:
cmlenz@152: file2 = open(os.path.join(self.dirname, 'tmpl2.html'), 'w')
cmlenz@152: try:
cmlenz@152: file2.write("""
cmlenz@158:
cmlenz@158: """)
cmlenz@152: finally:
cmlenz@152: file2.close()
cmlenz@152:
cmlenz@152: loader = TemplateLoader([self.dirname])
cmlenz@152: tmpl = loader.load('tmpl2.html')
cmlenz@152: self.assertEqual("""
cmlenz@158: Included
cmlenz@158: """, tmpl.generate().render())
cmlenz@152:
cmlenz@152: def test_relative_include_parentdir(self):
cmlenz@152: file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
cmlenz@152: try:
cmlenz@152: file1.write("""Included
""")
cmlenz@152: finally:
cmlenz@152: file1.close()
cmlenz@152:
cmlenz@152: os.mkdir(os.path.join(self.dirname, 'sub'))
cmlenz@152: file2 = open(os.path.join(self.dirname, 'sub', 'tmpl2.html'), 'w')
cmlenz@152: try:
cmlenz@152: file2.write("""
cmlenz@158:
cmlenz@158: """)
cmlenz@152: finally:
cmlenz@152: file2.close()
cmlenz@152:
cmlenz@152: loader = TemplateLoader([self.dirname])
cmlenz@152: tmpl = loader.load('sub/tmpl2.html')
cmlenz@152: self.assertEqual("""
cmlenz@158: Included
cmlenz@158: """, tmpl.generate().render())
cmlenz@152:
cmlenz@174: def test_relative_include_without_search_path(self):
cmlenz@174: file1 = open(os.path.join(self.dirname, 'tmpl1.html'), 'w')
cmlenz@174: try:
cmlenz@174: file1.write("""Included
""")
cmlenz@174: finally:
cmlenz@174: file1.close()
cmlenz@174:
cmlenz@174: file2 = open(os.path.join(self.dirname, 'tmpl2.html'), 'w')
cmlenz@174: try:
cmlenz@174: file2.write("""
cmlenz@174:
cmlenz@174: """)
cmlenz@174: finally:
cmlenz@174: file2.close()
cmlenz@174:
cmlenz@174: loader = TemplateLoader()
cmlenz@175: tmpl = loader.load(os.path.join(self.dirname, 'tmpl2.html'))
cmlenz@174: self.assertEqual("""
cmlenz@174: Included
cmlenz@174: """, tmpl.generate().render())
cmlenz@174:
cmlenz@152:
cmlenz@1: def suite():
cmlenz@1: suite = unittest.TestSuite()
cmlenz@1: suite.addTest(doctest.DocTestSuite(Template.__module__))
cmlenz@50: suite.addTest(unittest.makeSuite(AttrsDirectiveTestCase, 'test'))
cmlenz@53: suite.addTest(unittest.makeSuite(ChooseDirectiveTestCase, 'test'))
cmlenz@50: suite.addTest(unittest.makeSuite(DefDirectiveTestCase, 'test'))
cmlenz@51: suite.addTest(unittest.makeSuite(ForDirectiveTestCase, 'test'))
cmlenz@65: suite.addTest(unittest.makeSuite(IfDirectiveTestCase, 'test'))
cmlenz@36: suite.addTest(unittest.makeSuite(MatchDirectiveTestCase, 'test'))
cmlenz@37: suite.addTest(unittest.makeSuite(StripDirectiveTestCase, 'test'))
cmlenz@104: suite.addTest(unittest.makeSuite(WithDirectiveTestCase, 'test'))
cmlenz@152: suite.addTest(unittest.makeSuite(TemplateTestCase, 'test'))
cmlenz@152: suite.addTest(unittest.makeSuite(TemplateLoaderTestCase, 'test'))
cmlenz@1: return suite
cmlenz@1:
cmlenz@1: if __name__ == '__main__':
cmlenz@1: unittest.main(defaultTest='suite')