| from tornado.escape import utf8, native_str |
| from tornado.template import Template, DictLoader, ParseError |
| from tornado.testing import LogTrapTestCase |
| from tornado.util import b, bytes_type |
| |
| class TemplateTest(LogTrapTestCase): |
| def test_simple(self): |
| template = Template("Hello {{ name }}!") |
| self.assertEqual(template.generate(name="Ben"), |
| b("Hello Ben!")) |
| |
| def test_bytes(self): |
| template = Template("Hello {{ name }}!") |
| self.assertEqual(template.generate(name=utf8("Ben")), |
| b("Hello Ben!")) |
| |
| def test_expressions(self): |
| template = Template("2 + 2 = {{ 2 + 2 }}") |
| self.assertEqual(template.generate(), b("2 + 2 = 4")) |
| |
| def test_include(self): |
| loader = DictLoader({ |
| "index.html": '{% include "header.html" %}\nbody text', |
| "header.html": "header text", |
| }) |
| self.assertEqual(loader.load("index.html").generate(), |
| b("header text\nbody text")) |
| |
| def test_extends(self): |
| loader = DictLoader({ |
| "base.html": """\ |
| <title>{% block title %}default title{% end %}</title> |
| <body>{% block body %}default body{% end %}</body> |
| """, |
| "page.html": """\ |
| {% extends "base.html" %} |
| {% block title %}page title{% end %} |
| {% block body %}page body{% end %} |
| """, |
| }) |
| self.assertEqual(loader.load("page.html").generate(), |
| b("<title>page title</title>\n<body>page body</body>\n")) |
| |
| def test_relative_load(self): |
| loader = DictLoader({ |
| "a/1.html": "{% include '2.html' %}", |
| "a/2.html": "{% include '../b/3.html' %}", |
| "b/3.html": "ok", |
| }) |
| self.assertEqual(loader.load("a/1.html").generate(), |
| b("ok")) |
| |
| def test_escaping(self): |
| self.assertRaises(ParseError, lambda: Template("{{")) |
| self.assertRaises(ParseError, lambda: Template("{%")) |
| self.assertEqual(Template("{{!").generate(), b("{{")) |
| self.assertEqual(Template("{%!").generate(), b("{%")) |
| self.assertEqual(Template("{{ 'expr' }} {{!jquery expr}}").generate(), |
| b("expr {{jquery expr}}")) |
| |
| |
| class AutoEscapeTest(LogTrapTestCase): |
| def setUp(self): |
| self.templates = { |
| "escaped.html": "{% autoescape xhtml_escape %}{{ name }}", |
| "unescaped.html": "{% autoescape None %}{{ name }}", |
| "default.html": "{{ name }}", |
| |
| "include.html": """\ |
| escaped: {% include 'escaped.html' %} |
| unescaped: {% include 'unescaped.html' %} |
| default: {% include 'default.html' %} |
| """, |
| |
| "escaped_block.html": """\ |
| {% autoescape xhtml_escape %}\ |
| {% block name %}base: {{ name }}{% end %}""", |
| "unescaped_block.html": """\ |
| {% autoescape None %}\ |
| {% block name %}base: {{ name }}{% end %}""", |
| |
| # Extend a base template with different autoescape policy, |
| # with and without overriding the base's blocks |
| "escaped_extends_unescaped.html": """\ |
| {% autoescape xhtml_escape %}\ |
| {% extends "unescaped_block.html" %}""", |
| "escaped_overrides_unescaped.html": """\ |
| {% autoescape xhtml_escape %}\ |
| {% extends "unescaped_block.html" %}\ |
| {% block name %}extended: {{ name }}{% end %}""", |
| "unescaped_extends_escaped.html": """\ |
| {% autoescape None %}\ |
| {% extends "escaped_block.html" %}""", |
| "unescaped_overrides_escaped.html": """\ |
| {% autoescape None %}\ |
| {% extends "escaped_block.html" %}\ |
| {% block name %}extended: {{ name }}{% end %}""", |
| |
| "raw_expression.html": """\ |
| {% autoescape xhtml_escape %}\ |
| expr: {{ name }} |
| raw: {% raw name %}""", |
| } |
| |
| def test_default_off(self): |
| loader = DictLoader(self.templates, autoescape=None) |
| name = "Bobby <table>s" |
| self.assertEqual(loader.load("escaped.html").generate(name=name), |
| b("Bobby <table>s")) |
| self.assertEqual(loader.load("unescaped.html").generate(name=name), |
| b("Bobby <table>s")) |
| self.assertEqual(loader.load("default.html").generate(name=name), |
| b("Bobby <table>s")) |
| |
| self.assertEqual(loader.load("include.html").generate(name=name), |
| b("escaped: Bobby <table>s\n" |
| "unescaped: Bobby <table>s\n" |
| "default: Bobby <table>s\n")) |
| |
| def test_default_on(self): |
| loader = DictLoader(self.templates, autoescape="xhtml_escape") |
| name = "Bobby <table>s" |
| self.assertEqual(loader.load("escaped.html").generate(name=name), |
| b("Bobby <table>s")) |
| self.assertEqual(loader.load("unescaped.html").generate(name=name), |
| b("Bobby <table>s")) |
| self.assertEqual(loader.load("default.html").generate(name=name), |
| b("Bobby <table>s")) |
| |
| self.assertEqual(loader.load("include.html").generate(name=name), |
| b("escaped: Bobby <table>s\n" |
| "unescaped: Bobby <table>s\n" |
| "default: Bobby <table>s\n")) |
| |
| def test_unextended_block(self): |
| loader = DictLoader(self.templates) |
| name = "<script>" |
| self.assertEqual(loader.load("escaped_block.html").generate(name=name), |
| b("base: <script>")) |
| self.assertEqual(loader.load("unescaped_block.html").generate(name=name), |
| b("base: <script>")) |
| |
| def test_extended_block(self): |
| loader = DictLoader(self.templates) |
| def render(name): return loader.load(name).generate(name="<script>") |
| self.assertEqual(render("escaped_extends_unescaped.html"), |
| b("base: <script>")) |
| self.assertEqual(render("escaped_overrides_unescaped.html"), |
| b("extended: <script>")) |
| |
| self.assertEqual(render("unescaped_extends_escaped.html"), |
| b("base: <script>")) |
| self.assertEqual(render("unescaped_overrides_escaped.html"), |
| b("extended: <script>")) |
| |
| def test_raw_expression(self): |
| loader = DictLoader(self.templates) |
| def render(name): return loader.load(name).generate(name='<>&"') |
| self.assertEqual(render("raw_expression.html"), |
| b("expr: <>&"\n" |
| "raw: <>&\"")) |
| |
| def test_custom_escape(self): |
| loader = DictLoader({"foo.py": |
| "{% autoescape py_escape %}s = {{ name }}\n"}) |
| def py_escape(s): |
| self.assertEqual(type(s), bytes_type) |
| return repr(native_str(s)) |
| def render(template, name): |
| return loader.load(template).generate(py_escape=py_escape, |
| name=name) |
| self.assertEqual(render("foo.py", "<html>"), |
| b("s = '<html>'\n")) |
| self.assertEqual(render("foo.py", "';sys.exit()"), |
| b("""s = "';sys.exit()"\n""")) |
| self.assertEqual(render("foo.py", ["not a string"]), |
| b("""s = "['not a string']"\n""")) |