mirror of https://github.com/django/django.git
Fixed #23958 -- Rewrote filter tests as unit tests.
This commit is contained in:
parent
34a06d99e0
commit
5c68870169
|
@ -0,0 +1,46 @@
|
|||
from datetime import date, timedelta
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class AddTests(SimpleTestCase):
|
||||
"""
|
||||
Tests for #11687 and #16676
|
||||
"""
|
||||
|
||||
@setup({'add01': '{{ i|add:"5" }}'})
|
||||
def test_add01(self):
|
||||
output = render('add01', {'i': 2000})
|
||||
self.assertEqual(output, '2005')
|
||||
|
||||
@setup({'add02': '{{ i|add:"napis" }}'})
|
||||
def test_add02(self):
|
||||
output = render('add02', {'i': 2000})
|
||||
self.assertEqual(output, '')
|
||||
|
||||
@setup({'add03': '{{ i|add:16 }}'})
|
||||
def test_add03(self):
|
||||
output = render('add03', {'i': 'not_an_int'})
|
||||
self.assertEqual(output, '')
|
||||
|
||||
@setup({'add04': '{{ i|add:"16" }}'})
|
||||
def test_add04(self):
|
||||
output = render('add04', {'i': 'not_an_int'})
|
||||
self.assertEqual(output, 'not_an_int16')
|
||||
|
||||
@setup({'add05': '{{ l1|add:l2 }}'})
|
||||
def test_add05(self):
|
||||
output = render('add05', {'l1': [1, 2], 'l2': [3, 4]})
|
||||
self.assertEqual(output, '[1, 2, 3, 4]')
|
||||
|
||||
@setup({'add06': '{{ t1|add:t2 }}'})
|
||||
def test_add06(self):
|
||||
output = render('add06', {'t1': (3, 4), 't2': (1, 2)})
|
||||
self.assertEqual(output, '(3, 4, 1, 2)')
|
||||
|
||||
@setup({'add07': '{{ d|add:t }}'})
|
||||
def test_add07(self):
|
||||
output = render('add07', {'d': date(2000, 1, 1), 't': timedelta(10)})
|
||||
self.assertEqual(output, 'Jan. 11, 2000')
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class AddslashesTests(SimpleTestCase):
|
||||
|
||||
@setup({'addslashes01': '{% autoescape off %}{{ a|addslashes }} {{ b|addslashes }}{% endautoescape %}'})
|
||||
def test_addslashes01(self):
|
||||
output = render('addslashes01', {"a": "<a>'", "b": mark_safe("<a>'")})
|
||||
self.assertEqual(output, r"<a>\' <a>\'")
|
||||
|
||||
@setup({'addslashes02': '{{ a|addslashes }} {{ b|addslashes }}'})
|
||||
def test_addslashes02(self):
|
||||
output = render('addslashes02', {"a": "<a>'", "b": mark_safe("<a>'")})
|
||||
self.assertEqual(output, r"<a>\' <a>\'")
|
|
@ -0,0 +1,29 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from ..utils import render, setup, SafeClass, UnsafeClass
|
||||
|
||||
|
||||
class AutoescapeStringfilterTests(SimpleTestCase):
|
||||
"""
|
||||
Filters decorated with stringfilter still respect is_safe.
|
||||
"""
|
||||
|
||||
@setup({'autoescape-stringfilter01': '{{ unsafe|capfirst }}'})
|
||||
def test_autoescape_stringfilter01(self):
|
||||
output = render('autoescape-stringfilter01', {'unsafe': UnsafeClass()})
|
||||
self.assertEqual(output, 'You & me')
|
||||
|
||||
@setup({'autoescape-stringfilter02': '{% autoescape off %}{{ unsafe|capfirst }}{% endautoescape %}'})
|
||||
def test_autoescape_stringfilter02(self):
|
||||
output = render('autoescape-stringfilter02', {'unsafe': UnsafeClass()})
|
||||
self.assertEqual(output, 'You & me')
|
||||
|
||||
@setup({'autoescape-stringfilter03': '{{ safe|capfirst }}'})
|
||||
def test_autoescape_stringfilter03(self):
|
||||
output = render('autoescape-stringfilter03', {'safe': SafeClass()})
|
||||
self.assertEqual(output, 'You > me')
|
||||
|
||||
@setup({'autoescape-stringfilter04': '{% autoescape off %}{{ safe|capfirst }}{% endautoescape %}'})
|
||||
def test_autoescape_stringfilter04(self):
|
||||
output = render('autoescape-stringfilter04', {'safe': SafeClass()})
|
||||
self.assertEqual(output, 'You > me')
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class CapfirstTests(SimpleTestCase):
|
||||
|
||||
@setup({'capfirst01': '{% autoescape off %}{{ a|capfirst }} {{ b|capfirst }}{% endautoescape %}'})
|
||||
def test_capfirst01(self):
|
||||
output = render('capfirst01', {'a': 'fred>', 'b': mark_safe('fred>')})
|
||||
self.assertEqual(output, 'Fred> Fred>')
|
||||
|
||||
@setup({'capfirst02': '{{ a|capfirst }} {{ b|capfirst }}'})
|
||||
def test_capfirst02(self):
|
||||
output = render('capfirst02', {'a': 'fred>', 'b': mark_safe('fred>')})
|
||||
self.assertEqual(output, 'Fred> Fred>')
|
|
@ -0,0 +1,18 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class CenterTests(SimpleTestCase):
|
||||
|
||||
@setup({'center01':
|
||||
'{% autoescape off %}.{{ a|center:"5" }}. .{{ b|center:"5" }}.{% endautoescape %}'})
|
||||
def test_center01(self):
|
||||
output = render('center01', {"a": "a&b", "b": mark_safe("a&b")})
|
||||
self.assertEqual(output, ". a&b . . a&b .")
|
||||
|
||||
@setup({'center02': '.{{ a|center:"5" }}. .{{ b|center:"5" }}.'})
|
||||
def test_center02(self):
|
||||
output = render('center02', {"a": "a&b", "b": mark_safe("a&b")})
|
||||
self.assertEqual(output, ". a&b . . a&b .")
|
|
@ -0,0 +1,86 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class ChainingTests(SimpleTestCase):
|
||||
"""
|
||||
Chaining safeness-preserving filters should not alter the safe status.
|
||||
"""
|
||||
|
||||
@setup({'chaining01': '{{ a|capfirst|center:"7" }}.{{ b|capfirst|center:"7" }}'})
|
||||
def test_chaining01(self):
|
||||
output = render('chaining01', {'a': 'a < b', 'b': mark_safe('a < b')})
|
||||
self.assertEqual(output, ' A < b . A < b ')
|
||||
|
||||
@setup({'chaining02':
|
||||
'{% autoescape off %}{{ a|capfirst|center:"7" }}.{{ b|capfirst|center:"7" }}{% endautoescape %}'})
|
||||
def test_chaining02(self):
|
||||
output = render('chaining02', {'a': 'a < b', 'b': mark_safe('a < b')})
|
||||
self.assertEqual(output, ' A < b . A < b ')
|
||||
|
||||
# Using a filter that forces a string back to unsafe:
|
||||
@setup({'chaining03': '{{ a|cut:"b"|capfirst }}.{{ b|cut:"b"|capfirst }}'})
|
||||
def test_chaining03(self):
|
||||
output = render('chaining03', {'a': 'a < b', 'b': mark_safe('a < b')})
|
||||
self.assertEqual(output, 'A < .A < ')
|
||||
|
||||
@setup({'chaining04':
|
||||
'{% autoescape off %}{{ a|cut:"b"|capfirst }}.{{ b|cut:"b"|capfirst }}{% endautoescape %}'})
|
||||
def test_chaining04(self):
|
||||
output = render('chaining04', {'a': 'a < b', 'b': mark_safe('a < b')})
|
||||
self.assertEqual(output, 'A < .A < ')
|
||||
|
||||
# Using a filter that forces safeness does not lead to double-escaping
|
||||
@setup({'chaining05': '{{ a|escape|capfirst }}'})
|
||||
def test_chaining05(self):
|
||||
output = render('chaining05', {'a': 'a < b'})
|
||||
self.assertEqual(output, 'A < b')
|
||||
|
||||
@setup({'chaining06': '{% autoescape off %}{{ a|escape|capfirst }}{% endautoescape %}'})
|
||||
def test_chaining06(self):
|
||||
output = render('chaining06', {'a': 'a < b'})
|
||||
self.assertEqual(output, 'A < b')
|
||||
|
||||
# Force to safe, then back (also showing why using force_escape too
|
||||
# early in a chain can lead to unexpected results).
|
||||
@setup({'chaining07': '{{ a|force_escape|cut:";" }}'})
|
||||
def test_chaining07(self):
|
||||
output = render('chaining07', {'a': 'a < b'})
|
||||
self.assertEqual(output, 'a &lt b')
|
||||
|
||||
@setup({'chaining08': '{% autoescape off %}{{ a|force_escape|cut:";" }}{% endautoescape %}'})
|
||||
def test_chaining08(self):
|
||||
output = render('chaining08', {'a': 'a < b'})
|
||||
self.assertEqual(output, 'a < b')
|
||||
|
||||
@setup({'chaining09': '{{ a|cut:";"|force_escape }}'})
|
||||
def test_chaining09(self):
|
||||
output = render('chaining09', {'a': 'a < b'})
|
||||
self.assertEqual(output, 'a < b')
|
||||
|
||||
@setup({'chaining10': '{% autoescape off %}{{ a|cut:";"|force_escape }}{% endautoescape %}'})
|
||||
def test_chaining10(self):
|
||||
output = render('chaining10', {'a': 'a < b'})
|
||||
self.assertEqual(output, 'a < b')
|
||||
|
||||
@setup({'chaining11': '{{ a|cut:"b"|safe }}'})
|
||||
def test_chaining11(self):
|
||||
output = render('chaining11', {'a': 'a < b'})
|
||||
self.assertEqual(output, 'a < ')
|
||||
|
||||
@setup({'chaining12': '{% autoescape off %}{{ a|cut:"b"|safe }}{% endautoescape %}'})
|
||||
def test_chaining12(self):
|
||||
output = render('chaining12', {'a': 'a < b'})
|
||||
self.assertEqual(output, 'a < ')
|
||||
|
||||
@setup({'chaining13': '{{ a|safe|force_escape }}'})
|
||||
def test_chaining13(self):
|
||||
output = render('chaining13', {"a": "a < b"})
|
||||
self.assertEqual(output, 'a < b')
|
||||
|
||||
@setup({'chaining14': '{% autoescape off %}{{ a|safe|force_escape }}{% endautoescape %}'})
|
||||
def test_chaining14(self):
|
||||
output = render('chaining14', {"a": "a < b"})
|
||||
self.assertEqual(output, 'a < b')
|
|
@ -0,0 +1,39 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class CutTests(SimpleTestCase):
|
||||
|
||||
@setup({'cut01': '{% autoescape off %}{{ a|cut:"x" }} {{ b|cut:"x" }}{% endautoescape %}'})
|
||||
def test_cut01(self):
|
||||
output = render('cut01', {"a": "x&y", "b": mark_safe("x&y")})
|
||||
self.assertEqual(output, "&y &y")
|
||||
|
||||
@setup({'cut02': '{{ a|cut:"x" }} {{ b|cut:"x" }}'})
|
||||
def test_cut02(self):
|
||||
output = render('cut02', {"a": "x&y", "b": mark_safe("x&y")})
|
||||
self.assertEqual(output, "&y &y")
|
||||
|
||||
@setup({'cut03': '{% autoescape off %}{{ a|cut:"&" }} {{ b|cut:"&" }}{% endautoescape %}'})
|
||||
def test_cut03(self):
|
||||
output = render('cut03', {"a": "x&y", "b": mark_safe("x&y")})
|
||||
self.assertEqual(output, "xy xamp;y")
|
||||
|
||||
@setup({'cut04': '{{ a|cut:"&" }} {{ b|cut:"&" }}'})
|
||||
def test_cut04(self):
|
||||
output = render('cut04', {"a": "x&y", "b": mark_safe("x&y")})
|
||||
self.assertEqual(output, "xy xamp;y")
|
||||
|
||||
# Passing ';' to cut can break existing HTML entities, so those strings
|
||||
# are auto-escaped.
|
||||
@setup({'cut05': '{% autoescape off %}{{ a|cut:";" }} {{ b|cut:";" }}{% endautoescape %}'})
|
||||
def test_cut05(self):
|
||||
output = render('cut05', {"a": "x&y", "b": mark_safe("x&y")})
|
||||
self.assertEqual(output, "x&y x&y")
|
||||
|
||||
@setup({'cut06': '{{ a|cut:";" }} {{ b|cut:";" }}'})
|
||||
def test_cut06(self):
|
||||
output = render('cut06', {"a": "x&y", "b": mark_safe("x&y")})
|
||||
self.assertEqual(output, "x&y x&ampy")
|
|
@ -0,0 +1,60 @@
|
|||
from datetime import datetime, time
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
from .timezone_utils import TimezoneTestCase
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class DateTests(TimezoneTestCase):
|
||||
|
||||
@setup({'date01': '{{ d|date:"m" }}'})
|
||||
def test_date01(self):
|
||||
output = render('date01', {'d': datetime(2008, 1, 1)})
|
||||
self.assertEqual(output, '01')
|
||||
|
||||
@setup({'date02': '{{ d|date }}'})
|
||||
def test_date02(self):
|
||||
output = render('date02', {'d': datetime(2008, 1, 1)})
|
||||
self.assertEqual(output, 'Jan. 1, 2008')
|
||||
|
||||
@setup({'date03': '{{ d|date:"m" }}'})
|
||||
def test_date03(self):
|
||||
"""
|
||||
#9520: Make sure |date doesn't blow up on non-dates
|
||||
"""
|
||||
output = render('date03', {'d': 'fail_string'})
|
||||
self.assertEqual(output, '')
|
||||
|
||||
# ISO date formats
|
||||
@setup({'date04': '{{ d|date:"o" }}'})
|
||||
def test_date04(self):
|
||||
output = render('date04', {'d': datetime(2008, 12, 29)})
|
||||
self.assertEqual(output, '2009')
|
||||
|
||||
@setup({'date05': '{{ d|date:"o" }}'})
|
||||
def test_date05(self):
|
||||
output = render('date05', {'d': datetime(2010, 1, 3)})
|
||||
self.assertEqual(output, '2009')
|
||||
|
||||
# Timezone name
|
||||
@setup({'date06': '{{ d|date:"e" }}'})
|
||||
def test_date06(self):
|
||||
output = render('date06', {'d': datetime(2009, 3, 12, tzinfo=timezone.get_fixed_timezone(30))})
|
||||
self.assertEqual(output, '+0030')
|
||||
|
||||
@setup({'date07': '{{ d|date:"e" }}'})
|
||||
def test_date07(self):
|
||||
output = render('date07', {'d': datetime(2009, 3, 12)})
|
||||
self.assertEqual(output, '')
|
||||
|
||||
# #19370: Make sure |date doesn't blow up on a midnight time object
|
||||
@setup({'date08': '{{ t|date:"H:i" }}'})
|
||||
def test_date08(self):
|
||||
output = render('date08', {'t': time(0, 1)})
|
||||
self.assertEqual(output, '00:01')
|
||||
|
||||
@setup({'date09': '{{ t|date:"H:i" }}'})
|
||||
def test_date09(self):
|
||||
output = render('date09', {'t': time(0, 0)})
|
||||
self.assertEqual(output, '00:00')
|
|
@ -0,0 +1,47 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class DefaultTests(SimpleTestCase):
|
||||
"""
|
||||
Literal string arguments to the default filter are always treated as
|
||||
safe strings, regardless of the auto-escaping state.
|
||||
|
||||
Note: we have to use {"a": ""} here, otherwise the invalid template
|
||||
variable string interferes with the test result.
|
||||
"""
|
||||
|
||||
@setup({'default01': '{{ a|default:"x<" }}'})
|
||||
def test_default01(self):
|
||||
output = render('default01', {"a": ""})
|
||||
self.assertEqual(output, "x<")
|
||||
|
||||
@setup({'default02': '{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}'})
|
||||
def test_default02(self):
|
||||
output = render('default02', {"a": ""})
|
||||
self.assertEqual(output, "x<")
|
||||
|
||||
@setup({'default03': '{{ a|default:"x<" }}'})
|
||||
def test_default03(self):
|
||||
output = render('default03', {"a": mark_safe("x>")})
|
||||
self.assertEqual(output, "x>")
|
||||
|
||||
@setup({'default04': '{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}'})
|
||||
def test_default04(self):
|
||||
output = render('default04', {"a": mark_safe("x>")})
|
||||
self.assertEqual(output, "x>")
|
||||
|
||||
|
||||
class DefaultIfNoneTests(SimpleTestCase):
|
||||
|
||||
@setup({'default_if_none01': '{{ a|default:"x<" }}'})
|
||||
def test_default_if_none01(self):
|
||||
output = render('default_if_none01', {"a": None})
|
||||
self.assertEqual(output, "x<")
|
||||
|
||||
@setup({'default_if_none02': '{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}'})
|
||||
def test_default_if_none02(self):
|
||||
output = render('default_if_none02', {"a": None})
|
||||
self.assertEqual(output, "x<")
|
|
@ -0,0 +1,33 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class EscapeTests(SimpleTestCase):
|
||||
"""
|
||||
The "escape" filter works the same whether autoescape is on or off,
|
||||
but it has no effect on strings already marked as safe.
|
||||
"""
|
||||
|
||||
@setup({'escape01': '{{ a|escape }} {{ b|escape }}'})
|
||||
def test_escape01(self):
|
||||
output = render('escape01', {"a": "x&y", "b": mark_safe("x&y")})
|
||||
self.assertEqual(output, "x&y x&y")
|
||||
|
||||
@setup({'escape02': '{% autoescape off %}{{ a|escape }} {{ b|escape }}{% endautoescape %}'})
|
||||
def test_escape02(self):
|
||||
output = render('escape02', {"a": "x&y", "b": mark_safe("x&y")})
|
||||
self.assertEqual(output, "x&y x&y")
|
||||
|
||||
# It is only applied once, regardless of the number of times it
|
||||
# appears in a chain.
|
||||
@setup({'escape03': '{% autoescape off %}{{ a|escape|escape }}{% endautoescape %}'})
|
||||
def test_escape03(self):
|
||||
output = render('escape03', {"a": "x&y"})
|
||||
self.assertEqual(output, "x&y")
|
||||
|
||||
@setup({'escape04': '{{ a|escape|escape }}'})
|
||||
def test_escape04(self):
|
||||
output = render('escape04', {"a": "x&y"})
|
||||
self.assertEqual(output, "x&y")
|
|
@ -0,0 +1,20 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class EscapejsTests(SimpleTestCase):
|
||||
|
||||
@setup({'escapejs01': '{{ a|escapejs }}'})
|
||||
def test_escapejs01(self):
|
||||
output = render('escapejs01', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'})
|
||||
self.assertEqual(output, 'testing\\u000D\\u000Ajavascript '
|
||||
'\\u0027string\\u0022 \\u003Cb\\u003E'
|
||||
'escaping\\u003C/b\\u003E')
|
||||
|
||||
@setup({'escapejs02': '{% autoescape off %}{{ a|escapejs }}{% endautoescape %}'})
|
||||
def test_escapejs02(self):
|
||||
output = render('escapejs02', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'})
|
||||
self.assertEqual(output, 'testing\\u000D\\u000Ajavascript '
|
||||
'\\u0027string\\u0022 \\u003Cb\\u003E'
|
||||
'escaping\\u003C/b\\u003E')
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class FirstTests(SimpleTestCase):
|
||||
|
||||
@setup({'first01': '{{ a|first }} {{ b|first }}'})
|
||||
def test_first01(self):
|
||||
output = render('first01', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]})
|
||||
self.assertEqual(output, "a&b a&b")
|
||||
|
||||
@setup({'first02': '{% autoescape off %}{{ a|first }} {{ b|first }}{% endautoescape %}'})
|
||||
def test_first02(self):
|
||||
output = render('first02', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]})
|
||||
self.assertEqual(output, "a&b a&b")
|
|
@ -0,0 +1,18 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class FloatformatTests(SimpleTestCase):
|
||||
|
||||
@setup({'floatformat01':
|
||||
'{% autoescape off %}{{ a|floatformat }} {{ b|floatformat }}{% endautoescape %}'})
|
||||
def test_floatformat01(self):
|
||||
output = render('floatformat01', {"a": "1.42", "b": mark_safe("1.42")})
|
||||
self.assertEqual(output, "1.4 1.4")
|
||||
|
||||
@setup({'floatformat02': '{{ a|floatformat }} {{ b|floatformat }}'})
|
||||
def test_floatformat02(self):
|
||||
output = render('floatformat02', {"a": "1.42", "b": mark_safe("1.42")})
|
||||
self.assertEqual(output, "1.4 1.4")
|
|
@ -0,0 +1,52 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class ForceEscapeTests(SimpleTestCase):
|
||||
"""
|
||||
Force_escape is applied immediately. It can be used to provide
|
||||
double-escaping, for example.
|
||||
"""
|
||||
|
||||
@setup({'force-escape01': '{% autoescape off %}{{ a|force_escape }}{% endautoescape %}'})
|
||||
def test_force_escape01(self):
|
||||
output = render('force-escape01', {"a": "x&y"})
|
||||
self.assertEqual(output, "x&y")
|
||||
|
||||
@setup({'force-escape02': '{{ a|force_escape }}'})
|
||||
def test_force_escape02(self):
|
||||
output = render('force-escape02', {"a": "x&y"})
|
||||
self.assertEqual(output, "x&y")
|
||||
|
||||
@setup({'force-escape03': '{% autoescape off %}{{ a|force_escape|force_escape }}{% endautoescape %}'})
|
||||
def test_force_escape03(self):
|
||||
output = render('force-escape03', {"a": "x&y"})
|
||||
self.assertEqual(output, "x&amp;y")
|
||||
|
||||
@setup({'force-escape04': '{{ a|force_escape|force_escape }}'})
|
||||
def test_force_escape04(self):
|
||||
output = render('force-escape04', {"a": "x&y"})
|
||||
self.assertEqual(output, "x&amp;y")
|
||||
|
||||
# Because the result of force_escape is "safe", an additional
|
||||
# escape filter has no effect.
|
||||
@setup({'force-escape05': '{% autoescape off %}{{ a|force_escape|escape }}{% endautoescape %}'})
|
||||
def test_force_escape05(self):
|
||||
output = render('force-escape05', {"a": "x&y"})
|
||||
self.assertEqual(output, "x&y")
|
||||
|
||||
@setup({'force-escape06': '{{ a|force_escape|escape }}'})
|
||||
def test_force_escape06(self):
|
||||
output = render('force-escape06', {"a": "x&y"})
|
||||
self.assertEqual(output, "x&y")
|
||||
|
||||
@setup({'force-escape07': '{% autoescape off %}{{ a|escape|force_escape }}{% endautoescape %}'})
|
||||
def test_force_escape07(self):
|
||||
output = render('force-escape07', {"a": "x&y"})
|
||||
self.assertEqual(output, "x&y")
|
||||
|
||||
@setup({'force-escape08': '{{ a|escape|force_escape }}'})
|
||||
def test_force_escape08(self):
|
||||
output = render('force-escape08', {"a": "x&y"})
|
||||
self.assertEqual(output, "x&y")
|
|
@ -0,0 +1,30 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class IriencodeTests(SimpleTestCase):
|
||||
"""
|
||||
Ensure iriencode keeps safe strings.
|
||||
"""
|
||||
|
||||
@setup({'iriencode01': '{{ url|iriencode }}'})
|
||||
def test_iriencode01(self):
|
||||
output = render('iriencode01', {'url': '?test=1&me=2'})
|
||||
self.assertEqual(output, '?test=1&me=2')
|
||||
|
||||
@setup({'iriencode02': '{% autoescape off %}{{ url|iriencode }}{% endautoescape %}'})
|
||||
def test_iriencode02(self):
|
||||
output = render('iriencode02', {'url': '?test=1&me=2'})
|
||||
self.assertEqual(output, '?test=1&me=2')
|
||||
|
||||
@setup({'iriencode03': '{{ url|iriencode }}'})
|
||||
def test_iriencode03(self):
|
||||
output = render('iriencode03', {'url': mark_safe('?test=1&me=2')})
|
||||
self.assertEqual(output, '?test=1&me=2')
|
||||
|
||||
@setup({'iriencode04': '{% autoescape off %}{{ url|iriencode }}{% endautoescape %}'})
|
||||
def test_iriencode04(self):
|
||||
output = render('iriencode04', {'url': mark_safe('?test=1&me=2')})
|
||||
self.assertEqual(output, '?test=1&me=2')
|
|
@ -0,0 +1,49 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class JoinTests(SimpleTestCase):
|
||||
|
||||
@setup({'join01': '{{ a|join:", " }}'})
|
||||
def test_join01(self):
|
||||
output = render('join01', {'a': ['alpha', 'beta & me']})
|
||||
self.assertEqual(output, 'alpha, beta & me')
|
||||
|
||||
@setup({'join02': '{% autoescape off %}{{ a|join:", " }}{% endautoescape %}'})
|
||||
def test_join02(self):
|
||||
output = render('join02', {'a': ['alpha', 'beta & me']})
|
||||
self.assertEqual(output, 'alpha, beta & me')
|
||||
|
||||
@setup({'join03': '{{ a|join:" & " }}'})
|
||||
def test_join03(self):
|
||||
output = render('join03', {'a': ['alpha', 'beta & me']})
|
||||
self.assertEqual(output, 'alpha & beta & me')
|
||||
|
||||
@setup({'join04': '{% autoescape off %}{{ a|join:" & " }}{% endautoescape %}'})
|
||||
def test_join04(self):
|
||||
output = render('join04', {'a': ['alpha', 'beta & me']})
|
||||
self.assertEqual(output, 'alpha & beta & me')
|
||||
|
||||
# #11377 Test that joining with unsafe joiners doesn't result in
|
||||
# unsafe strings
|
||||
@setup({'join05': '{{ a|join:var }}'})
|
||||
def test_join05(self):
|
||||
output = render('join05', {'a': ['alpha', 'beta & me'], 'var': ' & '})
|
||||
self.assertEqual(output, 'alpha & beta & me')
|
||||
|
||||
@setup({'join06': '{{ a|join:var }}'})
|
||||
def test_join06(self):
|
||||
output = render('join06', {'a': ['alpha', 'beta & me'], 'var': mark_safe(' & ')})
|
||||
self.assertEqual(output, 'alpha & beta & me')
|
||||
|
||||
@setup({'join07': '{{ a|join:var|lower }}'})
|
||||
def test_join07(self):
|
||||
output = render('join07', {'a': ['Alpha', 'Beta & me'], 'var': ' & '})
|
||||
self.assertEqual(output, 'alpha & beta & me')
|
||||
|
||||
@setup({'join08': '{{ a|join:var|lower }}'})
|
||||
def test_join08(self):
|
||||
output = render('join08', {'a': ['Alpha', 'Beta & me'], 'var': mark_safe(' & ')})
|
||||
self.assertEqual(output, 'alpha & beta & me')
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class LastTests(SimpleTestCase):
|
||||
|
||||
@setup({'last01': '{{ a|last }} {{ b|last }}'})
|
||||
def test_last01(self):
|
||||
output = render('last01', {"a": ["x", "a&b"], "b": ["x", mark_safe("a&b")]})
|
||||
self.assertEqual(output, "a&b a&b")
|
||||
|
||||
@setup({'last02': '{% autoescape off %}{{ a|last }} {{ b|last }}{% endautoescape %}'})
|
||||
def test_last02(self):
|
||||
output = render('last02', {"a": ["x", "a&b"], "b": ["x", mark_safe("a&b")]})
|
||||
self.assertEqual(output, "a&b a&b")
|
|
@ -0,0 +1,43 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class LengthTests(SimpleTestCase):
|
||||
|
||||
@setup({'length01': '{{ list|length }}'})
|
||||
def test_length01(self):
|
||||
output = render('length01', {'list': ['4', None, True, {}]})
|
||||
self.assertEqual(output, '4')
|
||||
|
||||
@setup({'length02': '{{ list|length }}'})
|
||||
def test_length02(self):
|
||||
output = render('length02', {'list': []})
|
||||
self.assertEqual(output, '0')
|
||||
|
||||
@setup({'length03': '{{ string|length }}'})
|
||||
def test_length03(self):
|
||||
output = render('length03', {'string': ''})
|
||||
self.assertEqual(output, '0')
|
||||
|
||||
@setup({'length04': '{{ string|length }}'})
|
||||
def test_length04(self):
|
||||
output = render('length04', {'string': 'django'})
|
||||
self.assertEqual(output, '6')
|
||||
|
||||
@setup({'length05': '{% if string|length == 6 %}Pass{% endif %}'})
|
||||
def test_length05(self):
|
||||
output = render('length05', {'string': mark_safe('django')})
|
||||
self.assertEqual(output, 'Pass')
|
||||
|
||||
# Invalid uses that should fail silently.
|
||||
@setup({'length06': '{{ int|length }}'})
|
||||
def test_length06(self):
|
||||
output = render('length06', {'int': 7})
|
||||
self.assertEqual(output, '0')
|
||||
|
||||
@setup({'length07': '{{ None|length }}'})
|
||||
def test_length07(self):
|
||||
output = render('length07', {'None': None})
|
||||
self.assertEqual(output, '0')
|
|
@ -0,0 +1,63 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class LengthIsTests(SimpleTestCase):
|
||||
|
||||
@setup({'length_is01': '{% if some_list|length_is:"4" %}Four{% endif %}'})
|
||||
def test_length_is01(self):
|
||||
output = render('length_is01', {'some_list': ['4', None, True, {}]})
|
||||
self.assertEqual(output, 'Four')
|
||||
|
||||
@setup({'length_is02': '{% if some_list|length_is:"4" %}Four{% else %}Not Four{% endif %}'})
|
||||
def test_length_is02(self):
|
||||
output = render('length_is02', {'some_list': ['4', None, True, {}, 17]})
|
||||
self.assertEqual(output, 'Not Four')
|
||||
|
||||
@setup({'length_is03': '{% if mystring|length_is:"4" %}Four{% endif %}'})
|
||||
def test_length_is03(self):
|
||||
output = render('length_is03', {'mystring': 'word'})
|
||||
self.assertEqual(output, 'Four')
|
||||
|
||||
@setup({'length_is04': '{% if mystring|length_is:"4" %}Four{% else %}Not Four{% endif %}'})
|
||||
def test_length_is04(self):
|
||||
output = render('length_is04', {'mystring': 'Python'})
|
||||
self.assertEqual(output, 'Not Four')
|
||||
|
||||
@setup({'length_is05': '{% if mystring|length_is:"4" %}Four{% else %}Not Four{% endif %}'})
|
||||
def test_length_is05(self):
|
||||
output = render('length_is05', {'mystring': ''})
|
||||
self.assertEqual(output, 'Not Four')
|
||||
|
||||
@setup({'length_is06': '{% with var|length as my_length %}{{ my_length }}{% endwith %}'})
|
||||
def test_length_is06(self):
|
||||
output = render('length_is06', {'var': 'django'})
|
||||
self.assertEqual(output, '6')
|
||||
|
||||
# Boolean return value from length_is should not be coerced to a string
|
||||
@setup({'length_is07': '{% if "X"|length_is:0 %}Length is 0{% else %}Length not 0{% endif %}'})
|
||||
def test_length_is07(self):
|
||||
output = render('length_is07', {})
|
||||
self.assertEqual(output, 'Length not 0')
|
||||
|
||||
@setup({'length_is08': '{% if "X"|length_is:1 %}Length is 1{% else %}Length not 1{% endif %}'})
|
||||
def test_length_is08(self):
|
||||
output = render('length_is08', {})
|
||||
self.assertEqual(output, 'Length is 1')
|
||||
|
||||
# Invalid uses that should fail silently.
|
||||
@setup({'length_is09': '{{ var|length_is:"fish" }}'})
|
||||
def test_length_is09(self):
|
||||
output = render('length_is09', {'var': 'django'})
|
||||
self.assertEqual(output, '')
|
||||
|
||||
@setup({'length_is10': '{{ int|length_is:"1" }}'})
|
||||
def test_length_is10(self):
|
||||
output = render('length_is10', {'int': 7})
|
||||
self.assertEqual(output, '')
|
||||
|
||||
@setup({'length_is11': '{{ none|length_is:"1" }}'})
|
||||
def test_length_is11(self):
|
||||
output = render('length_is11', {'none': None})
|
||||
self.assertEqual(output, '')
|
|
@ -0,0 +1,22 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class LinebreaksTests(SimpleTestCase):
|
||||
"""
|
||||
The contents in "linebreaks" are escaped according to the current
|
||||
autoescape setting.
|
||||
"""
|
||||
|
||||
@setup({'linebreaks01': '{{ a|linebreaks }} {{ b|linebreaks }}'})
|
||||
def test_linebreaks01(self):
|
||||
output = render('linebreaks01', {"a": "x&\ny", "b": mark_safe("x&\ny")})
|
||||
self.assertEqual(output, "<p>x&<br />y</p> <p>x&<br />y</p>")
|
||||
|
||||
@setup({'linebreaks02':
|
||||
'{% autoescape off %}{{ a|linebreaks }} {{ b|linebreaks }}{% endautoescape %}'})
|
||||
def test_linebreaks02(self):
|
||||
output = render('linebreaks02', {"a": "x&\ny", "b": mark_safe("x&\ny")})
|
||||
self.assertEqual(output, "<p>x&<br />y</p> <p>x&<br />y</p>")
|
|
@ -0,0 +1,22 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class LinebreaksbrTests(SimpleTestCase):
|
||||
"""
|
||||
The contents in "linebreaksbr" are escaped according to the current
|
||||
autoescape setting.
|
||||
"""
|
||||
|
||||
@setup({'linebreaksbr01': '{{ a|linebreaksbr }} {{ b|linebreaksbr }}'})
|
||||
def test_linebreaksbr01(self):
|
||||
output = render('linebreaksbr01', {"a": "x&\ny", "b": mark_safe("x&\ny")})
|
||||
self.assertEqual(output, "x&<br />y x&<br />y")
|
||||
|
||||
@setup({'linebreaksbr02':
|
||||
'{% autoescape off %}{{ a|linebreaksbr }} {{ b|linebreaksbr }}{% endautoescape %}'})
|
||||
def test_linebreaksbr02(self):
|
||||
output = render('linebreaksbr02', {"a": "x&\ny", "b": mark_safe("x&\ny")})
|
||||
self.assertEqual(output, "x&<br />y x&<br />y")
|
|
@ -0,0 +1,30 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class LinenumbersTests(SimpleTestCase):
|
||||
"""
|
||||
The contents of "linenumbers" is escaped according to the current
|
||||
autoescape setting.
|
||||
"""
|
||||
|
||||
@setup({'linenumbers01': '{{ a|linenumbers }} {{ b|linenumbers }}'})
|
||||
def test_linenumbers01(self):
|
||||
output = render(
|
||||
'linenumbers01',
|
||||
{'a': 'one\n<two>\nthree', 'b': mark_safe('one\n<two>\nthree')},
|
||||
)
|
||||
self.assertEqual(output, '1. one\n2. <two>\n3. three '
|
||||
'1. one\n2. <two>\n3. three')
|
||||
|
||||
@setup({'linenumbers02':
|
||||
'{% autoescape off %}{{ a|linenumbers }} {{ b|linenumbers }}{% endautoescape %}'})
|
||||
def test_linenumbers02(self):
|
||||
output = render(
|
||||
'linenumbers02',
|
||||
{'a': 'one\n<two>\nthree', 'b': mark_safe('one\n<two>\nthree')},
|
||||
)
|
||||
self.assertEqual(output, '1. one\n2. <two>\n3. three '
|
||||
'1. one\n2. <two>\n3. three')
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class LjustTests(SimpleTestCase):
|
||||
|
||||
@setup({'ljust01': '{% autoescape off %}.{{ a|ljust:"5" }}. .{{ b|ljust:"5" }}.{% endautoescape %}'})
|
||||
def test_ljust01(self):
|
||||
output = render('ljust01', {"a": "a&b", "b": mark_safe("a&b")})
|
||||
self.assertEqual(output, ".a&b . .a&b .")
|
||||
|
||||
@setup({'ljust02': '.{{ a|ljust:"5" }}. .{{ b|ljust:"5" }}.'})
|
||||
def test_ljust02(self):
|
||||
output = render('ljust02', {"a": "a&b", "b": mark_safe("a&b")})
|
||||
self.assertEqual(output, ".a&b . .a&b .")
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class LowerTests(SimpleTestCase):
|
||||
|
||||
@setup({'lower01': '{% autoescape off %}{{ a|lower }} {{ b|lower }}{% endautoescape %}'})
|
||||
def test_lower01(self):
|
||||
output = render('lower01', {"a": "Apple & banana", "b": mark_safe("Apple & banana")})
|
||||
self.assertEqual(output, "apple & banana apple & banana")
|
||||
|
||||
@setup({'lower02': '{{ a|lower }} {{ b|lower }}'})
|
||||
def test_lower02(self):
|
||||
output = render('lower02', {"a": "Apple & banana", "b": mark_safe("Apple & banana")})
|
||||
self.assertEqual(output, "apple & banana apple & banana")
|
|
@ -0,0 +1,33 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.test.utils import str_prefix
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class MakeListTests(SimpleTestCase):
|
||||
"""
|
||||
The make_list filter can destroy existing escaping, so the results are
|
||||
escaped.
|
||||
"""
|
||||
|
||||
@setup({'make_list01': '{% autoescape off %}{{ a|make_list }}{% endautoescape %}'})
|
||||
def test_make_list01(self):
|
||||
output = render('make_list01', {"a": mark_safe("&")})
|
||||
self.assertEqual(output, str_prefix("[%(_)s'&']"))
|
||||
|
||||
@setup({'make_list02': '{{ a|make_list }}'})
|
||||
def test_make_list02(self):
|
||||
output = render('make_list02', {"a": mark_safe("&")})
|
||||
self.assertEqual(output, str_prefix("[%(_)s'&']"))
|
||||
|
||||
@setup({'make_list03':
|
||||
'{% autoescape off %}{{ a|make_list|stringformat:"s"|safe }}{% endautoescape %}'})
|
||||
def test_make_list03(self):
|
||||
output = render('make_list03', {"a": mark_safe("&")})
|
||||
self.assertEqual(output, str_prefix("[%(_)s'&']"))
|
||||
|
||||
@setup({'make_list04': '{{ a|make_list|stringformat:"s"|safe }}'})
|
||||
def test_make_list04(self):
|
||||
output = render('make_list04', {"a": mark_safe("&")})
|
||||
self.assertEqual(output, str_prefix("[%(_)s'&']"))
|
|
@ -0,0 +1,35 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class Phone2numericTests(SimpleTestCase):
|
||||
|
||||
@setup({'phone2numeric01': '{{ a|phone2numeric }} {{ b|phone2numeric }}'})
|
||||
def test_phone2numeric01(self):
|
||||
output = render(
|
||||
'phone2numeric01',
|
||||
{'a': '<1-800-call-me>', 'b': mark_safe('<1-800-call-me>')},
|
||||
)
|
||||
self.assertEqual(output, '<1-800-2255-63> <1-800-2255-63>')
|
||||
|
||||
@setup({'phone2numeric02':
|
||||
'{% autoescape off %}{{ a|phone2numeric }} {{ b|phone2numeric }}{% endautoescape %}'})
|
||||
def test_phone2numeric02(self):
|
||||
output = render(
|
||||
'phone2numeric02',
|
||||
{'a': '<1-800-call-me>', 'b': mark_safe('<1-800-call-me>')},
|
||||
)
|
||||
self.assertEqual(output, '<1-800-2255-63> <1-800-2255-63>')
|
||||
|
||||
@setup({'phone2numeric03': '{{ a|phone2numeric }}'})
|
||||
def test_phone2numeric03(self):
|
||||
output = render(
|
||||
'phone2numeric03',
|
||||
{'a': 'How razorback-jumping frogs can level six piqued gymnasts!'},
|
||||
)
|
||||
self.assertEqual(
|
||||
output,
|
||||
'469 729672225-5867464 37647 226 53835 749 747833 49662787!'
|
||||
)
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class RandomTests(SimpleTestCase):
|
||||
|
||||
@setup({'random01': '{{ a|random }} {{ b|random }}'})
|
||||
def test_random01(self):
|
||||
output = render('random01', {'a': ['a&b', 'a&b'], 'b': [mark_safe('a&b'), mark_safe('a&b')]})
|
||||
self.assertEqual(output, 'a&b a&b')
|
||||
|
||||
@setup({'random02': '{% autoescape off %}{{ a|random }} {{ b|random }}{% endautoescape %}'})
|
||||
def test_random02(self):
|
||||
output = render('random02', {'a': ['a&b', 'a&b'], 'b': [mark_safe('a&b'), mark_safe('a&b')]})
|
||||
self.assertEqual(output, 'a&b a&b')
|
|
@ -0,0 +1,37 @@
|
|||
import warnings
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class RemovetagsTests(SimpleTestCase):
|
||||
|
||||
@setup({'removetags01': '{{ a|removetags:"a b" }} {{ b|removetags:"a b" }}'})
|
||||
def test_removetags01(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', RemovedInDjango20Warning)
|
||||
output = render(
|
||||
'removetags01',
|
||||
{
|
||||
'a': '<a>x</a> <p><b>y</b></p>',
|
||||
'b': mark_safe('<a>x</a> <p><b>y</b></p>'),
|
||||
},
|
||||
)
|
||||
self.assertEqual(output, 'x <p>y</p> x <p>y</p>')
|
||||
|
||||
@setup({'removetags02':
|
||||
'{% autoescape off %}{{ a|removetags:"a b" }} {{ b|removetags:"a b" }}{% endautoescape %}'})
|
||||
def test_removetags02(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', RemovedInDjango20Warning)
|
||||
output = render(
|
||||
'removetags02',
|
||||
{
|
||||
'a': '<a>x</a> <p><b>y</b></p>',
|
||||
'b': mark_safe('<a>x</a> <p><b>y</b></p>'),
|
||||
},
|
||||
)
|
||||
self.assertEqual(output, 'x <p>y</p> x <p>y</p>')
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class RjustTests(SimpleTestCase):
|
||||
|
||||
@setup({'rjust01': '{% autoescape off %}.{{ a|rjust:"5" }}. .{{ b|rjust:"5" }}.{% endautoescape %}'})
|
||||
def test_rjust01(self):
|
||||
output = render('rjust01', {"a": "a&b", "b": mark_safe("a&b")})
|
||||
self.assertEqual(output, ". a&b. . a&b.")
|
||||
|
||||
@setup({'rjust02': '.{{ a|rjust:"5" }}. .{{ b|rjust:"5" }}.'})
|
||||
def test_rjust02(self):
|
||||
output = render('rjust02', {"a": "a&b", "b": mark_safe("a&b")})
|
||||
self.assertEqual(output, ". a&b. . a&b.")
|
|
@ -0,0 +1,16 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class SafeTests(SimpleTestCase):
|
||||
|
||||
@setup({'safe01': '{{ a }} -- {{ a|safe }}'})
|
||||
def test_safe01(self):
|
||||
output = render('safe01', {'a': '<b>hello</b>'})
|
||||
self.assertEqual(output, '<b>hello</b> -- <b>hello</b>')
|
||||
|
||||
@setup({'safe02': '{% autoescape off %}{{ a }} -- {{ a|safe }}{% endautoescape %}'})
|
||||
def test_safe02(self):
|
||||
output = render('safe02', {'a': '<b>hello</b>'})
|
||||
self.assertEqual(output, '<b>hello</b> -- <b>hello</b>')
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class SafeseqTests(SimpleTestCase):
|
||||
|
||||
@setup({'safeseq01': '{{ a|join:", " }} -- {{ a|safeseq|join:", " }}'})
|
||||
def test_safeseq01(self):
|
||||
output = render('safeseq01', {'a': ['&', '<']})
|
||||
self.assertEqual(output, '&, < -- &, <')
|
||||
|
||||
@setup({'safeseq02':
|
||||
'{% autoescape off %}{{ a|join:", " }} -- {{ a|safeseq|join:", " }}{% endautoescape %}'})
|
||||
def test_safeseq02(self):
|
||||
output = render('safeseq02', {'a': ['&', '<']})
|
||||
self.assertEqual(output, '&, < -- &, <')
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class SliceTests(SimpleTestCase):
|
||||
|
||||
@setup({'slice01': '{{ a|slice:"1:3" }} {{ b|slice:"1:3" }}'})
|
||||
def test_slice01(self):
|
||||
output = render('slice01', {'a': 'a&b', 'b': mark_safe('a&b')})
|
||||
self.assertEqual(output, '&b &b')
|
||||
|
||||
@setup({'slice02': '{% autoescape off %}{{ a|slice:"1:3" }} {{ b|slice:"1:3" }}{% endautoescape %}'})
|
||||
def test_slice02(self):
|
||||
output = render('slice02', {'a': 'a&b', 'b': mark_safe('a&b')})
|
||||
self.assertEqual(output, '&b &b')
|
|
@ -0,0 +1,21 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class SlugifyTests(SimpleTestCase):
|
||||
"""
|
||||
Running slugify on a pre-escaped string leads to odd behavior,
|
||||
but the result is still safe.
|
||||
"""
|
||||
|
||||
@setup({'slugify01': '{% autoescape off %}{{ a|slugify }} {{ b|slugify }}{% endautoescape %}'})
|
||||
def test_slugify01(self):
|
||||
output = render('slugify01', {'a': 'a & b', 'b': mark_safe('a & b')})
|
||||
self.assertEqual(output, 'a-b a-amp-b')
|
||||
|
||||
@setup({'slugify02': '{{ a|slugify }} {{ b|slugify }}'})
|
||||
def test_slugify02(self):
|
||||
output = render('slugify02', {'a': 'a & b', 'b': mark_safe('a & b')})
|
||||
self.assertEqual(output, 'a-b a-amp-b')
|
|
@ -0,0 +1,22 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class StringformatTests(SimpleTestCase):
|
||||
"""
|
||||
Notice that escaping is applied *after* any filters, so the string
|
||||
formatting here only needs to deal with pre-escaped characters.
|
||||
"""
|
||||
|
||||
@setup({'stringformat01':
|
||||
'{% autoescape off %}.{{ a|stringformat:"5s" }}. .{{ b|stringformat:"5s" }}.{% endautoescape %}'})
|
||||
def test_stringformat01(self):
|
||||
output = render('stringformat01', {'a': 'a<b', 'b': mark_safe('a<b')})
|
||||
self.assertEqual(output, '. a<b. . a<b.')
|
||||
|
||||
@setup({'stringformat02': '.{{ a|stringformat:"5s" }}. .{{ b|stringformat:"5s" }}.'})
|
||||
def test_stringformat02(self):
|
||||
output = render('stringformat02', {'a': 'a<b', 'b': mark_safe('a<b')})
|
||||
self.assertEqual(output, '. a<b. . a<b.')
|
|
@ -0,0 +1,29 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class StriptagsTests(SimpleTestCase):
|
||||
|
||||
@setup({'striptags01': '{{ a|striptags }} {{ b|striptags }}'})
|
||||
def test_striptags01(self):
|
||||
output = render(
|
||||
'striptags01',
|
||||
{
|
||||
'a': '<a>x</a> <p><b>y</b></p>',
|
||||
'b': mark_safe('<a>x</a> <p><b>y</b></p>'),
|
||||
},
|
||||
)
|
||||
self.assertEqual(output, 'x y x y')
|
||||
|
||||
@setup({'striptags02': '{% autoescape off %}{{ a|striptags }} {{ b|striptags }}{% endautoescape %}'})
|
||||
def test_striptags02(self):
|
||||
output = render(
|
||||
'striptags02',
|
||||
{
|
||||
'a': '<a>x</a> <p><b>y</b></p>',
|
||||
'b': mark_safe('<a>x</a> <p><b>y</b></p>'),
|
||||
},
|
||||
)
|
||||
self.assertEqual(output, 'x y x y')
|
|
@ -0,0 +1,42 @@
|
|||
from datetime import time
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
from .timezone_utils import TimezoneTestCase
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class TimeTests(TimezoneTestCase):
|
||||
"""
|
||||
#20693: Timezone support for the time template filter
|
||||
"""
|
||||
|
||||
@setup({'time01': '{{ dt|time:"e:O:T:Z" }}'})
|
||||
def test_time01(self):
|
||||
output = render('time01', {'dt': self.now_tz_i})
|
||||
self.assertEqual(output, '+0315:+0315:+0315:11700')
|
||||
|
||||
@setup({'time02': '{{ dt|time:"e:T" }}'})
|
||||
def test_time02(self):
|
||||
output = render('time02', {'dt': self.now})
|
||||
self.assertEqual(output, ':' + self.now_tz.tzinfo.tzname(self.now_tz))
|
||||
|
||||
@setup({'time03': '{{ t|time:"P:e:O:T:Z" }}'})
|
||||
def test_time03(self):
|
||||
output = render('time03', {'t': time(4, 0, tzinfo=timezone.get_fixed_timezone(30))})
|
||||
self.assertEqual(output, '4 a.m.::::')
|
||||
|
||||
@setup({'time04': '{{ t|time:"P:e:O:T:Z" }}'})
|
||||
def test_time04(self):
|
||||
output = render('time04', {'t': time(4, 0)})
|
||||
self.assertEqual(output, '4 a.m.::::')
|
||||
|
||||
@setup({'time05': '{{ d|time:"P:e:O:T:Z" }}'})
|
||||
def test_time05(self):
|
||||
output = render('time05', {'d': self.today})
|
||||
self.assertEqual(output, '')
|
||||
|
||||
@setup({'time06': '{{ obj|time:"P:e:O:T:Z" }}'})
|
||||
def test_time06(self):
|
||||
output = render('time06', {'obj': 'non-datetime-value'})
|
||||
self.assertEqual(output, '')
|
|
@ -0,0 +1,118 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from django.test.utils import requires_tz_support
|
||||
|
||||
from .timezone_utils import TimezoneTestCase
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class TimesinceTests(TimezoneTestCase):
|
||||
"""
|
||||
#20246 - \xa0 in output avoids line-breaks between value and unit
|
||||
"""
|
||||
|
||||
# Default compare with datetime.now()
|
||||
@setup({'timesince01': '{{ a|timesince }}'})
|
||||
def test_timesince01(self):
|
||||
output = render('timesince01', {'a': datetime.now() + timedelta(minutes=-1, seconds=-10)})
|
||||
self.assertEqual(output, '1\xa0minute')
|
||||
|
||||
@setup({'timesince02': '{{ a|timesince }}'})
|
||||
def test_timesince02(self):
|
||||
output = render('timesince02', {'a': datetime.now() - timedelta(days=1, minutes=1)})
|
||||
self.assertEqual(output, '1\xa0day')
|
||||
|
||||
@setup({'timesince03': '{{ a|timesince }}'})
|
||||
def test_timesince03(self):
|
||||
output = render('timesince03', {'a': datetime.now() - timedelta(hours=1, minutes=25, seconds=10)})
|
||||
self.assertEqual(output, '1\xa0hour, 25\xa0minutes')
|
||||
|
||||
# Compare to a given parameter
|
||||
@setup({'timesince04': '{{ a|timesince:b }}'})
|
||||
def test_timesince04(self):
|
||||
output = render(
|
||||
'timesince04',
|
||||
{'a': self.now - timedelta(days=2), 'b': self.now - timedelta(days=1)},
|
||||
)
|
||||
self.assertEqual(output, '1\xa0day')
|
||||
|
||||
@setup({'timesince05': '{{ a|timesince:b }}'})
|
||||
def test_timesince05(self):
|
||||
output = render(
|
||||
'timesince05',
|
||||
{'a': self.now - timedelta(days=2, minutes=1), 'b': self.now - timedelta(days=2)},
|
||||
)
|
||||
self.assertEqual(output, '1\xa0minute')
|
||||
|
||||
# Check that timezone is respected
|
||||
@setup({'timesince06': '{{ a|timesince:b }}'})
|
||||
def test_timesince06(self):
|
||||
output = render('timesince06', {'a': self.now_tz - timedelta(hours=8), 'b': self.now_tz})
|
||||
self.assertEqual(output, '8\xa0hours')
|
||||
|
||||
# Tests for #7443
|
||||
@setup({'timesince07': '{{ earlier|timesince }}'})
|
||||
def test_timesince07(self):
|
||||
output = render('timesince07', {'earlier': self.now - timedelta(days=7)})
|
||||
self.assertEqual(output, '1\xa0week')
|
||||
|
||||
@setup({'timesince08': '{{ earlier|timesince:now }}'})
|
||||
def test_timesince08(self):
|
||||
output = render('timesince08', {'now': self.now, 'earlier': self.now - timedelta(days=7)})
|
||||
self.assertEqual(output, '1\xa0week')
|
||||
|
||||
@setup({'timesince09': '{{ later|timesince }}'})
|
||||
def test_timesince09(self):
|
||||
output = render('timesince09', {'later': self.now + timedelta(days=7)})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@setup({'timesince10': '{{ later|timesince:now }}'})
|
||||
def test_timesince10(self):
|
||||
output = render('timesince10', {'now': self.now, 'later': self.now + timedelta(days=7)})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
# Ensures that differing timezones are calculated correctly.
|
||||
@setup({'timesince11': '{{ a|timesince }}'})
|
||||
def test_timesince11(self):
|
||||
output = render('timesince11', {'a': self.now})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@requires_tz_support
|
||||
@setup({'timesince12': '{{ a|timesince }}'})
|
||||
def test_timesince12(self):
|
||||
output = render('timesince12', {'a': self.now_tz})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@requires_tz_support
|
||||
@setup({'timesince13': '{{ a|timesince }}'})
|
||||
def test_timesince13(self):
|
||||
output = render('timesince13', {'a': self.now_tz_i})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@setup({'timesince14': '{{ a|timesince:b }}'})
|
||||
def test_timesince14(self):
|
||||
output = render('timesince14', {'a': self.now_tz, 'b': self.now_tz_i})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@setup({'timesince15': '{{ a|timesince:b }}'})
|
||||
def test_timesince15(self):
|
||||
output = render('timesince15', {'a': self.now, 'b': self.now_tz_i})
|
||||
self.assertEqual(output, '')
|
||||
|
||||
@setup({'timesince16': '{{ a|timesince:b }}'})
|
||||
def test_timesince16(self):
|
||||
output = render('timesince16', {'a': self.now_tz_i, 'b': self.now})
|
||||
self.assertEqual(output, '')
|
||||
|
||||
# Tests for #9065 (two date objects).
|
||||
@setup({'timesince17': '{{ a|timesince:b }}'})
|
||||
def test_timesince17(self):
|
||||
output = render('timesince17', {'a': self.today, 'b': self.today})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@setup({'timesince18': '{{ a|timesince:b }}'})
|
||||
def test_timesince18(self):
|
||||
output = render('timesince18', {'a': self.today, 'b': self.today + timedelta(hours=24)})
|
||||
self.assertEqual(output, '1\xa0day')
|
|
@ -0,0 +1,94 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from django.test.utils import requires_tz_support
|
||||
|
||||
from .timezone_utils import TimezoneTestCase
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class TimeuntilTests(TimezoneTestCase):
|
||||
|
||||
# Default compare with datetime.now()
|
||||
@setup({'timeuntil01': '{{ a|timeuntil }}'})
|
||||
def test_timeuntil01(self):
|
||||
output = render('timeuntil01', {'a': datetime.now() + timedelta(minutes=2, seconds=10)})
|
||||
self.assertEqual(output, '2\xa0minutes')
|
||||
|
||||
@setup({'timeuntil02': '{{ a|timeuntil }}'})
|
||||
def test_timeuntil02(self):
|
||||
output = render('timeuntil02', {'a': (datetime.now() + timedelta(days=1, seconds=10))})
|
||||
self.assertEqual(output, '1\xa0day')
|
||||
|
||||
@setup({'timeuntil03': '{{ a|timeuntil }}'})
|
||||
def test_timeuntil03(self):
|
||||
output = render('timeuntil03', {'a': (datetime.now() + timedelta(hours=8, minutes=10, seconds=10))})
|
||||
self.assertEqual(output, '8\xa0hours, 10\xa0minutes')
|
||||
|
||||
# Compare to a given parameter
|
||||
@setup({'timeuntil04': '{{ a|timeuntil:b }}'})
|
||||
def test_timeuntil04(self):
|
||||
output = render(
|
||||
'timeuntil04',
|
||||
{'a': self.now - timedelta(days=1), 'b': self.now - timedelta(days=2)},
|
||||
)
|
||||
self.assertEqual(output, '1\xa0day')
|
||||
|
||||
@setup({'timeuntil05': '{{ a|timeuntil:b }}'})
|
||||
def test_timeuntil05(self):
|
||||
output = render(
|
||||
'timeuntil05',
|
||||
{'a': self.now - timedelta(days=2), 'b': self.now - timedelta(days=2, minutes=1)},
|
||||
)
|
||||
self.assertEqual(output, '1\xa0minute')
|
||||
|
||||
# Regression for #7443
|
||||
@setup({'timeuntil06': '{{ earlier|timeuntil }}'})
|
||||
def test_timeuntil06(self):
|
||||
output = render('timeuntil06', {'earlier': self.now - timedelta(days=7)})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@setup({'timeuntil07': '{{ earlier|timeuntil:now }}'})
|
||||
def test_timeuntil07(self):
|
||||
output = render('timeuntil07', {'now': self.now, 'earlier': self.now - timedelta(days=7)})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@setup({'timeuntil08': '{{ later|timeuntil }}'})
|
||||
def test_timeuntil08(self):
|
||||
output = render('timeuntil08', {'later': self.now + timedelta(days=7, hours=1)})
|
||||
self.assertEqual(output, '1\xa0week')
|
||||
|
||||
@setup({'timeuntil09': '{{ later|timeuntil:now }}'})
|
||||
def test_timeuntil09(self):
|
||||
output = render('timeuntil09', {'now': self.now, 'later': self.now + timedelta(days=7)})
|
||||
self.assertEqual(output, '1\xa0week')
|
||||
|
||||
# Ensures that differing timezones are calculated correctly.
|
||||
@requires_tz_support
|
||||
@setup({'timeuntil10': '{{ a|timeuntil }}'})
|
||||
def test_timeuntil10(self):
|
||||
output = render('timeuntil10', {'a': self.now_tz})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@requires_tz_support
|
||||
@setup({'timeuntil11': '{{ a|timeuntil }}'})
|
||||
def test_timeuntil11(self):
|
||||
output = render('timeuntil11', {'a': self.now_tz_i})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@setup({'timeuntil12': '{{ a|timeuntil:b }}'})
|
||||
def test_timeuntil12(self):
|
||||
output = render('timeuntil12', {'a': self.now_tz_i, 'b': self.now_tz})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
# Regression for #9065 (two date objects).
|
||||
@setup({'timeuntil13': '{{ a|timeuntil:b }}'})
|
||||
def test_timeuntil13(self):
|
||||
output = render('timeuntil13', {'a': self.today, 'b': self.today})
|
||||
self.assertEqual(output, '0\xa0minutes')
|
||||
|
||||
@setup({'timeuntil14': '{{ a|timeuntil:b }}'})
|
||||
def test_timeuntil14(self):
|
||||
output = render('timeuntil14', {'a': self.today, 'b': self.today - timedelta(hours=24)})
|
||||
self.assertEqual(output, '1\xa0day')
|
|
@ -0,0 +1,16 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class TitleTests(SimpleTestCase):
|
||||
|
||||
@setup({'title1': '{{ a|title }}'})
|
||||
def test_title1(self):
|
||||
output = render('title1', {'a': 'JOE\'S CRAB SHACK'})
|
||||
self.assertEqual(output, 'Joe's Crab Shack')
|
||||
|
||||
@setup({'title2': '{{ a|title }}'})
|
||||
def test_title2(self):
|
||||
output = render('title2', {'a': '555 WEST 53RD STREET'})
|
||||
self.assertEqual(output, '555 West 53rd Street')
|
|
@ -0,0 +1,16 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class TruncatecharsTests(SimpleTestCase):
|
||||
|
||||
@setup({'truncatechars01': '{{ a|truncatechars:5 }}'})
|
||||
def test_truncatechars01(self):
|
||||
output = render('truncatechars01', {'a': 'Testing, testing'})
|
||||
self.assertEqual(output, 'Te...')
|
||||
|
||||
@setup({'truncatechars02': '{{ a|truncatechars:7 }}'})
|
||||
def test_truncatechars02(self):
|
||||
output = render('truncatechars02', {'a': 'Testing'})
|
||||
self.assertEqual(output, 'Testing')
|
|
@ -0,0 +1,18 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class TruncatewordsTests(SimpleTestCase):
|
||||
|
||||
@setup({'truncatewords01':
|
||||
'{% autoescape off %}{{ a|truncatewords:"2" }} {{ b|truncatewords:"2"}}{% endautoescape %}'})
|
||||
def test_truncatewords01(self):
|
||||
output = render('truncatewords01', {'a': 'alpha & bravo', 'b': mark_safe('alpha & bravo')})
|
||||
self.assertEqual(output, 'alpha & ... alpha & ...')
|
||||
|
||||
@setup({'truncatewords02': '{{ a|truncatewords:"2" }} {{ b|truncatewords:"2"}}'})
|
||||
def test_truncatewords02(self):
|
||||
output = render('truncatewords02', {'a': 'alpha & bravo', 'b': mark_safe('alpha & bravo')})
|
||||
self.assertEqual(output, 'alpha & ... alpha & ...')
|
|
@ -0,0 +1,75 @@
|
|||
import warnings
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class UnorderedListTests(SimpleTestCase):
|
||||
|
||||
@setup({'unordered_list01': '{{ a|unordered_list }}'})
|
||||
def test_unordered_list01(self):
|
||||
output = render('unordered_list01', {'a': ['x>', ['<y']]})
|
||||
self.assertEqual(output, '\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>')
|
||||
|
||||
@setup({'unordered_list02': '{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}'})
|
||||
def test_unordered_list02(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', RemovedInDjango20Warning)
|
||||
output = render('unordered_list02', {'a': ['x>', ['<y']]})
|
||||
self.assertEqual(output, '\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>')
|
||||
|
||||
@setup({'unordered_list03': '{{ a|unordered_list }}'})
|
||||
def test_unordered_list03(self):
|
||||
output = render('unordered_list03', {'a': ['x>', [mark_safe('<y')]]})
|
||||
self.assertEqual(output, '\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>')
|
||||
|
||||
@setup({'unordered_list04': '{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}'})
|
||||
def test_unordered_list04(self):
|
||||
output = render('unordered_list04', {'a': ['x>', [mark_safe('<y')]]})
|
||||
self.assertEqual(output, '\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>')
|
||||
|
||||
@setup({'unordered_list05': '{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}'})
|
||||
def test_unordered_list05(self):
|
||||
output = render('unordered_list05', {'a': ['x>', ['<y']]})
|
||||
self.assertEqual(output, '\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>')
|
||||
|
||||
|
||||
class DeprecatedUnorderedListSyntaxTests(SimpleTestCase):
|
||||
|
||||
@setup({'unordered_list01': '{{ a|unordered_list }}'})
|
||||
def test_unordered_list01(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', RemovedInDjango20Warning)
|
||||
output = render('unordered_list01', {'a': ['x>', [['<y', []]]]})
|
||||
self.assertEqual(output, '\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>')
|
||||
|
||||
@setup({'unordered_list02': '{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}'})
|
||||
def test_unordered_list02(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', RemovedInDjango20Warning)
|
||||
output = render('unordered_list02', {'a': ['x>', [['<y', []]]]})
|
||||
self.assertEqual(output, '\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>')
|
||||
|
||||
@setup({'unordered_list03': '{{ a|unordered_list }}'})
|
||||
def test_unordered_list03(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', RemovedInDjango20Warning)
|
||||
output = render('unordered_list03', {'a': ['x>', [[mark_safe('<y'), []]]]})
|
||||
self.assertEqual(output, '\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>')
|
||||
|
||||
@setup({'unordered_list04': '{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}'})
|
||||
def test_unordered_list04(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', RemovedInDjango20Warning)
|
||||
output = render('unordered_list04', {'a': ['x>', [[mark_safe('<y'), []]]]})
|
||||
self.assertEqual(output, '\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>')
|
||||
|
||||
@setup({'unordered_list05': '{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}'})
|
||||
def test_unordered_list05(self):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter('ignore', RemovedInDjango20Warning)
|
||||
output = render('unordered_list05', {'a': ['x>', [['<y', []]]]})
|
||||
self.assertEqual(output, '\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>')
|
|
@ -0,0 +1,21 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class UpperTests(SimpleTestCase):
|
||||
"""
|
||||
The "upper" filter messes up entities (which are case-sensitive),
|
||||
so it's not safe for non-escaping purposes.
|
||||
"""
|
||||
|
||||
@setup({'upper01': '{% autoescape off %}{{ a|upper }} {{ b|upper }}{% endautoescape %}'})
|
||||
def test_upper01(self):
|
||||
output = render('upper01', {'a': 'a & b', 'b': mark_safe('a & b')})
|
||||
self.assertEqual(output, 'A & B A & B')
|
||||
|
||||
@setup({'upper02': '{{ a|upper }} {{ b|upper }}'})
|
||||
def test_upper02(self):
|
||||
output = render('upper02', {'a': 'a & b', 'b': mark_safe('a & b')})
|
||||
self.assertEqual(output, 'A & B A &AMP; B')
|
|
@ -0,0 +1,16 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class UrlencodeTests(SimpleTestCase):
|
||||
|
||||
@setup({'urlencode01': '{{ url|urlencode }}'})
|
||||
def test_urlencode01(self):
|
||||
output = render('urlencode01', {'url': '/test&"/me?/'})
|
||||
self.assertEqual(output, '/test%26%22/me%3F/')
|
||||
|
||||
@setup({'urlencode02': '/test/{{ urlbit|urlencode:"" }}/'})
|
||||
def test_urlencode02(self):
|
||||
output = render('urlencode02', {'urlbit': 'escape/slash'})
|
||||
self.assertEqual(output, '/test/escape%2Fslash/')
|
|
@ -0,0 +1,70 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class UrlizeTests(SimpleTestCase):
|
||||
|
||||
@setup({'urlize01': '{% autoescape off %}{{ a|urlize }} {{ b|urlize }}{% endautoescape %}'})
|
||||
def test_urlize01(self):
|
||||
output = render(
|
||||
'urlize01',
|
||||
{'a': 'http://example.com/?x=&y=', 'b': mark_safe('http://example.com?x=&y=<2>')},
|
||||
)
|
||||
self.assertEqual(
|
||||
output,
|
||||
'<a href="http://example.com/?x=&y=" rel="nofollow">http://example.com/?x=&y=</a> '
|
||||
'<a href="http://example.com?x=&y=%3C2%3E" rel="nofollow">http://example.com?x=&y=<2></a>'
|
||||
)
|
||||
|
||||
@setup({'urlize02': '{{ a|urlize }} {{ b|urlize }}'})
|
||||
def test_urlize02(self):
|
||||
output = render(
|
||||
'urlize02',
|
||||
{'a': "http://example.com/?x=&y=", 'b': mark_safe("http://example.com?x=&y=")},
|
||||
)
|
||||
self.assertEqual(
|
||||
output,
|
||||
'<a href="http://example.com/?x=&y=" rel="nofollow">http://example.com/?x=&y=</a> '
|
||||
'<a href="http://example.com?x=&y=" rel="nofollow">http://example.com?x=&y=</a>'
|
||||
)
|
||||
|
||||
@setup({'urlize03': '{% autoescape off %}{{ a|urlize }}{% endautoescape %}'})
|
||||
def test_urlize03(self):
|
||||
output = render('urlize03', {'a': mark_safe("a & b")})
|
||||
self.assertEqual(output, 'a & b')
|
||||
|
||||
@setup({'urlize04': '{{ a|urlize }}'})
|
||||
def test_urlize04(self):
|
||||
output = render('urlize04', {'a': mark_safe("a & b")})
|
||||
self.assertEqual(output, 'a & b')
|
||||
|
||||
# This will lead to a nonsense result, but at least it won't be
|
||||
# exploitable for XSS purposes when auto-escaping is on.
|
||||
@setup({'urlize05': '{% autoescape off %}{{ a|urlize }}{% endautoescape %}'})
|
||||
def test_urlize05(self):
|
||||
output = render('urlize05', {'a': "<script>alert('foo')</script>"})
|
||||
self.assertEqual(output, "<script>alert('foo')</script>")
|
||||
|
||||
@setup({'urlize06': '{{ a|urlize }}'})
|
||||
def test_urlize06(self):
|
||||
output = render('urlize06', {'a': "<script>alert('foo')</script>"})
|
||||
self.assertEqual(output, '<script>alert('foo')</script>')
|
||||
|
||||
# mailto: testing for urlize
|
||||
@setup({'urlize07': '{{ a|urlize }}'})
|
||||
def test_urlize07(self):
|
||||
output = render('urlize07', {'a': "Email me at me@example.com"})
|
||||
self.assertEqual(
|
||||
output,
|
||||
'Email me at <a href="mailto:me@example.com">me@example.com</a>',
|
||||
)
|
||||
|
||||
@setup({'urlize08': '{{ a|urlize }}'})
|
||||
def test_urlize08(self):
|
||||
output = render('urlize08', {'a': "Email me at <me@example.com>"})
|
||||
self.assertEqual(
|
||||
output,
|
||||
'Email me at <<a href="mailto:me@example.com">me@example.com</a>>',
|
||||
)
|
|
@ -0,0 +1,38 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class UrlizetruncTests(SimpleTestCase):
|
||||
|
||||
@setup({'urlizetrunc01':
|
||||
'{% autoescape off %}{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}{% endautoescape %}'})
|
||||
def test_urlizetrunc01(self):
|
||||
output = render(
|
||||
'urlizetrunc01',
|
||||
{
|
||||
'a': '"Unsafe" http://example.com/x=&y=',
|
||||
'b': mark_safe('"Safe" http://example.com?x=&y='),
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
output,
|
||||
'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> '
|
||||
'"Safe" <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'
|
||||
)
|
||||
|
||||
@setup({'urlizetrunc02': '{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}'})
|
||||
def test_urlizetrunc02(self):
|
||||
output = render(
|
||||
'urlizetrunc02',
|
||||
{
|
||||
'a': '"Unsafe" http://example.com/x=&y=',
|
||||
'b': mark_safe('"Safe" http://example.com?x=&y='),
|
||||
},
|
||||
)
|
||||
self.assertEqual(
|
||||
output,
|
||||
'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> '
|
||||
'"Safe" <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'
|
||||
)
|
|
@ -0,0 +1,17 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class WordcountTests(SimpleTestCase):
|
||||
|
||||
@setup({'wordcount01': '{% autoescape off %}{{ a|wordcount }} {{ b|wordcount }}{% endautoescape %}'})
|
||||
def test_wordcount01(self):
|
||||
output = render('wordcount01', {'a': 'a & b', 'b': mark_safe('a & b')})
|
||||
self.assertEqual(output, '3 3')
|
||||
|
||||
@setup({'wordcount02': '{{ a|wordcount }} {{ b|wordcount }}'})
|
||||
def test_wordcount02(self):
|
||||
output = render('wordcount02', {'a': 'a & b', 'b': mark_safe('a & b')})
|
||||
self.assertEqual(output, '3 3')
|
|
@ -0,0 +1,18 @@
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class WordwrapTests(SimpleTestCase):
|
||||
|
||||
@setup({'wordwrap01':
|
||||
'{% autoescape off %}{{ a|wordwrap:"3" }} {{ b|wordwrap:"3" }}{% endautoescape %}'})
|
||||
def test_wordwrap01(self):
|
||||
output = render('wordwrap01', {'a': 'a & b', 'b': mark_safe('a & b')})
|
||||
self.assertEqual(output, 'a &\nb a &\nb')
|
||||
|
||||
@setup({'wordwrap02': '{{ a|wordwrap:"3" }} {{ b|wordwrap:"3" }}'})
|
||||
def test_wordwrap02(self):
|
||||
output = render('wordwrap02', {'a': 'a & b', 'b': mark_safe('a & b')})
|
||||
self.assertEqual(output, 'a &\nb a &\nb')
|
|
@ -0,0 +1,17 @@
|
|||
from datetime import date, datetime
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
class TimezoneTestCase(SimpleTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.now = datetime.now()
|
||||
self.now_tz = timezone.make_aware(
|
||||
self.now, timezone.get_default_timezone(),
|
||||
)
|
||||
self.now_tz_i = timezone.localtime(
|
||||
self.now_tz, timezone.get_fixed_timezone(195),
|
||||
)
|
||||
self.today = date.today()
|
|
@ -1,387 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Tests for template filters (as opposed to template tags).
|
||||
|
||||
The tests are hidden inside a function so that things like timestamps and
|
||||
timezones are only evaluated at the moment of execution and will therefore be
|
||||
consistent.
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from datetime import date, datetime, time, timedelta
|
||||
|
||||
from django.test.utils import str_prefix, TZ_SUPPORT
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils import timezone
|
||||
|
||||
from .syntax_tests.utils import SafeClass, UnsafeClass
|
||||
|
||||
|
||||
# RESULT SYNTAX --
|
||||
# 'template_name': ('template contents', 'context dict',
|
||||
# 'expected string output' or Exception class)
|
||||
|
||||
|
||||
def get_filter_tests():
|
||||
now = datetime.now()
|
||||
now_tz = timezone.make_aware(now, timezone.get_default_timezone())
|
||||
now_tz_i = timezone.localtime(now_tz, timezone.get_fixed_timezone(195))
|
||||
today = date.today()
|
||||
|
||||
# NOTE: \xa0 avoids wrapping between value and unit
|
||||
return {
|
||||
# Default compare with datetime.now()
|
||||
'filter-timesince01': ('{{ a|timesince }}', {'a': datetime.now() + timedelta(minutes=-1, seconds=-10)}, '1\xa0minute'),
|
||||
'filter-timesince02': ('{{ a|timesince }}', {'a': datetime.now() - timedelta(days=1, minutes=1)}, '1\xa0day'),
|
||||
'filter-timesince03': ('{{ a|timesince }}', {'a': datetime.now() - timedelta(hours=1, minutes=25, seconds=10)}, '1\xa0hour, 25\xa0minutes'),
|
||||
|
||||
# Compare to a given parameter
|
||||
'filter-timesince04': ('{{ a|timesince:b }}', {'a': now - timedelta(days=2), 'b': now - timedelta(days=1)}, '1\xa0day'),
|
||||
'filter-timesince05': ('{{ a|timesince:b }}', {'a': now - timedelta(days=2, minutes=1), 'b': now - timedelta(days=2)}, '1\xa0minute'),
|
||||
|
||||
# Check that timezone is respected
|
||||
'filter-timesince06': ('{{ a|timesince:b }}', {'a': now_tz - timedelta(hours=8), 'b': now_tz}, '8\xa0hours'),
|
||||
|
||||
# Regression for #7443
|
||||
'filter-timesince07': ('{{ earlier|timesince }}', {'earlier': now - timedelta(days=7)}, '1\xa0week'),
|
||||
'filter-timesince08': ('{{ earlier|timesince:now }}', {'now': now, 'earlier': now - timedelta(days=7)}, '1\xa0week'),
|
||||
'filter-timesince09': ('{{ later|timesince }}', {'later': now + timedelta(days=7)}, '0\xa0minutes'),
|
||||
'filter-timesince10': ('{{ later|timesince:now }}', {'now': now, 'later': now + timedelta(days=7)}, '0\xa0minutes'),
|
||||
|
||||
# Ensures that differing timezones are calculated correctly
|
||||
# Tests trying to compare a timezone-aware 'now' to now aren't supported on no-tz-support systems (e.g Windows).
|
||||
'filter-timesince11': ('{{ a|timesince }}', {'a': now}, '0\xa0minutes'),
|
||||
'filter-timesince12': ('{{ a|timesince }}', {'a': now_tz}, '0\xa0minutes') if TZ_SUPPORT else ('', {}, ''),
|
||||
'filter-timesince13': ('{{ a|timesince }}', {'a': now_tz_i}, '0\xa0minutes') if TZ_SUPPORT else ('', {}, ''),
|
||||
'filter-timesince14': ('{{ a|timesince:b }}', {'a': now_tz, 'b': now_tz_i}, '0\xa0minutes'),
|
||||
'filter-timesince15': ('{{ a|timesince:b }}', {'a': now, 'b': now_tz_i}, ''),
|
||||
'filter-timesince16': ('{{ a|timesince:b }}', {'a': now_tz_i, 'b': now}, ''),
|
||||
|
||||
# Regression for #9065 (two date objects).
|
||||
'filter-timesince17': ('{{ a|timesince:b }}', {'a': today, 'b': today}, '0\xa0minutes'),
|
||||
'filter-timesince18': ('{{ a|timesince:b }}', {'a': today, 'b': today + timedelta(hours=24)}, '1\xa0day'),
|
||||
|
||||
# Default compare with datetime.now()
|
||||
'filter-timeuntil01': ('{{ a|timeuntil }}', {'a': datetime.now() + timedelta(minutes=2, seconds=10)}, '2\xa0minutes'),
|
||||
'filter-timeuntil02': ('{{ a|timeuntil }}', {'a': (datetime.now() + timedelta(days=1, seconds=10))}, '1\xa0day'),
|
||||
'filter-timeuntil03': ('{{ a|timeuntil }}', {'a': (datetime.now() + timedelta(hours=8, minutes=10, seconds=10))}, '8\xa0hours, 10\xa0minutes'),
|
||||
|
||||
# Compare to a given parameter
|
||||
'filter-timeuntil04': ('{{ a|timeuntil:b }}', {'a': now - timedelta(days=1), 'b': now - timedelta(days=2)}, '1\xa0day'),
|
||||
'filter-timeuntil05': ('{{ a|timeuntil:b }}', {'a': now - timedelta(days=2), 'b': now - timedelta(days=2, minutes=1)}, '1\xa0minute'),
|
||||
|
||||
# Regression for #7443
|
||||
'filter-timeuntil06': ('{{ earlier|timeuntil }}', {'earlier': now - timedelta(days=7)}, '0\xa0minutes'),
|
||||
'filter-timeuntil07': ('{{ earlier|timeuntil:now }}', {'now': now, 'earlier': now - timedelta(days=7)}, '0\xa0minutes'),
|
||||
'filter-timeuntil08': ('{{ later|timeuntil }}', {'later': now + timedelta(days=7, hours=1)}, '1\xa0week'),
|
||||
'filter-timeuntil09': ('{{ later|timeuntil:now }}', {'now': now, 'later': now + timedelta(days=7)}, '1\xa0week'),
|
||||
|
||||
# Ensures that differing timezones are calculated correctly
|
||||
# Tests trying to compare a timezone-aware 'now' to now aren't supported on no-tz-support systems (e.g Windows).
|
||||
'filter-timeuntil10': ('{{ a|timeuntil }}', {'a': now_tz}, '0\xa0minutes') if TZ_SUPPORT else ('', {}, ''),
|
||||
'filter-timeuntil11': ('{{ a|timeuntil }}', {'a': now_tz_i}, '0\xa0minutes') if TZ_SUPPORT else ('', {}, ''),
|
||||
'filter-timeuntil12': ('{{ a|timeuntil:b }}', {'a': now_tz_i, 'b': now_tz}, '0\xa0minutes'),
|
||||
|
||||
# Regression for #9065 (two date objects).
|
||||
'filter-timeuntil13': ('{{ a|timeuntil:b }}', {'a': today, 'b': today}, '0\xa0minutes'),
|
||||
'filter-timeuntil14': ('{{ a|timeuntil:b }}', {'a': today, 'b': today - timedelta(hours=24)}, '1\xa0day'),
|
||||
|
||||
'filter-addslash01': ("{% autoescape off %}{{ a|addslashes }} {{ b|addslashes }}{% endautoescape %}", {"a": "<a>'", "b": mark_safe("<a>'")}, r"<a>\' <a>\'"),
|
||||
'filter-addslash02': ("{{ a|addslashes }} {{ b|addslashes }}", {"a": "<a>'", "b": mark_safe("<a>'")}, r"<a>\' <a>\'"),
|
||||
|
||||
'filter-capfirst01': ("{% autoescape off %}{{ a|capfirst }} {{ b|capfirst }}{% endautoescape %}", {"a": "fred>", "b": mark_safe("fred>")}, "Fred> Fred>"),
|
||||
'filter-capfirst02': ("{{ a|capfirst }} {{ b|capfirst }}", {"a": "fred>", "b": mark_safe("fred>")}, "Fred> Fred>"),
|
||||
|
||||
'filter-floatformat01': ("{% autoescape off %}{{ a|floatformat }} {{ b|floatformat }}{% endautoescape %}", {"a": "1.42", "b": mark_safe("1.42")}, "1.4 1.4"),
|
||||
'filter-floatformat02': ("{{ a|floatformat }} {{ b|floatformat }}", {"a": "1.42", "b": mark_safe("1.42")}, "1.4 1.4"),
|
||||
|
||||
# The contents of "linenumbers" is escaped according to the current
|
||||
# autoescape setting.
|
||||
'filter-linenumbers01': ("{{ a|linenumbers }} {{ b|linenumbers }}", {"a": "one\n<two>\nthree", "b": mark_safe("one\n<two>\nthree")}, "1. one\n2. <two>\n3. three 1. one\n2. <two>\n3. three"),
|
||||
'filter-linenumbers02': ("{% autoescape off %}{{ a|linenumbers }} {{ b|linenumbers }}{% endautoescape %}", {"a": "one\n<two>\nthree", "b": mark_safe("one\n<two>\nthree")}, "1. one\n2. <two>\n3. three 1. one\n2. <two>\n3. three"),
|
||||
|
||||
'filter-lower01': ("{% autoescape off %}{{ a|lower }} {{ b|lower }}{% endautoescape %}", {"a": "Apple & banana", "b": mark_safe("Apple & banana")}, "apple & banana apple & banana"),
|
||||
'filter-lower02': ("{{ a|lower }} {{ b|lower }}", {"a": "Apple & banana", "b": mark_safe("Apple & banana")}, "apple & banana apple & banana"),
|
||||
|
||||
# The make_list filter can destroy existing escaping, so the results are
|
||||
# escaped.
|
||||
'filter-make_list01': ("{% autoescape off %}{{ a|make_list }}{% endautoescape %}", {"a": mark_safe("&")}, str_prefix("[%(_)s'&']")),
|
||||
'filter-make_list02': ("{{ a|make_list }}", {"a": mark_safe("&")}, str_prefix("[%(_)s'&']")),
|
||||
'filter-make_list03': ('{% autoescape off %}{{ a|make_list|stringformat:"s"|safe }}{% endautoescape %}', {"a": mark_safe("&")}, str_prefix("[%(_)s'&']")),
|
||||
'filter-make_list04': ('{{ a|make_list|stringformat:"s"|safe }}', {"a": mark_safe("&")}, str_prefix("[%(_)s'&']")),
|
||||
|
||||
# Running slugify on a pre-escaped string leads to odd behavior,
|
||||
# but the result is still safe.
|
||||
'filter-slugify01': ("{% autoescape off %}{{ a|slugify }} {{ b|slugify }}{% endautoescape %}", {"a": "a & b", "b": mark_safe("a & b")}, "a-b a-amp-b"),
|
||||
'filter-slugify02': ("{{ a|slugify }} {{ b|slugify }}", {"a": "a & b", "b": mark_safe("a & b")}, "a-b a-amp-b"),
|
||||
|
||||
# Notice that escaping is applied *after* any filters, so the string
|
||||
# formatting here only needs to deal with pre-escaped characters.
|
||||
'filter-stringformat01': ('{% autoescape off %}.{{ a|stringformat:"5s" }}. .{{ b|stringformat:"5s" }}.{% endautoescape %}',
|
||||
{"a": "a<b", "b": mark_safe("a<b")}, ". a<b. . a<b."),
|
||||
'filter-stringformat02': ('.{{ a|stringformat:"5s" }}. .{{ b|stringformat:"5s" }}.', {"a": "a<b", "b": mark_safe("a<b")},
|
||||
". a<b. . a<b."),
|
||||
|
||||
# Test the title filter
|
||||
'filter-title1': ('{{ a|title }}', {'a': 'JOE\'S CRAB SHACK'}, 'Joe's Crab Shack'),
|
||||
'filter-title2': ('{{ a|title }}', {'a': '555 WEST 53RD STREET'}, '555 West 53rd Street'),
|
||||
|
||||
'filter-truncatewords01': ('{% autoescape off %}{{ a|truncatewords:"2" }} {{ b|truncatewords:"2"}}{% endautoescape %}',
|
||||
{"a": "alpha & bravo", "b": mark_safe("alpha & bravo")}, "alpha & ... alpha & ..."),
|
||||
'filter-truncatewords02': ('{{ a|truncatewords:"2" }} {{ b|truncatewords:"2"}}',
|
||||
{"a": "alpha & bravo", "b": mark_safe("alpha & bravo")}, "alpha & ... alpha & ..."),
|
||||
|
||||
'filter-truncatechars01': ('{{ a|truncatechars:5 }}', {'a': "Testing, testing"}, "Te..."),
|
||||
'filter-truncatechars02': ('{{ a|truncatechars:7 }}', {'a': "Testing"}, "Testing"),
|
||||
|
||||
# The "upper" filter messes up entities (which are case-sensitive),
|
||||
# so it's not safe for non-escaping purposes.
|
||||
'filter-upper01': ('{% autoescape off %}{{ a|upper }} {{ b|upper }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, "A & B A & B"),
|
||||
'filter-upper02': ('{{ a|upper }} {{ b|upper }}', {"a": "a & b", "b": mark_safe("a & b")}, "A & B A &AMP; B"),
|
||||
|
||||
'filter-urlize01': (
|
||||
'{% autoescape off %}{{ a|urlize }} {{ b|urlize }}{% endautoescape %}',
|
||||
{"a": "http://example.com/?x=&y=", "b": mark_safe("http://example.com?x=&y=<2>")},
|
||||
'<a href="http://example.com/?x=&y=" rel="nofollow">http://example.com/?x=&y=</a> '
|
||||
'<a href="http://example.com?x=&y=%3C2%3E" rel="nofollow">http://example.com?x=&y=<2></a>'),
|
||||
'filter-urlize02': (
|
||||
'{{ a|urlize }} {{ b|urlize }}',
|
||||
{"a": "http://example.com/?x=&y=", "b": mark_safe("http://example.com?x=&y=")},
|
||||
'<a href="http://example.com/?x=&y=" rel="nofollow">http://example.com/?x=&y=</a> '
|
||||
'<a href="http://example.com?x=&y=" rel="nofollow">http://example.com?x=&y=</a>'),
|
||||
'filter-urlize03': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": mark_safe("a & b")}, 'a & b'),
|
||||
'filter-urlize04': ('{{ a|urlize }}', {"a": mark_safe("a & b")}, 'a & b'),
|
||||
|
||||
# This will lead to a nonsense result, but at least it won't be
|
||||
# exploitable for XSS purposes when auto-escaping is on.
|
||||
'filter-urlize05': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": "<script>alert('foo')</script>"}, "<script>alert('foo')</script>"),
|
||||
'filter-urlize06': ('{{ a|urlize }}', {"a": "<script>alert('foo')</script>"}, '<script>alert('foo')</script>'),
|
||||
|
||||
# mailto: testing for urlize
|
||||
'filter-urlize07': ('{{ a|urlize }}', {"a": "Email me at me@example.com"}, 'Email me at <a href="mailto:me@example.com">me@example.com</a>'),
|
||||
'filter-urlize08': ('{{ a|urlize }}', {"a": "Email me at <me@example.com>"}, 'Email me at <<a href="mailto:me@example.com">me@example.com</a>>'),
|
||||
|
||||
'filter-urlizetrunc01': (
|
||||
'{% autoescape off %}{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}{% endautoescape %}',
|
||||
{"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('"Safe" http://example.com?x=&y=')},
|
||||
'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> '
|
||||
'"Safe" <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'),
|
||||
'filter-urlizetrunc02': (
|
||||
'{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}',
|
||||
{"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('"Safe" http://example.com?x=&y=')},
|
||||
'"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> '
|
||||
'"Safe" <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>'),
|
||||
|
||||
'filter-wordcount01': ('{% autoescape off %}{{ a|wordcount }} {{ b|wordcount }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, "3 3"),
|
||||
'filter-wordcount02': ('{{ a|wordcount }} {{ b|wordcount }}', {"a": "a & b", "b": mark_safe("a & b")}, "3 3"),
|
||||
|
||||
'filter-wordwrap01': ('{% autoescape off %}{{ a|wordwrap:"3" }} {{ b|wordwrap:"3" }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, "a &\nb a &\nb"),
|
||||
'filter-wordwrap02': ('{{ a|wordwrap:"3" }} {{ b|wordwrap:"3" }}', {"a": "a & b", "b": mark_safe("a & b")}, "a &\nb a &\nb"),
|
||||
|
||||
'filter-ljust01': ('{% autoescape off %}.{{ a|ljust:"5" }}. .{{ b|ljust:"5" }}.{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, ".a&b . .a&b ."),
|
||||
'filter-ljust02': ('.{{ a|ljust:"5" }}. .{{ b|ljust:"5" }}.', {"a": "a&b", "b": mark_safe("a&b")}, ".a&b . .a&b ."),
|
||||
|
||||
'filter-rjust01': ('{% autoescape off %}.{{ a|rjust:"5" }}. .{{ b|rjust:"5" }}.{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, ". a&b. . a&b."),
|
||||
'filter-rjust02': ('.{{ a|rjust:"5" }}. .{{ b|rjust:"5" }}.', {"a": "a&b", "b": mark_safe("a&b")}, ". a&b. . a&b."),
|
||||
|
||||
'filter-center01': ('{% autoescape off %}.{{ a|center:"5" }}. .{{ b|center:"5" }}.{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, ". a&b . . a&b ."),
|
||||
'filter-center02': ('.{{ a|center:"5" }}. .{{ b|center:"5" }}.', {"a": "a&b", "b": mark_safe("a&b")}, ". a&b . . a&b ."),
|
||||
|
||||
'filter-cut01': ('{% autoescape off %}{{ a|cut:"x" }} {{ b|cut:"x" }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, "&y &y"),
|
||||
'filter-cut02': ('{{ a|cut:"x" }} {{ b|cut:"x" }}', {"a": "x&y", "b": mark_safe("x&y")}, "&y &y"),
|
||||
'filter-cut03': ('{% autoescape off %}{{ a|cut:"&" }} {{ b|cut:"&" }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, "xy xamp;y"),
|
||||
'filter-cut04': ('{{ a|cut:"&" }} {{ b|cut:"&" }}', {"a": "x&y", "b": mark_safe("x&y")}, "xy xamp;y"),
|
||||
# Passing ';' to cut can break existing HTML entities, so those strings
|
||||
# are auto-escaped.
|
||||
'filter-cut05': ('{% autoescape off %}{{ a|cut:";" }} {{ b|cut:";" }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, "x&y x&y"),
|
||||
'filter-cut06': ('{{ a|cut:";" }} {{ b|cut:";" }}', {"a": "x&y", "b": mark_safe("x&y")}, "x&y x&ampy"),
|
||||
|
||||
# The "escape" filter works the same whether autoescape is on or off,
|
||||
# but it has no effect on strings already marked as safe.
|
||||
'filter-escape01': ('{{ a|escape }} {{ b|escape }}', {"a": "x&y", "b": mark_safe("x&y")}, "x&y x&y"),
|
||||
'filter-escape02': ('{% autoescape off %}{{ a|escape }} {{ b|escape }}{% endautoescape %}', {"a": "x&y", "b": mark_safe("x&y")}, "x&y x&y"),
|
||||
|
||||
# It is only applied once, regardless of the number of times it
|
||||
# appears in a chain.
|
||||
'filter-escape03': ('{% autoescape off %}{{ a|escape|escape }}{% endautoescape %}', {"a": "x&y"}, "x&y"),
|
||||
'filter-escape04': ('{{ a|escape|escape }}', {"a": "x&y"}, "x&y"),
|
||||
|
||||
# Force_escape is applied immediately. It can be used to provide
|
||||
# double-escaping, for example.
|
||||
'filter-force-escape01': ('{% autoescape off %}{{ a|force_escape }}{% endautoescape %}', {"a": "x&y"}, "x&y"),
|
||||
'filter-force-escape02': ('{{ a|force_escape }}', {"a": "x&y"}, "x&y"),
|
||||
'filter-force-escape03': ('{% autoescape off %}{{ a|force_escape|force_escape }}{% endautoescape %}', {"a": "x&y"}, "x&amp;y"),
|
||||
'filter-force-escape04': ('{{ a|force_escape|force_escape }}', {"a": "x&y"}, "x&amp;y"),
|
||||
|
||||
# Because the result of force_escape is "safe", an additional
|
||||
# escape filter has no effect.
|
||||
'filter-force-escape05': ('{% autoescape off %}{{ a|force_escape|escape }}{% endautoescape %}', {"a": "x&y"}, "x&y"),
|
||||
'filter-force-escape06': ('{{ a|force_escape|escape }}', {"a": "x&y"}, "x&y"),
|
||||
'filter-force-escape07': ('{% autoescape off %}{{ a|escape|force_escape }}{% endautoescape %}', {"a": "x&y"}, "x&y"),
|
||||
'filter-force-escape08': ('{{ a|escape|force_escape }}', {"a": "x&y"}, "x&y"),
|
||||
|
||||
# The contents in "linebreaks" and "linebreaksbr" are escaped
|
||||
# according to the current autoescape setting.
|
||||
'filter-linebreaks01': ('{{ a|linebreaks }} {{ b|linebreaks }}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, "<p>x&<br />y</p> <p>x&<br />y</p>"),
|
||||
'filter-linebreaks02': ('{% autoescape off %}{{ a|linebreaks }} {{ b|linebreaks }}{% endautoescape %}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, "<p>x&<br />y</p> <p>x&<br />y</p>"),
|
||||
|
||||
'filter-linebreaksbr01': ('{{ a|linebreaksbr }} {{ b|linebreaksbr }}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, "x&<br />y x&<br />y"),
|
||||
'filter-linebreaksbr02': ('{% autoescape off %}{{ a|linebreaksbr }} {{ b|linebreaksbr }}{% endautoescape %}', {"a": "x&\ny", "b": mark_safe("x&\ny")}, "x&<br />y x&<br />y"),
|
||||
|
||||
'filter-safe01': ("{{ a }} -- {{ a|safe }}", {"a": "<b>hello</b>"}, "<b>hello</b> -- <b>hello</b>"),
|
||||
'filter-safe02': ("{% autoescape off %}{{ a }} -- {{ a|safe }}{% endautoescape %}", {"a": "<b>hello</b>"}, "<b>hello</b> -- <b>hello</b>"),
|
||||
|
||||
'filter-safeseq01': ('{{ a|join:", " }} -- {{ a|safeseq|join:", " }}', {"a": ["&", "<"]}, "&, < -- &, <"),
|
||||
'filter-safeseq02': ('{% autoescape off %}{{ a|join:", " }} -- {{ a|safeseq|join:", " }}{% endautoescape %}', {"a": ["&", "<"]}, "&, < -- &, <"),
|
||||
|
||||
'filter-removetags01': ('{{ a|removetags:"a b" }} {{ b|removetags:"a b" }}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, "x <p>y</p> x <p>y</p>"),
|
||||
'filter-removetags02': ('{% autoescape off %}{{ a|removetags:"a b" }} {{ b|removetags:"a b" }}{% endautoescape %}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, "x <p>y</p> x <p>y</p>"),
|
||||
|
||||
'filter-striptags01': ('{{ a|striptags }} {{ b|striptags }}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, "x y x y"),
|
||||
'filter-striptags02': ('{% autoescape off %}{{ a|striptags }} {{ b|striptags }}{% endautoescape %}', {"a": "<a>x</a> <p><b>y</b></p>", "b": mark_safe("<a>x</a> <p><b>y</b></p>")}, "x y x y"),
|
||||
|
||||
'filter-first01': ('{{ a|first }} {{ b|first }}', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}, "a&b a&b"),
|
||||
'filter-first02': ('{% autoescape off %}{{ a|first }} {{ b|first }}{% endautoescape %}', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}, "a&b a&b"),
|
||||
|
||||
'filter-last01': ('{{ a|last }} {{ b|last }}', {"a": ["x", "a&b"], "b": ["x", mark_safe("a&b")]}, "a&b a&b"),
|
||||
'filter-last02': ('{% autoescape off %}{{ a|last }} {{ b|last }}{% endautoescape %}', {"a": ["x", "a&b"], "b": ["x", mark_safe("a&b")]}, "a&b a&b"),
|
||||
|
||||
'filter-random01': ('{{ a|random }} {{ b|random }}', {"a": ["a&b", "a&b"], "b": [mark_safe("a&b"), mark_safe("a&b")]}, "a&b a&b"),
|
||||
'filter-random02': ('{% autoescape off %}{{ a|random }} {{ b|random }}{% endautoescape %}', {"a": ["a&b", "a&b"], "b": [mark_safe("a&b"), mark_safe("a&b")]}, "a&b a&b"),
|
||||
|
||||
'filter-slice01': ('{{ a|slice:"1:3" }} {{ b|slice:"1:3" }}', {"a": "a&b", "b": mark_safe("a&b")}, "&b &b"),
|
||||
'filter-slice02': ('{% autoescape off %}{{ a|slice:"1:3" }} {{ b|slice:"1:3" }}{% endautoescape %}', {"a": "a&b", "b": mark_safe("a&b")}, "&b &b"),
|
||||
|
||||
'filter-unordered_list01': ('{{ a|unordered_list }}', {"a": ["x>", [["<y", []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"),
|
||||
'filter-unordered_list02': ('{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}', {"a": ["x>", [["<y", []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"),
|
||||
'filter-unordered_list03': ('{{ a|unordered_list }}', {"a": ["x>", [[mark_safe("<y"), []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"),
|
||||
'filter-unordered_list04': ('{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}', {"a": ["x>", [[mark_safe("<y"), []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"),
|
||||
'filter-unordered_list05': ('{% autoescape off %}{{ a|unordered_list }}{% endautoescape %}', {"a": ["x>", [["<y", []]]]}, "\t<li>x>\n\t<ul>\n\t\t<li><y</li>\n\t</ul>\n\t</li>"),
|
||||
|
||||
# Literal string arguments to the default filter are always treated as
|
||||
# safe strings, regardless of the auto-escaping state.
|
||||
#
|
||||
# Note: we have to use {"a": ""} here, otherwise the invalid template
|
||||
# variable string interferes with the test result.
|
||||
'filter-default01': ('{{ a|default:"x<" }}', {"a": ""}, "x<"),
|
||||
'filter-default02': ('{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}', {"a": ""}, "x<"),
|
||||
'filter-default03': ('{{ a|default:"x<" }}', {"a": mark_safe("x>")}, "x>"),
|
||||
'filter-default04': ('{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}', {"a": mark_safe("x>")}, "x>"),
|
||||
|
||||
'filter-default_if_none01': ('{{ a|default:"x<" }}', {"a": None}, "x<"),
|
||||
'filter-default_if_none02': ('{% autoescape off %}{{ a|default:"x<" }}{% endautoescape %}', {"a": None}, "x<"),
|
||||
|
||||
'filter-phone2numeric01': ('{{ a|phone2numeric }} {{ b|phone2numeric }}', {"a": "<1-800-call-me>", "b": mark_safe("<1-800-call-me>")}, "<1-800-2255-63> <1-800-2255-63>"),
|
||||
'filter-phone2numeric02': ('{% autoescape off %}{{ a|phone2numeric }} {{ b|phone2numeric }}{% endautoescape %}', {"a": "<1-800-call-me>", "b": mark_safe("<1-800-call-me>")}, "<1-800-2255-63> <1-800-2255-63>"),
|
||||
'filter-phone2numeric03': ('{{ a|phone2numeric }}', {"a": "How razorback-jumping frogs can level six piqued gymnasts!"}, "469 729672225-5867464 37647 226 53835 749 747833 49662787!"),
|
||||
|
||||
# Ensure iriencode keeps safe strings:
|
||||
'filter-iriencode01': ('{{ url|iriencode }}', {'url': '?test=1&me=2'}, '?test=1&me=2'),
|
||||
'filter-iriencode02': ('{% autoescape off %}{{ url|iriencode }}{% endautoescape %}', {'url': '?test=1&me=2'}, '?test=1&me=2'),
|
||||
'filter-iriencode03': ('{{ url|iriencode }}', {'url': mark_safe('?test=1&me=2')}, '?test=1&me=2'),
|
||||
'filter-iriencode04': ('{% autoescape off %}{{ url|iriencode }}{% endautoescape %}', {'url': mark_safe('?test=1&me=2')}, '?test=1&me=2'),
|
||||
|
||||
# urlencode
|
||||
'filter-urlencode01': ('{{ url|urlencode }}', {'url': '/test&"/me?/'}, '/test%26%22/me%3F/'),
|
||||
'filter-urlencode02': ('/test/{{ urlbit|urlencode:"" }}/', {'urlbit': 'escape/slash'}, '/test/escape%2Fslash/'),
|
||||
|
||||
# Chaining a bunch of safeness-preserving filters should not alter
|
||||
# the safe status either way.
|
||||
'chaining01': ('{{ a|capfirst|center:"7" }}.{{ b|capfirst|center:"7" }}', {"a": "a < b", "b": mark_safe("a < b")}, " A < b . A < b "),
|
||||
'chaining02': ('{% autoescape off %}{{ a|capfirst|center:"7" }}.{{ b|capfirst|center:"7" }}{% endautoescape %}', {"a": "a < b", "b": mark_safe("a < b")}, " A < b . A < b "),
|
||||
|
||||
# Using a filter that forces a string back to unsafe:
|
||||
'chaining03': ('{{ a|cut:"b"|capfirst }}.{{ b|cut:"b"|capfirst }}', {"a": "a < b", "b": mark_safe("a < b")}, "A < .A < "),
|
||||
'chaining04': ('{% autoescape off %}{{ a|cut:"b"|capfirst }}.{{ b|cut:"b"|capfirst }}{% endautoescape %}', {"a": "a < b", "b": mark_safe("a < b")}, "A < .A < "),
|
||||
|
||||
# Using a filter that forces safeness does not lead to double-escaping
|
||||
'chaining05': ('{{ a|escape|capfirst }}', {"a": "a < b"}, "A < b"),
|
||||
'chaining06': ('{% autoescape off %}{{ a|escape|capfirst }}{% endautoescape %}', {"a": "a < b"}, "A < b"),
|
||||
|
||||
# Force to safe, then back (also showing why using force_escape too
|
||||
# early in a chain can lead to unexpected results).
|
||||
'chaining07': ('{{ a|force_escape|cut:";" }}', {"a": "a < b"}, "a &lt b"),
|
||||
'chaining08': ('{% autoescape off %}{{ a|force_escape|cut:";" }}{% endautoescape %}', {"a": "a < b"}, "a < b"),
|
||||
'chaining09': ('{{ a|cut:";"|force_escape }}', {"a": "a < b"}, "a < b"),
|
||||
'chaining10': ('{% autoescape off %}{{ a|cut:";"|force_escape }}{% endautoescape %}', {"a": "a < b"}, "a < b"),
|
||||
'chaining11': ('{{ a|cut:"b"|safe }}', {"a": "a < b"}, "a < "),
|
||||
'chaining12': ('{% autoescape off %}{{ a|cut:"b"|safe }}{% endautoescape %}', {"a": "a < b"}, "a < "),
|
||||
'chaining13': ('{{ a|safe|force_escape }}', {"a": "a < b"}, "a < b"),
|
||||
'chaining14': ('{% autoescape off %}{{ a|safe|force_escape }}{% endautoescape %}', {"a": "a < b"}, "a < b"),
|
||||
|
||||
# Filters decorated with stringfilter still respect is_safe.
|
||||
'autoescape-stringfilter01': (r'{{ unsafe|capfirst }}', {'unsafe': UnsafeClass()}, 'You & me'),
|
||||
'autoescape-stringfilter02': (r'{% autoescape off %}{{ unsafe|capfirst }}{% endautoescape %}', {'unsafe': UnsafeClass()}, 'You & me'),
|
||||
'autoescape-stringfilter03': (r'{{ safe|capfirst }}', {'safe': SafeClass()}, 'You > me'),
|
||||
'autoescape-stringfilter04': (r'{% autoescape off %}{{ safe|capfirst }}{% endautoescape %}', {'safe': SafeClass()}, 'You > me'),
|
||||
|
||||
'escapejs01': (r'{{ a|escapejs }}', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'}, 'testing\\u000D\\u000Ajavascript \\u0027string\\u0022 \\u003Cb\\u003Eescaping\\u003C/b\\u003E'),
|
||||
'escapejs02': (r'{% autoescape off %}{{ a|escapejs }}{% endautoescape %}', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'}, 'testing\\u000D\\u000Ajavascript \\u0027string\\u0022 \\u003Cb\\u003Eescaping\\u003C/b\\u003E'),
|
||||
|
||||
|
||||
# length filter.
|
||||
'length01': ('{{ list|length }}', {'list': ['4', None, True, {}]}, '4'),
|
||||
'length02': ('{{ list|length }}', {'list': []}, '0'),
|
||||
'length03': ('{{ string|length }}', {'string': ''}, '0'),
|
||||
'length04': ('{{ string|length }}', {'string': 'django'}, '6'),
|
||||
'length05': ('{% if string|length == 6 %}Pass{% endif %}', {'string': mark_safe('django')}, 'Pass'),
|
||||
# Invalid uses that should fail silently.
|
||||
'length06': ('{{ int|length }}', {'int': 7}, '0'),
|
||||
'length07': ('{{ None|length }}', {'None': None}, '0'),
|
||||
|
||||
# length_is filter.
|
||||
'length_is01': ('{% if some_list|length_is:"4" %}Four{% endif %}', {'some_list': ['4', None, True, {}]}, 'Four'),
|
||||
'length_is02': ('{% if some_list|length_is:"4" %}Four{% else %}Not Four{% endif %}', {'some_list': ['4', None, True, {}, 17]}, 'Not Four'),
|
||||
'length_is03': ('{% if mystring|length_is:"4" %}Four{% endif %}', {'mystring': 'word'}, 'Four'),
|
||||
'length_is04': ('{% if mystring|length_is:"4" %}Four{% else %}Not Four{% endif %}', {'mystring': 'Python'}, 'Not Four'),
|
||||
'length_is05': ('{% if mystring|length_is:"4" %}Four{% else %}Not Four{% endif %}', {'mystring': ''}, 'Not Four'),
|
||||
'length_is06': ('{% with var|length as my_length %}{{ my_length }}{% endwith %}', {'var': 'django'}, '6'),
|
||||
# Boolean return value from length_is should not be coerced to a string
|
||||
'length_is07': (r'{% if "X"|length_is:0 %}Length is 0{% else %}Length not 0{% endif %}', {}, 'Length not 0'),
|
||||
'length_is08': (r'{% if "X"|length_is:1 %}Length is 1{% else %}Length not 1{% endif %}', {}, 'Length is 1'),
|
||||
# Invalid uses that should fail silently.
|
||||
'length_is09': ('{{ var|length_is:"fish" }}', {'var': 'django'}, ''),
|
||||
'length_is10': ('{{ int|length_is:"1" }}', {'int': 7}, ''),
|
||||
'length_is11': ('{{ none|length_is:"1" }}', {'none': None}, ''),
|
||||
|
||||
'join01': (r'{{ a|join:", " }}', {'a': ['alpha', 'beta & me']}, 'alpha, beta & me'),
|
||||
'join02': (r'{% autoescape off %}{{ a|join:", " }}{% endautoescape %}', {'a': ['alpha', 'beta & me']}, 'alpha, beta & me'),
|
||||
'join03': (r'{{ a|join:" & " }}', {'a': ['alpha', 'beta & me']}, 'alpha & beta & me'),
|
||||
'join04': (r'{% autoescape off %}{{ a|join:" & " }}{% endautoescape %}', {'a': ['alpha', 'beta & me']}, 'alpha & beta & me'),
|
||||
|
||||
# Test that joining with unsafe joiners don't result in unsafe strings (#11377)
|
||||
'join05': (r'{{ a|join:var }}', {'a': ['alpha', 'beta & me'], 'var': ' & '}, 'alpha & beta & me'),
|
||||
'join06': (r'{{ a|join:var }}', {'a': ['alpha', 'beta & me'], 'var': mark_safe(' & ')}, 'alpha & beta & me'),
|
||||
'join07': (r'{{ a|join:var|lower }}', {'a': ['Alpha', 'Beta & me'], 'var': ' & '}, 'alpha & beta & me'),
|
||||
'join08': (r'{{ a|join:var|lower }}', {'a': ['Alpha', 'Beta & me'], 'var': mark_safe(' & ')}, 'alpha & beta & me'),
|
||||
|
||||
'date01': (r'{{ d|date:"m" }}', {'d': datetime(2008, 1, 1)}, '01'),
|
||||
'date02': (r'{{ d|date }}', {'d': datetime(2008, 1, 1)}, 'Jan. 1, 2008'),
|
||||
# Ticket 9520: Make sure |date doesn't blow up on non-dates
|
||||
'date03': (r'{{ d|date:"m" }}', {'d': 'fail_string'}, ''),
|
||||
# ISO date formats
|
||||
'date04': (r'{{ d|date:"o" }}', {'d': datetime(2008, 12, 29)}, '2009'),
|
||||
'date05': (r'{{ d|date:"o" }}', {'d': datetime(2010, 1, 3)}, '2009'),
|
||||
# Timezone name
|
||||
'date06': (r'{{ d|date:"e" }}', {'d': datetime(2009, 3, 12, tzinfo=timezone.get_fixed_timezone(30))}, '+0030'),
|
||||
'date07': (r'{{ d|date:"e" }}', {'d': datetime(2009, 3, 12)}, ''),
|
||||
# Ticket 19370: Make sure |date doesn't blow up on a midnight time object
|
||||
'date08': (r'{{ t|date:"H:i" }}', {'t': time(0, 1)}, '00:01'),
|
||||
'date09': (r'{{ t|date:"H:i" }}', {'t': time(0, 0)}, '00:00'),
|
||||
# Ticket 20693: Add timezone support to built-in time template filter
|
||||
'time01': (r'{{ dt|time:"e:O:T:Z" }}', {'dt': now_tz_i}, '+0315:+0315:+0315:11700'),
|
||||
'time02': (r'{{ dt|time:"e:T" }}', {'dt': now}, ':' + now_tz.tzinfo.tzname(now_tz)),
|
||||
'time03': (r'{{ t|time:"P:e:O:T:Z" }}', {'t': time(4, 0, tzinfo=timezone.get_fixed_timezone(30))}, '4 a.m.::::'),
|
||||
'time04': (r'{{ t|time:"P:e:O:T:Z" }}', {'t': time(4, 0)}, '4 a.m.::::'),
|
||||
'time05': (r'{{ d|time:"P:e:O:T:Z" }}', {'d': today}, ''),
|
||||
'time06': (r'{{ obj|time:"P:e:O:T:Z" }}', {'obj': 'non-datetime-value'}, ''),
|
||||
|
||||
# Tests for #11687 and #16676
|
||||
'add01': (r'{{ i|add:"5" }}', {'i': 2000}, '2005'),
|
||||
'add02': (r'{{ i|add:"napis" }}', {'i': 2000}, ''),
|
||||
'add03': (r'{{ i|add:16 }}', {'i': 'not_an_int'}, ''),
|
||||
'add04': (r'{{ i|add:"16" }}', {'i': 'not_an_int'}, 'not_an_int16'),
|
||||
'add05': (r'{{ l1|add:l2 }}', {'l1': [1, 2], 'l2': [3, 4]}, '[1, 2, 3, 4]'),
|
||||
'add06': (r'{{ t1|add:t2 }}', {'t1': (3, 4), 't2': (1, 2)}, '(3, 4, 1, 2)'),
|
||||
'add07': (r'{{ d|add:t }}', {'d': date(2000, 1, 1), 't': timedelta(10)}, 'Jan. 11, 2000'),
|
||||
}
|
|
@ -2,7 +2,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from .utils import render, setup, SafeClass, UnsafeClass
|
||||
from ..utils import render, setup, SafeClass, UnsafeClass
|
||||
|
||||
|
||||
class AutoescapeTagTests(SimpleTestCase):
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.template.base import Context, TemplateSyntaxError
|
|||
from django.template.loader import get_template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup, SilentGetItemClass, SilentAttrClass, SomeClass
|
||||
from ..utils import render, setup, SilentGetItemClass, SilentAttrClass, SomeClass
|
||||
|
||||
|
||||
basic_templates = {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class BuiltinsTests(SimpleTestCase):
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.template.loader import get_template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class CacheTagTests(SimpleTestCase):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class CommentSyntaxTests(SimpleTestCase):
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.template.loader import get_template
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class CycleTagTests(SimpleTestCase):
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.template.loader import get_template
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from .test_extends import inheritance_templates
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class ExceptionsTests(SimpleTestCase):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.template.base import Template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
inheritance_templates = {
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.template.loader import get_template
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
|
||||
from .utils import render, setup, SomeClass, SomeOtherException, UTF8Class
|
||||
from ..utils import render, setup, SomeClass, SomeOtherException, UTF8Class
|
||||
|
||||
|
||||
class FilterSyntaxTests(SimpleTestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.template.loader import get_template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class FilterTagTests(SimpleTestCase):
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.template.loader import get_template
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class FirstOfTagTests(SimpleTestCase):
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class ForTagTests(SimpleTestCase):
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.conf import settings
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class I18nTagTests(SimpleTestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.template.loader import get_template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup, TestObj
|
||||
from ..utils import render, setup, TestObj
|
||||
|
||||
|
||||
class IfTagTests(SimpleTestCase):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class IfChangedTagTests(SimpleTestCase):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class IfEqualTagTests(SimpleTestCase):
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.template.loader import get_template
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from .test_basic import basic_templates
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
include_fail_templates = {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf import settings
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class InvalidStringTests(SimpleTestCase):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf import settings
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class ListIndexTests(SimpleTestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.template.loader import get_template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class LoadTagTests(SimpleTestCase):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class LoremTagTests(SimpleTestCase):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
multiline_string = """
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.template.loader import get_template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class NamedEndblockTests(SimpleTestCase):
|
||||
|
|
|
@ -3,7 +3,7 @@ from datetime import datetime
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils.formats import date_format
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class NowTagTests(SimpleTestCase):
|
||||
|
|
|
@ -3,7 +3,7 @@ from unittest import skipIf
|
|||
from django.conf import settings
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
try:
|
||||
import numpy
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.template.loader import get_template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class RegroupTagTests(SimpleTestCase):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.conf import settings
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import setup
|
||||
from ..utils import setup
|
||||
|
||||
|
||||
class SetupTests(SimpleTestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.template.loader import get_template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class SimpleTagTests(SimpleTestCase):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class SpacelessTagTests(SimpleTestCase):
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.test import override_settings, SimpleTestCase
|
|||
from django.utils._os import upath
|
||||
from django.utils.deprecation import RemovedInDjango19Warning
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
cwd = os.path.dirname(os.path.abspath(upath(__file__)))
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.conf import settings
|
|||
from django.test import override_settings, SimpleTestCase
|
||||
from django.utils.six.moves.urllib.parse import urljoin
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
@override_settings(MEDIA_URL="/media/", STATIC_URL="/static/")
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.template.loader import get_template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class TemplateTagTests(SimpleTestCase):
|
||||
|
|
|
@ -7,7 +7,7 @@ from django.template.loader import get_template
|
|||
from django.test import override_settings, SimpleTestCase
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='template_tests.urls')
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.template.base import TemplateSyntaxError
|
|||
from django.template.loader import get_template
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class VerbatimTagTests(SimpleTestCase):
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.template.loader import get_template
|
|||
from django.test import SimpleTestCase
|
||||
from django.utils import six
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class WidthRatioTagTests(SimpleTestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.conf import settings
|
|||
from django.template.base import TemplateSyntaxError
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
from .utils import render, setup
|
||||
from ..utils import render, setup
|
||||
|
||||
|
||||
class WithTagTests(SimpleTestCase):
|
||||
|
|
|
@ -3,9 +3,7 @@ from __future__ import unicode_literals
|
|||
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from django import template
|
||||
from django.contrib.auth.models import Group
|
||||
|
@ -15,17 +13,7 @@ from django.template.engine import Engine
|
|||
from django.template.loaders import app_directories, filesystem
|
||||
from django.test import RequestFactory, SimpleTestCase
|
||||
from django.test.utils import override_settings, extend_sys_path
|
||||
from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
|
||||
from django.utils._os import upath
|
||||
from django.utils import six
|
||||
from django.utils import translation
|
||||
|
||||
from . import filters
|
||||
from .syntax_tests.utils import register_test_tags, ShouldNotExecuteException
|
||||
|
||||
|
||||
class ContextStackException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class TemplateLoaderTests(SimpleTestCase):
|
||||
|
@ -393,114 +381,6 @@ class TemplateRegressionTests(SimpleTestCase):
|
|||
self.assertIn("清風", t1.render(c1))
|
||||
|
||||
|
||||
# Set ALLOWED_INCLUDE_ROOTS so that ssi works.
|
||||
@override_settings(TEMPLATE_DEBUG=False, ROOT_URLCONF='template_tests.urls')
|
||||
class TemplateTests(SimpleTestCase):
|
||||
|
||||
@register_test_tags
|
||||
def test_templates(self):
|
||||
template_tests = filters.get_filter_tests()
|
||||
|
||||
templates = dict((name, t[0]) for name, t in six.iteritems(template_tests))
|
||||
with override_settings(TEMPLATE_LOADERS=[
|
||||
('django.template.loaders.cached.Loader', [
|
||||
('django.template.loaders.locmem.Loader', templates),
|
||||
]),
|
||||
]):
|
||||
failures = []
|
||||
tests = sorted(template_tests.items())
|
||||
|
||||
# Warm the URL reversing cache. This ensures we don't pay the cost
|
||||
# warming the cache during one of the tests.
|
||||
urlresolvers.reverse('named.client', args=(0,))
|
||||
|
||||
for name, vals in tests:
|
||||
|
||||
# Set TEMPLATE_STRING_IF_INVALID to a known string.
|
||||
expected_invalid_str = 'INVALID'
|
||||
|
||||
if isinstance(vals[2], tuple):
|
||||
normal_string_result = vals[2][0]
|
||||
invalid_string_result = vals[2][1]
|
||||
|
||||
if isinstance(invalid_string_result, tuple):
|
||||
expected_invalid_str = 'INVALID %s'
|
||||
invalid_string_result = invalid_string_result[0] % invalid_string_result[1]
|
||||
|
||||
try:
|
||||
template_debug_result = vals[2][2]
|
||||
except IndexError:
|
||||
template_debug_result = normal_string_result
|
||||
|
||||
else:
|
||||
normal_string_result = vals[2]
|
||||
invalid_string_result = vals[2]
|
||||
template_debug_result = vals[2]
|
||||
|
||||
with translation.override(vals[1].get('LANGUAGE_CODE', 'en-us')):
|
||||
for invalid_str, template_debug, result in [
|
||||
('', False, normal_string_result),
|
||||
(expected_invalid_str, False, invalid_string_result),
|
||||
('', True, template_debug_result)
|
||||
]:
|
||||
with override_settings(TEMPLATE_STRING_IF_INVALID=invalid_str,
|
||||
TEMPLATE_DEBUG=template_debug):
|
||||
for is_cached in (False, True):
|
||||
try:
|
||||
try:
|
||||
with warnings.catch_warnings():
|
||||
# Ignore pending deprecations of loading 'ssi' and 'url' tags from future.
|
||||
warnings.filterwarnings("ignore", category=RemovedInDjango19Warning, module='django.templatetags.future')
|
||||
# Ignore deprecations of loading 'cycle' and 'firstof' tags from future.
|
||||
warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.templatetags.future")
|
||||
test_template = loader.get_template(name)
|
||||
except ShouldNotExecuteException:
|
||||
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Template loading invoked method that shouldn't have been invoked." % (is_cached, invalid_str, template_debug, name))
|
||||
|
||||
try:
|
||||
with warnings.catch_warnings():
|
||||
# Ignore deprecations of using the wrong number of variables with the 'for' tag.
|
||||
# and warnings for {% url %} reversing by dotted path
|
||||
warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.template.defaulttags")
|
||||
# Ignore deprecations of old style unordered_list
|
||||
# and removetags.
|
||||
warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.template.defaultfilters")
|
||||
# Ignore numpy deprecation warnings (#23890)
|
||||
warnings.filterwarnings(
|
||||
"ignore",
|
||||
"Using a non-integer number instead of an "
|
||||
"integer will result in an error in the future",
|
||||
DeprecationWarning
|
||||
)
|
||||
output = self.render(test_template, vals)
|
||||
except ShouldNotExecuteException:
|
||||
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Template rendering invoked method that shouldn't have been invoked." % (is_cached, invalid_str, template_debug, name))
|
||||
except ContextStackException:
|
||||
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Context stack was left imbalanced" % (is_cached, invalid_str, template_debug, name))
|
||||
continue
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_tb = sys.exc_info()
|
||||
if exc_type != result:
|
||||
tb = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_tb))
|
||||
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Got %s, exception: %s\n%s" % (is_cached, invalid_str, template_debug, name, exc_type, exc_value, tb))
|
||||
continue
|
||||
if output != result:
|
||||
failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Expected %r, got %r" % (is_cached, invalid_str, template_debug, name, result, output))
|
||||
|
||||
Engine.get_default().template_loaders[0].reset()
|
||||
|
||||
self.assertEqual(failures, [], "Tests failed:\n%s\n%s" %
|
||||
('-' * 70, ("\n%s\n" % ('-' * 70)).join(failures)))
|
||||
|
||||
def render(self, test_template, vals):
|
||||
context = template.Context(vals[1])
|
||||
before_stack_size = len(context.dicts)
|
||||
output = test_template.render(context)
|
||||
if len(context.dicts) != before_stack_size:
|
||||
raise ContextStackException
|
||||
return output
|
||||
|
||||
|
||||
class TemplateTagLoading(SimpleTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
|
Loading…
Reference in New Issue