summaryrefslogtreecommitdiff
path: root/tests/regressiontests/templates
diff options
context:
space:
mode:
authorLuke Plant <L.Plant.98@cantab.net>2009-12-09 22:40:36 +0000
committerLuke Plant <L.Plant.98@cantab.net>2009-12-09 22:40:36 +0000
commit2c2f5aee4d44836779fcd74c7782368914f9cfd1 (patch)
tree686d60b434ffe9ebcc019ef61208e5cd45921ab9 /tests/regressiontests/templates
parent25020ddb05543fff1c37d77b49bd937fd2bbb170 (diff)
Implemented 'smart if' template tag, allowing filters and various operators to be used in the 'if' tag
Thanks to Chris Beaven for the initial patch, Fredrik Lundh for the basis of the parser methodology and Russell Keith-Magee for code reviews. There are some BACKWARDS INCOMPATIBILITIES in rare cases - in particular, if you were using the keywords 'and', 'or' or 'not' as variable names within the 'if' expression, which was previously allowed in some cases. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11806 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests/regressiontests/templates')
-rw-r--r--tests/regressiontests/templates/smartif.py46
-rw-r--r--tests/regressiontests/templates/tests.py44
2 files changed, 83 insertions, 7 deletions
diff --git a/tests/regressiontests/templates/smartif.py b/tests/regressiontests/templates/smartif.py
new file mode 100644
index 0000000000..0114753830
--- /dev/null
+++ b/tests/regressiontests/templates/smartif.py
@@ -0,0 +1,46 @@
+import unittest
+from django.template.smartif import IfParser, Literal
+
+class SmartIfTests(unittest.TestCase):
+
+ def assertCalcEqual(self, expected, tokens):
+ self.assertEqual(expected, IfParser(tokens).parse().eval({}))
+
+ # We only test things here that are difficult to test elsewhere
+ # Many other tests are found in the main tests for builtin template tags
+ # Test parsing via the printed parse tree
+ def test_not(self):
+ var = IfParser(["not", False]).parse()
+ self.assertEqual("(not (literal False))", repr(var))
+ self.assert_(var.eval({}))
+
+ self.assertFalse(IfParser(["not", True]).parse().eval({}))
+
+ def test_or(self):
+ var = IfParser([True, "or", False]).parse()
+ self.assertEqual("(or (literal True) (literal False))", repr(var))
+ self.assert_(var.eval({}))
+
+ def test_in(self):
+ list_ = [1,2,3]
+ self.assertCalcEqual(True, [1, 'in', list_])
+ self.assertCalcEqual(False, [1, 'in', None])
+ self.assertCalcEqual(False, [None, 'in', list_])
+
+ def test_precedence(self):
+ # (False and False) or True == True <- we want this one, like Python
+ # False and (False or True) == False
+ self.assertCalcEqual(True, [False, 'and', False, 'or', True])
+
+ # True or (False and False) == True <- we want this one, like Python
+ # (True or False) and False == False
+ self.assertCalcEqual(True, [True, 'or', False, 'and', False])
+
+ # (1 or 1) == 2 -> False
+ # 1 or (1 == 2) -> True <- we want this one
+ self.assertCalcEqual(True, [1, 'or', 1, '==', 2])
+
+ self.assertCalcEqual(True, [True, '==', True, 'or', True, '==', False])
+
+ self.assertEqual("(or (and (== (literal 1) (literal 2)) (literal 3)) (literal 4))",
+ repr(IfParser([1, '==', 2, 'and', 3, 'or', 4]).parse()))
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index 9c01b492e3..c29c53ae44 100644
--- a/tests/regressiontests/templates/tests.py
+++ b/tests/regressiontests/templates/tests.py
@@ -24,6 +24,7 @@ from context import context_tests
from custom import custom_filters
from parser import filter_parsing, variable_parsing
from unicode import unicode_tests
+from smartif import *
try:
from loaders import *
@@ -534,6 +535,27 @@ class Templates(unittest.TestCase):
'if-tag02': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": False}, "no"),
'if-tag03': ("{% if foo %}yes{% else %}no{% endif %}", {}, "no"),
+ # Filters
+ 'if-tag-filter01': ("{% if foo|length == 5 %}yes{% else %}no{% endif %}", {'foo': 'abcde'}, "yes"),
+ 'if-tag-filter02': ("{% if foo|upper == 'ABC' %}yes{% else %}no{% endif %}", {}, "no"),
+
+ # Equality
+ 'if-tag-eq01': ("{% if foo == bar %}yes{% else %}no{% endif %}", {}, "yes"),
+ 'if-tag-eq02': ("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1}, "no"),
+ 'if-tag-eq03': ("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1, 'bar': 1}, "yes"),
+ 'if-tag-eq04': ("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1, 'bar': 2}, "no"),
+ 'if-tag-eq05': ("{% if foo == '' %}yes{% else %}no{% endif %}", {}, "no"),
+
+ # Comparison
+ 'if-tag-gt-01': ("{% if 2 > 1 %}yes{% else %}no{% endif %}", {}, "yes"),
+ 'if-tag-gt-02': ("{% if 1 > 1 %}yes{% else %}no{% endif %}", {}, "no"),
+ 'if-tag-gte-01': ("{% if 1 >= 1 %}yes{% else %}no{% endif %}", {}, "yes"),
+ 'if-tag-gte-02': ("{% if 1 >= 2 %}yes{% else %}no{% endif %}", {}, "no"),
+ 'if-tag-lt-01': ("{% if 1 < 2 %}yes{% else %}no{% endif %}", {}, "yes"),
+ 'if-tag-lt-02': ("{% if 1 < 1 %}yes{% else %}no{% endif %}", {}, "no"),
+ 'if-tag-lte-01': ("{% if 1 <= 1 %}yes{% else %}no{% endif %}", {}, "yes"),
+ 'if-tag-lte-02': ("{% if 2 <= 1 %}yes{% else %}no{% endif %}", {}, "no"),
+
# AND
'if-tag-and01': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
'if-tag-and02': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
@@ -554,14 +576,13 @@ class Templates(unittest.TestCase):
'if-tag-or07': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True}, 'yes'),
'if-tag-or08': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': True}, 'yes'),
- # TODO: multiple ORs
+ # multiple ORs
+ 'if-tag-or09': ("{% if foo or bar or baz %}yes{% else %}no{% endif %}", {'baz': True}, 'yes'),
# NOT
'if-tag-not01': ("{% if not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'yes'),
- 'if-tag-not02': ("{% if not %}yes{% else %}no{% endif %}", {'foo': True}, 'no'),
- 'if-tag-not03': ("{% if not %}yes{% else %}no{% endif %}", {'not': True}, 'yes'),
- 'if-tag-not04': ("{% if not not %}no{% else %}yes{% endif %}", {'not': True}, 'yes'),
- 'if-tag-not05': ("{% if not not %}no{% else %}yes{% endif %}", {}, 'no'),
+ 'if-tag-not02': ("{% if not not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'no'),
+ # not03 to not05 removed, now TemplateSyntaxErrors
'if-tag-not06': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {}, 'no'),
'if-tag-not07': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
@@ -599,12 +620,21 @@ class Templates(unittest.TestCase):
'if-tag-not34': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
'if-tag-not35': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
- # AND and OR raises a TemplateSyntaxError
- 'if-tag-error01': ("{% if foo or bar and baz %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, template.TemplateSyntaxError),
+ # Various syntax errors
+ 'if-tag-error01': ("{% if %}yes{% endif %}", {}, template.TemplateSyntaxError),
'if-tag-error02': ("{% if foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
'if-tag-error03': ("{% if foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
'if-tag-error04': ("{% if not foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
'if-tag-error05': ("{% if not foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
+ 'if-tag-error06': ("{% if abc def %}yes{% endif %}", {}, template.TemplateSyntaxError),
+ 'if-tag-error07': ("{% if not %}yes{% endif %}", {}, template.TemplateSyntaxError),
+ 'if-tag-error08': ("{% if and %}yes{% endif %}", {}, template.TemplateSyntaxError),
+ 'if-tag-error09': ("{% if or %}yes{% endif %}", {}, template.TemplateSyntaxError),
+ 'if-tag-error10': ("{% if == %}yes{% endif %}", {}, template.TemplateSyntaxError),
+ 'if-tag-error11': ("{% if 1 == %}yes{% endif %}", {}, template.TemplateSyntaxError),
+ 'if-tag-error12': ("{% if a not b %}yes{% endif %}", {}, template.TemplateSyntaxError),
+
+ # Additional, more precise parsing tests are in SmartIfTests
### IFCHANGED TAG #########################################################
'ifchanged01': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', {'num': (1,2,3)}, '123'),