from django.template import TemplateSyntaxError from django.test import SimpleTestCase, ignore_warnings from django.utils.deprecation import RemovedInDjango40Warning from django.utils.safestring import mark_safe from ..utils import SafeClass, UnsafeClass, setup class AutoescapeTagTests(SimpleTestCase): @setup({'autoescape-tag01': '{% autoescape off %}hello{% endautoescape %}'}) def test_autoescape_tag01(self): output = self.engine.render_to_string('autoescape-tag01') self.assertEqual(output, 'hello') @setup({'autoescape-tag02': '{% autoescape off %}{{ first }}{% endautoescape %}'}) def test_autoescape_tag02(self): output = self.engine.render_to_string('autoescape-tag02', {'first': 'hello'}) self.assertEqual(output, 'hello') @setup({'autoescape-tag03': '{% autoescape on %}{{ first }}{% endautoescape %}'}) def test_autoescape_tag03(self): output = self.engine.render_to_string('autoescape-tag03', {'first': 'hello'}) self.assertEqual(output, '<b>hello</b>') # Autoescape disabling and enabling nest in a predictable way. @setup({ 'autoescape-tag04': '{% autoescape off %}{{ first }} {% autoescape on %}{{ first }}{% endautoescape %}{% endautoescape %}' }) def test_autoescape_tag04(self): output = self.engine.render_to_string('autoescape-tag04', {'first': ''}) self.assertEqual(output, ' <a>') @setup({'autoescape-tag05': '{% autoescape on %}{{ first }}{% endautoescape %}'}) def test_autoescape_tag05(self): output = self.engine.render_to_string('autoescape-tag05', {'first': 'first'}) self.assertEqual(output, '<b>first</b>') # Strings (ASCII or Unicode) already marked as "safe" are not # auto-escaped @setup({'autoescape-tag06': '{{ first }}'}) def test_autoescape_tag06(self): output = self.engine.render_to_string('autoescape-tag06', {'first': mark_safe('first')}) self.assertEqual(output, 'first') @setup({'autoescape-tag07': '{% autoescape on %}{{ first }}{% endautoescape %}'}) def test_autoescape_tag07(self): output = self.engine.render_to_string('autoescape-tag07', {'first': mark_safe('Apple')}) self.assertEqual(output, 'Apple') @setup({ 'autoescape-tag08': r'{% autoescape on %}{{ var|default_if_none:" endquote\" hah" }}{% endautoescape %}' }) def test_autoescape_tag08(self): """ Literal string arguments to filters, if used in the result, are safe. """ output = self.engine.render_to_string('autoescape-tag08', {"var": None}) self.assertEqual(output, ' endquote" hah') # Objects which return safe strings as their __str__ method # won't get double-escaped. @setup({'autoescape-tag09': r'{{ unsafe }}'}) def test_autoescape_tag09(self): output = self.engine.render_to_string('autoescape-tag09', {'unsafe': UnsafeClass()}) self.assertEqual(output, 'you & me') @setup({'autoescape-tag10': r'{{ safe }}'}) def test_autoescape_tag10(self): output = self.engine.render_to_string('autoescape-tag10', {'safe': SafeClass()}) self.assertEqual(output, 'you > me') @setup({'autoescape-filtertag01': '{{ first }}{% filter safe %}{{ first }} x'}) @ignore_warnings(category=RemovedInDjango40Warning) @setup({'autoescape-ifequal01': '{% ifequal var "this & that" %}yes{% endifequal %}'}) def test_autoescape_ifequal01(self): """ ifequal compares unescaped vales. """ output = self.engine.render_to_string('autoescape-ifequal01', {'var': 'this & that'}) self.assertEqual(output, 'yes') # Arguments to filters are 'safe' and manipulate their input unescaped. @setup({'autoescape-filters01': '{{ var|cut:"&" }}'}) def test_autoescape_filters01(self): output = self.engine.render_to_string('autoescape-filters01', {'var': 'this & that'}) self.assertEqual(output, 'this that') @setup({'autoescape-filters02': '{{ var|join:" & " }}'}) def test_autoescape_filters02(self): output = self.engine.render_to_string('autoescape-filters02', {'var': ('Tom', 'Dick', 'Harry')}) self.assertEqual(output, 'Tom & Dick & Harry') @setup({'autoescape-literals01': '{{ "this & that" }}'}) def test_autoescape_literals01(self): """ Literal strings are safe. """ output = self.engine.render_to_string('autoescape-literals01') self.assertEqual(output, 'this & that') @setup({'autoescape-stringiterations01': '{% for l in var %}{{ l }},{% endfor %}'}) def test_autoescape_stringiterations01(self): """ Iterating over strings outputs safe characters. """ output = self.engine.render_to_string('autoescape-stringiterations01', {'var': 'K&R'}) self.assertEqual(output, 'K,&,R,') @setup({'autoescape-lookup01': '{{ var.key }}'}) def test_autoescape_lookup01(self): """ Escape requirement survives lookup. """ output = self.engine.render_to_string('autoescape-lookup01', {'var': {'key': 'this & that'}}) self.assertEqual(output, 'this & that') @setup({'autoescape-incorrect-arg': '{% autoescape true %}{{ var.key }}{% endautoescape %}'}) def test_invalid_arg(self): msg = "'autoescape' argument should be 'on' or 'off'" with self.assertRaisesMessage(TemplateSyntaxError, msg): self.engine.render_to_string('autoescape-incorrect-arg', {'var': {'key': 'this & that'}}) @setup({'autoescape-incorrect-arg': '{% autoescape %}{{ var.key }}{% endautoescape %}'}) def test_no_arg(self): msg = "'autoescape' tag requires exactly one argument." with self.assertRaisesMessage(TemplateSyntaxError, msg): self.engine.render_to_string('autoescape-incorrect-arg', {'var': {'key': 'this & that'}})