From f91d7366e066dc5e1edd90c6bde438fae9fe67fb Mon Sep 17 00:00:00 2001 From: Preston Timmons <prestontimmons@gmail.com> Date: Mon, 15 Dec 2014 08:33:33 -0600 Subject: [PATCH] Fixed #16028 -- Moved defaultfilters tests into template_tests. --- tests/defaultfilters/__init__.py | 0 tests/defaultfilters/tests.py | 754 ------------------ tests/template_tests/filter_tests/test_add.py | 7 + .../filter_tests/test_addslashes.py | 16 + .../filter_tests/test_capfirst.py | 7 + .../filter_tests/test_center.py | 10 + tests/template_tests/filter_tests/test_cut.py | 16 + .../template_tests/filter_tests/test_date.py | 11 + .../filter_tests/test_default.py | 13 + .../filter_tests/test_default_if_none.py | 14 + .../filter_tests/test_dictsort.py | 44 + .../filter_tests/test_dictsortreversed.py | 30 + .../filter_tests/test_divisibleby.py | 11 + .../filter_tests/test_escape.py | 7 + .../filter_tests/test_escapejs.py | 33 + .../filter_tests/test_filesizeformat.py | 41 + .../template_tests/filter_tests/test_first.py | 13 + .../filter_tests/test_floatformat.py | 91 +++ .../filter_tests/test_force_escape.py | 19 + .../filter_tests/test_get_digit.py | 15 + .../filter_tests/test_iriencode.py | 13 + .../template_tests/filter_tests/test_join.py | 7 + .../filter_tests/test_length.py | 13 + .../filter_tests/test_length_is.py | 12 + .../filter_tests/test_linebreaks.py | 19 + .../filter_tests/test_linebreaksbr.py | 16 + .../filter_tests/test_linenumbers.py | 16 + .../template_tests/filter_tests/test_ljust.py | 14 + .../template_tests/filter_tests/test_lower.py | 17 + .../filter_tests/test_make_list.py | 10 + .../filter_tests/test_phone2numeric.py | 7 + .../filter_tests/test_pluralize.py | 35 + .../filter_tests/test_removetags.py | 20 + .../template_tests/filter_tests/test_rjust.py | 13 + .../template_tests/filter_tests/test_slice.py | 22 + .../filter_tests/test_slugify.py | 22 + .../filter_tests/test_stringformat.py | 10 + .../filter_tests/test_striptags.py | 13 + .../template_tests/filter_tests/test_time.py | 9 + .../filter_tests/test_timesince.py | 11 + .../filter_tests/test_timeuntil.py | 11 + .../template_tests/filter_tests/test_title.py | 16 + .../filter_tests/test_truncatechars_html.py | 35 + .../filter_tests/test_truncatewords.py | 28 + .../filter_tests/test_truncatewords_html.py | 44 + .../filter_tests/test_unordered_list.py | 82 ++ .../template_tests/filter_tests/test_upper.py | 17 + .../filter_tests/test_urlencode.py | 13 + .../filter_tests/test_urlize.py | 240 ++++++ .../filter_tests/test_urlizetrunc.py | 42 + .../filter_tests/test_wordcount.py | 16 + .../filter_tests/test_wordwrap.py | 25 + .../template_tests/filter_tests/test_yesno.py | 26 + 53 files changed, 1292 insertions(+), 754 deletions(-) delete mode 100644 tests/defaultfilters/__init__.py delete mode 100644 tests/defaultfilters/tests.py create mode 100644 tests/template_tests/filter_tests/test_default_if_none.py create mode 100644 tests/template_tests/filter_tests/test_dictsort.py create mode 100644 tests/template_tests/filter_tests/test_dictsortreversed.py create mode 100644 tests/template_tests/filter_tests/test_divisibleby.py create mode 100644 tests/template_tests/filter_tests/test_filesizeformat.py create mode 100644 tests/template_tests/filter_tests/test_get_digit.py create mode 100644 tests/template_tests/filter_tests/test_pluralize.py create mode 100644 tests/template_tests/filter_tests/test_truncatechars_html.py create mode 100644 tests/template_tests/filter_tests/test_truncatewords_html.py create mode 100644 tests/template_tests/filter_tests/test_yesno.py diff --git a/tests/defaultfilters/__init__.py b/tests/defaultfilters/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/defaultfilters/tests.py b/tests/defaultfilters/tests.py deleted file mode 100644 index bf80ccb313..0000000000 --- a/tests/defaultfilters/tests.py +++ /dev/null @@ -1,754 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import datetime -import decimal -import unittest -import warnings - -from django.template.defaultfilters import ( - add, addslashes, capfirst, center, cut, date, default, default_if_none, - dictsort, dictsortreversed, divisibleby, escape, escapejs_filter, - filesizeformat, first, floatformat, force_escape, - get_digit, iriencode, join, length, length_is, linebreaksbr, - linebreaks_filter, linenumbers, ljust, lower, make_list, - phone2numeric_filter, pluralize, removetags, rjust, slice_filter, slugify, - stringformat, striptags, time, timesince_filter, timeuntil_filter, title, - truncatechars_html, truncatewords, truncatewords_html, unordered_list, - upper, urlencode, urlize, urlizetrunc, wordcount, wordwrap, yesno, -) -from django.test import TestCase -from django.utils import six -from django.utils import translation -from django.utils.encoding import python_2_unicode_compatible -from django.utils.safestring import mark_safe, SafeData - - -class DefaultFiltersTests(TestCase): - - def test_floatformat(self): - self.assertEqual(floatformat(7.7), '7.7') - self.assertEqual(floatformat(7.0), '7') - self.assertEqual(floatformat(0.7), '0.7') - self.assertEqual(floatformat(0.07), '0.1') - self.assertEqual(floatformat(0.007), '0.0') - self.assertEqual(floatformat(0.0), '0') - self.assertEqual(floatformat(7.7, 3), '7.700') - self.assertEqual(floatformat(6.000000, 3), '6.000') - self.assertEqual(floatformat(6.200000, 3), '6.200') - self.assertEqual(floatformat(6.200000, -3), '6.200') - self.assertEqual(floatformat(13.1031, -3), '13.103') - self.assertEqual(floatformat(11.1197, -2), '11.12') - self.assertEqual(floatformat(11.0000, -2), '11') - self.assertEqual(floatformat(11.000001, -2), '11.00') - self.assertEqual(floatformat(8.2798, 3), '8.280') - self.assertEqual(floatformat(5555.555, 2), '5555.56') - self.assertEqual(floatformat(001.3000, 2), '1.30') - self.assertEqual(floatformat(0.12345, 2), '0.12') - self.assertEqual(floatformat(decimal.Decimal('555.555'), 2), '555.56') - self.assertEqual(floatformat(decimal.Decimal('09.000')), '9') - self.assertEqual(floatformat('foo'), '') - self.assertEqual(floatformat(13.1031, 'bar'), '13.1031') - self.assertEqual(floatformat(18.125, 2), '18.13') - self.assertEqual(floatformat('foo', 'bar'), '') - self.assertEqual(floatformat('¿Cómo esta usted?'), '') - self.assertEqual(floatformat(None), '') - - # Check that we're not converting to scientific notation. - self.assertEqual(floatformat(0, 6), '0.000000') - self.assertEqual(floatformat(0, 7), '0.0000000') - self.assertEqual(floatformat(0, 10), '0.0000000000') - self.assertEqual(floatformat(0.000000000000000000015, 20), - '0.00000000000000000002') - - pos_inf = float(1e30000) - self.assertEqual(floatformat(pos_inf), six.text_type(pos_inf)) - - neg_inf = float(-1e30000) - self.assertEqual(floatformat(neg_inf), six.text_type(neg_inf)) - - nan = pos_inf / pos_inf - self.assertEqual(floatformat(nan), six.text_type(nan)) - - class FloatWrapper(object): - def __init__(self, value): - self.value = value - - def __float__(self): - return self.value - - self.assertEqual(floatformat(FloatWrapper(11.000001), -2), '11.00') - - # Regression for #15789 - decimal_ctx = decimal.getcontext() - old_prec, decimal_ctx.prec = decimal_ctx.prec, 2 - try: - self.assertEqual(floatformat(1.2345, 2), '1.23') - self.assertEqual(floatformat(15.2042, -3), '15.204') - self.assertEqual(floatformat(1.2345, '2'), '1.23') - self.assertEqual(floatformat(15.2042, '-3'), '15.204') - self.assertEqual(floatformat(decimal.Decimal('1.2345'), 2), '1.23') - self.assertEqual(floatformat(decimal.Decimal('15.2042'), -3), '15.204') - finally: - decimal_ctx.prec = old_prec - - def test_floatformat_py2_fail(self): - self.assertEqual(floatformat(1.00000000000000015, 16), '1.0000000000000002') - - # The test above fails because of Python 2's float handling. Floats with - # many zeroes after the decimal point should be passed in as another type - # such as unicode or Decimal. - if six.PY2: - test_floatformat_py2_fail = unittest.expectedFailure(test_floatformat_py2_fail) - - def test_addslashes(self): - self.assertEqual(addslashes('"double quotes" and \'single quotes\''), - '\\"double quotes\\" and \\\'single quotes\\\'') - - self.assertEqual(addslashes(r'\ : backslashes, too'), - '\\\\ : backslashes, too') - - def test_capfirst(self): - self.assertEqual(capfirst('hello world'), 'Hello world') - - def test_escapejs(self): - self.assertEqual(escapejs_filter('"double quotes" and \'single quotes\''), - '\\u0022double quotes\\u0022 and \\u0027single quotes\\u0027') - self.assertEqual(escapejs_filter(r'\ : backslashes, too'), - '\\u005C : backslashes, too') - self.assertEqual(escapejs_filter('and lots of whitespace: \r\n\t\v\f\b'), - 'and lots of whitespace: \\u000D\\u000A\\u0009\\u000B\\u000C\\u0008') - self.assertEqual(escapejs_filter(r'<script>and this</script>'), - '\\u003Cscript\\u003Eand this\\u003C/script\\u003E') - self.assertEqual( - escapejs_filter('paragraph separator:\u2029and line separator:\u2028'), - 'paragraph separator:\\u2029and line separator:\\u2028') - - def test_linenumbers(self): - self.assertEqual(linenumbers('line 1\nline 2'), - '1. line 1\n2. line 2') - self.assertEqual(linenumbers('\n'.join(['x'] * 10)), - '01. x\n02. x\n03. x\n04. x\n05. x\n06. x\n07. ' - 'x\n08. x\n09. x\n10. x') - - def test_lower(self): - self.assertEqual(lower('TEST'), 'test') - - # uppercase E umlaut - self.assertEqual(lower('\xcb'), '\xeb') - - def test_make_list(self): - self.assertEqual(make_list('abc'), ['a', 'b', 'c']) - self.assertEqual(make_list(1234), ['1', '2', '3', '4']) - - def test_slugify(self): - self.assertEqual(slugify(' Jack & Jill like numbers 1,2,3 and 4 and' - ' silly characters ?%.$!/'), - 'jack-jill-like-numbers-123-and-4-and-silly-characters') - - self.assertEqual(slugify("Un \xe9l\xe9phant \xe0 l'or\xe9e du bois"), - 'un-elephant-a-loree-du-bois') - - def test_stringformat(self): - self.assertEqual(stringformat(1, '03d'), '001') - self.assertEqual(stringformat(1, 'z'), '') - - def test_title(self): - self.assertEqual(title('a nice title, isn\'t it?'), - "A Nice Title, Isn't It?") - self.assertEqual(title('discoth\xe8que'), 'Discoth\xe8que') - - def test_truncatewords(self): - self.assertEqual( - truncatewords('A sentence with a few words in it', 1), 'A ...') - self.assertEqual( - truncatewords('A sentence with a few words in it', 5), - 'A sentence with a few ...') - self.assertEqual( - truncatewords('A sentence with a few words in it', 100), - 'A sentence with a few words in it') - self.assertEqual( - truncatewords('A sentence with a few words in it', - 'not a number'), 'A sentence with a few words in it') - - def test_truncatewords_html(self): - self.assertEqual(truncatewords_html( - '<p>one <a href="#">two - three <br>four</a> five</p>', 0), '') - self.assertEqual(truncatewords_html('<p>one <a href="#">two - ' - 'three <br>four</a> five</p>', 2), - '<p>one <a href="#">two ...</a></p>') - self.assertEqual(truncatewords_html( - '<p>one <a href="#">two - three <br>four</a> five</p>', 4), - '<p>one <a href="#">two - three <br>four ...</a></p>') - self.assertEqual(truncatewords_html( - '<p>one <a href="#">two - three <br>four</a> five</p>', 5), - '<p>one <a href="#">two - three <br>four</a> five</p>') - self.assertEqual(truncatewords_html( - '<p>one <a href="#">two - three <br>four</a> five</p>', 100), - '<p>one <a href="#">two - three <br>four</a> five</p>') - self.assertEqual(truncatewords_html( - '\xc5ngstr\xf6m was here', 1), '\xc5ngstr\xf6m ...') - self.assertEqual(truncatewords_html('<i>Buenos días! ' - '¿Cómo está?</i>', 3), - '<i>Buenos días! ¿Cómo ...</i>') - - def test_truncatechars_html(self): - self.assertEqual(truncatechars_html( - '<p>one <a href="#">two - three <br>four</a> five</p>', 0), '...') - self.assertEqual(truncatechars_html('<p>one <a href="#">two - ' - 'three <br>four</a> five</p>', 6), - '<p>one...</p>') - self.assertEqual(truncatechars_html( - '<p>one <a href="#">two - three <br>four</a> five</p>', 11), - '<p>one <a href="#">two ...</a></p>') - self.assertEqual(truncatechars_html( - '<p>one <a href="#">two - three <br>four</a> five</p>', 100), - '<p>one <a href="#">two - three <br>four</a> five</p>') - self.assertEqual(truncatechars_html( - '<b>\xc5ngstr\xf6m</b> was here', 5), '<b>\xc5n...</b>') - self.assertEqual(truncatechars_html( - 'a<b>b</b>c', 3), 'a<b>b</b>c') - - def test_upper(self): - self.assertEqual(upper('Mixed case input'), 'MIXED CASE INPUT') - # lowercase e umlaut - self.assertEqual(upper('\xeb'), '\xcb') - - def test_urlencode(self): - self.assertEqual(urlencode('fran\xe7ois & jill'), - 'fran%C3%A7ois%20%26%20jill') - self.assertEqual(urlencode(1), '1') - - def test_iriencode(self): - self.assertEqual(iriencode('S\xf8r-Tr\xf8ndelag'), - 'S%C3%B8r-Tr%C3%B8ndelag') - self.assertEqual(iriencode(urlencode('fran\xe7ois & jill')), - 'fran%C3%A7ois%20%26%20jill') - - def test_urlizetrunc(self): - self.assertEqual(urlizetrunc('http://short.com/', 20), '<a href=' - '"http://short.com/" rel="nofollow">http://short.com/</a>') - - self.assertEqual(urlizetrunc('http://www.google.co.uk/search?hl=en' - '&q=some+long+url&btnG=Search&meta=', 20), '<a href="http://' - 'www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&' - 'meta=" rel="nofollow">http://www.google...</a>') - - self.assertEqual(urlizetrunc('http://www.google.co.uk/search?hl=en' - '&q=some+long+url&btnG=Search&meta=', 20), '<a href="http://' - 'www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search' - '&meta=" rel="nofollow">http://www.google...</a>') - - # Check truncating of URIs which are the exact length - uri = 'http://31characteruri.com/test/' - self.assertEqual(len(uri), 31) - - self.assertEqual(urlizetrunc(uri, 31), - '<a href="http://31characteruri.com/test/" rel="nofollow">' - 'http://31characteruri.com/test/</a>') - - self.assertEqual(urlizetrunc(uri, 30), - '<a href="http://31characteruri.com/test/" rel="nofollow">' - 'http://31characteruri.com/t...</a>') - - self.assertEqual(urlizetrunc(uri, 2), - '<a href="http://31characteruri.com/test/"' - ' rel="nofollow">...</a>') - - def test_urlize(self): - # Check normal urlize - self.assertEqual(urlize('http://google.com'), - '<a href="http://google.com" rel="nofollow">http://google.com</a>') - self.assertEqual(urlize('http://google.com/'), - '<a href="http://google.com/" rel="nofollow">http://google.com/</a>') - self.assertEqual(urlize('www.google.com'), - '<a href="http://www.google.com" rel="nofollow">www.google.com</a>') - self.assertEqual(urlize('djangoproject.org'), - '<a href="http://djangoproject.org" rel="nofollow">djangoproject.org</a>') - self.assertEqual(urlize('djangoproject.org/'), - '<a href="http://djangoproject.org/" rel="nofollow">djangoproject.org/</a>') - self.assertEqual(urlize('info@djangoproject.org'), - '<a href="mailto:info@djangoproject.org">info@djangoproject.org</a>') - self.assertEqual(urlize('some.organization'), - 'some.organization'), - - # Check urlize with https addresses - self.assertEqual(urlize('https://google.com'), - '<a href="https://google.com" rel="nofollow">https://google.com</a>') - - # Check urlize doesn't overquote already quoted urls - see #9655 - # The teststring is the urlquoted version of 'http://hi.baidu.com/重新开始' - self.assertEqual(urlize('http://hi.baidu.com/%E9%87%8D%E6%96%B0%E5%BC%80%E5%A7%8B'), - '<a href="http://hi.baidu.com/%E9%87%8D%E6%96%B0%E5%BC%80%E5%A7%8B" rel="nofollow">' - 'http://hi.baidu.com/%E9%87%8D%E6%96%B0%E5%BC%80%E5%A7%8B</a>') - self.assertEqual(urlize('www.mystore.com/30%OffCoupons!'), - '<a href="http://www.mystore.com/30%25OffCoupons" rel="nofollow">' - 'www.mystore.com/30%OffCoupons</a>!') - self.assertEqual(urlize('http://en.wikipedia.org/wiki/Caf%C3%A9'), - '<a href="http://en.wikipedia.org/wiki/Caf%C3%A9" rel="nofollow">' - 'http://en.wikipedia.org/wiki/Caf%C3%A9</a>') - self.assertEqual(urlize('http://en.wikipedia.org/wiki/Café'), - '<a href="http://en.wikipedia.org/wiki/Caf%C3%A9" rel="nofollow">' - 'http://en.wikipedia.org/wiki/Café</a>') - - # Check urlize keeps balanced parentheses - see #11911 - self.assertEqual(urlize('http://en.wikipedia.org/wiki/Django_(web_framework)'), - '<a href="http://en.wikipedia.org/wiki/Django_(web_framework)" rel="nofollow">' - 'http://en.wikipedia.org/wiki/Django_(web_framework)</a>') - self.assertEqual(urlize('(see http://en.wikipedia.org/wiki/Django_(web_framework))'), - '(see <a href="http://en.wikipedia.org/wiki/Django_(web_framework)" rel="nofollow">' - 'http://en.wikipedia.org/wiki/Django_(web_framework)</a>)') - - # Check urlize adds nofollow properly - see #12183 - self.assertEqual(urlize('foo@bar.com or www.bar.com'), - '<a href="mailto:foo@bar.com">foo@bar.com</a> or ' - '<a href="http://www.bar.com" rel="nofollow">www.bar.com</a>') - - # Check urlize handles IDN correctly - see #13704 - self.assertEqual(urlize('http://c✶.ws'), - '<a href="http://xn--c-lgq.ws" rel="nofollow">http://c✶.ws</a>') - self.assertEqual(urlize('www.c✶.ws'), - '<a href="http://www.xn--c-lgq.ws" rel="nofollow">www.c✶.ws</a>') - self.assertEqual(urlize('c✶.org'), - '<a href="http://xn--c-lgq.org" rel="nofollow">c✶.org</a>') - self.assertEqual(urlize('info@c✶.org'), - '<a href="mailto:info@xn--c-lgq.org">info@c✶.org</a>') - - # Check urlize doesn't highlight malformed URIs - see #16395 - self.assertEqual(urlize('http:///www.google.com'), - 'http:///www.google.com') - self.assertEqual(urlize('http://.google.com'), - 'http://.google.com') - self.assertEqual(urlize('http://@foo.com'), - 'http://@foo.com') - - # Check urlize accepts more TLDs - see #16656 - self.assertEqual(urlize('usa.gov'), - '<a href="http://usa.gov" rel="nofollow">usa.gov</a>') - - # Check urlize don't crash on invalid email with dot-starting domain - see #17592 - self.assertEqual(urlize('email@.stream.ru'), - 'email@.stream.ru') - - # Check urlize accepts uppercased URL schemes - see #18071 - self.assertEqual(urlize('HTTPS://github.com/'), - '<a href="https://github.com/" rel="nofollow">HTTPS://github.com/</a>') - - # Check urlize trims trailing period when followed by parenthesis - see #18644 - self.assertEqual(urlize('(Go to http://www.example.com/foo.)'), - '(Go to <a href="http://www.example.com/foo" rel="nofollow">http://www.example.com/foo</a>.)') - - # Check urlize handles brackets properly (#19070) - self.assertEqual(urlize('[see www.example.com]'), - '[see <a href="http://www.example.com" rel="nofollow">www.example.com</a>]') - self.assertEqual(urlize('see test[at[example.com'), - 'see <a href="http://test[at[example.com" rel="nofollow">test[at[example.com</a>') - self.assertEqual(urlize('[http://168.192.0.1](http://168.192.0.1)'), - '[<a href="http://168.192.0.1](http://168.192.0.1)" rel="nofollow">http://168.192.0.1](http://168.192.0.1)</a>') - - # Check urlize works with IPv4/IPv6 addresses - self.assertEqual(urlize('http://192.168.0.15/api/9'), - '<a href="http://192.168.0.15/api/9" rel="nofollow">http://192.168.0.15/api/9</a>') - self.assertEqual(urlize('http://[2001:db8:cafe::2]/api/9'), - '<a href="http://[2001:db8:cafe::2]/api/9" rel="nofollow">http://[2001:db8:cafe::2]/api/9</a>') - - # Check urlize correctly include quotation marks in links - #20364 - self.assertEqual(urlize('before "hi@example.com" afterwards'), - 'before "<a href="mailto:hi@example.com">hi@example.com</a>" afterwards') - self.assertEqual(urlize('before hi@example.com" afterwards'), - 'before <a href="mailto:hi@example.com">hi@example.com</a>" afterwards') - self.assertEqual(urlize('before "hi@example.com afterwards'), - 'before "<a href="mailto:hi@example.com">hi@example.com</a> afterwards') - self.assertEqual(urlize('before \'hi@example.com\' afterwards'), - 'before \'<a href="mailto:hi@example.com">hi@example.com</a>\' afterwards') - self.assertEqual(urlize('before hi@example.com\' afterwards'), - 'before <a href="mailto:hi@example.com">hi@example.com</a>\' afterwards') - self.assertEqual(urlize('before \'hi@example.com afterwards'), - 'before \'<a href="mailto:hi@example.com">hi@example.com</a> afterwards') - - # Check urlize copes with commas following URLs in quotes - see #20364 - self.assertEqual(urlize('Email us at "hi@example.com", or phone us at +xx.yy'), - 'Email us at "<a href="mailto:hi@example.com">hi@example.com</a>", or phone us at +xx.yy') - - # Check urlize correctly handles exclamation marks after TLDs or query string - see #23715 - self.assertEqual(urlize('Go to djangoproject.com! and enjoy.'), - 'Go to <a href="http://djangoproject.com" rel="nofollow">djangoproject.com</a>! and enjoy.') - self.assertEqual(urlize('Search for google.com/?q=! and see.'), - 'Search for <a href="http://google.com/?q=" rel="nofollow">google.com/?q=</a>! and see.') - self.assertEqual(urlize('Search for google.com/?q=dj!`? and see.'), - 'Search for <a href="http://google.com/?q=dj%21%60%3F" rel="nofollow">google.com/?q=dj!`?</a> and see.') - self.assertEqual(urlize('Search for google.com/?q=dj!`?! and see.'), - 'Search for <a href="http://google.com/?q=dj%21%60%3F" rel="nofollow">google.com/?q=dj!`?</a>! and see.') - - def test_wordcount(self): - self.assertEqual(wordcount(''), 0) - self.assertEqual(wordcount('oneword'), 1) - self.assertEqual(wordcount('lots of words'), 3) - - def test_wordwrap(self): - self.assertEqual(wordwrap('this is a long paragraph of text that ' - "really needs to be wrapped I'm afraid", 14), - 'this is a long\nparagraph of\ntext that\nreally needs\nto be ' - "wrapped\nI'm afraid") - self.assertEqual(wordwrap('this is a short paragraph of text.\n ' - 'But this line should be indented', 14), - 'this is a\nshort\nparagraph of\ntext.\n But this\nline ' - 'should be\nindented') - self.assertEqual(wordwrap('this is a short paragraph of text.\n ' - 'But this line should be indented', 15), 'this is a short\n' - 'paragraph of\ntext.\n But this line\nshould be\nindented') - - def test_rjust(self): - self.assertEqual(ljust('test', 10), 'test ') - self.assertEqual(ljust('test', 3), 'test') - self.assertEqual(rjust('test', 10), ' test') - self.assertEqual(rjust('test', 3), 'test') - - def test_center(self): - self.assertEqual(center('test', 6), ' test ') - - def test_cut(self): - self.assertEqual(cut('a string to be mangled', 'a'), - ' string to be mngled') - self.assertEqual(cut('a string to be mangled', 'ng'), - 'a stri to be maled') - self.assertEqual(cut('a string to be mangled', 'strings'), - 'a string to be mangled') - - def test_force_escape(self): - escaped = force_escape('<some html & special characters > here') - self.assertEqual( - escaped, '<some html & special characters > here') - self.assertIsInstance(escaped, SafeData) - self.assertEqual( - force_escape('<some html & special characters > here ĐÅ€£'), - '<some html & special characters > here' - ' \u0110\xc5\u20ac\xa3') - - def test_linebreaks(self): - self.assertEqual(linebreaks_filter('line 1'), '<p>line 1</p>') - self.assertEqual(linebreaks_filter('line 1\nline 2'), - '<p>line 1<br />line 2</p>') - self.assertEqual(linebreaks_filter('line 1\rline 2'), - '<p>line 1<br />line 2</p>') - self.assertEqual(linebreaks_filter('line 1\r\nline 2'), - '<p>line 1<br />line 2</p>') - - def test_linebreaksbr(self): - self.assertEqual(linebreaksbr('line 1\nline 2'), - 'line 1<br />line 2') - self.assertEqual(linebreaksbr('line 1\rline 2'), - 'line 1<br />line 2') - self.assertEqual(linebreaksbr('line 1\r\nline 2'), - 'line 1<br />line 2') - - def test_removetags(self): - with warnings.catch_warnings(record=True): - warnings.simplefilter("always") - self.assertEqual(removetags('some <b>html</b> with <script>alert' - '("You smell")</script> disallowed <img /> tags', 'script img'), - 'some <b>html</b> with alert("You smell") disallowed tags') - - def test_striptags(self): - self.assertEqual(striptags('some <b>html</b> with <script>alert' - '("You smell")</script> disallowed <img /> tags'), - 'some html with alert("You smell") disallowed tags') - - def test_dictsort(self): - sorted_dicts = dictsort([{'age': 23, 'name': 'Barbara-Ann'}, - {'age': 63, 'name': 'Ra Ra Rasputin'}, - {'name': 'Jonny B Goode', 'age': 18}], 'age') - - self.assertEqual([sorted(dict.items()) for dict in sorted_dicts], - [[('age', 18), ('name', 'Jonny B Goode')], - [('age', 23), ('name', 'Barbara-Ann')], - [('age', 63), ('name', 'Ra Ra Rasputin')]]) - - # If it gets passed a list of something else different from - # dictionaries it should fail silently - self.assertEqual(dictsort([1, 2, 3], 'age'), '') - self.assertEqual(dictsort('Hello!', 'age'), '') - self.assertEqual(dictsort({'a': 1}, 'age'), '') - self.assertEqual(dictsort(1, 'age'), '') - - def test_dictsort_complex_sorting_key(self): - """ - Since dictsort uses template.Variable under the hood, it can sort - on keys like 'foo.bar'. - """ - data = [ - {'foo': {'bar': 1, 'baz': 'c'}}, - {'foo': {'bar': 2, 'baz': 'b'}}, - {'foo': {'bar': 3, 'baz': 'a'}}, - ] - sorted_data = dictsort(data, 'foo.baz') - - self.assertEqual([d['foo']['bar'] for d in sorted_data], [3, 2, 1]) - - def test_dictsortreversed(self): - sorted_dicts = dictsortreversed([{'age': 23, 'name': 'Barbara-Ann'}, - {'age': 63, 'name': 'Ra Ra Rasputin'}, - {'name': 'Jonny B Goode', 'age': 18}], - 'age') - - self.assertEqual([sorted(dict.items()) for dict in sorted_dicts], - [[('age', 63), ('name', 'Ra Ra Rasputin')], - [('age', 23), ('name', 'Barbara-Ann')], - [('age', 18), ('name', 'Jonny B Goode')]]) - - # If it gets passed a list of something else different from - # dictionaries it should fail silently - self.assertEqual(dictsortreversed([1, 2, 3], 'age'), '') - self.assertEqual(dictsortreversed('Hello!', 'age'), '') - self.assertEqual(dictsortreversed({'a': 1}, 'age'), '') - self.assertEqual(dictsortreversed(1, 'age'), '') - - def test_first(self): - self.assertEqual(first([0, 1, 2]), 0) - self.assertEqual(first(''), '') - self.assertEqual(first('test'), 't') - - def test_join(self): - self.assertEqual(join([0, 1, 2], 'glue'), '0glue1glue2') - - def test_length(self): - self.assertEqual(length('1234'), 4) - self.assertEqual(length(mark_safe('1234')), 4) - self.assertEqual(length([1, 2, 3, 4]), 4) - self.assertEqual(length_is([], 0), True) - self.assertEqual(length_is([], 1), False) - self.assertEqual(length_is('a', 1), True) - self.assertEqual(length_is('a', 10), False) - - def test_slice(self): - self.assertEqual(slice_filter('abcdefg', '0'), '') - self.assertEqual(slice_filter('abcdefg', '1'), 'a') - self.assertEqual(slice_filter('abcdefg', '-1'), 'abcdef') - self.assertEqual(slice_filter('abcdefg', '1:2'), 'b') - self.assertEqual(slice_filter('abcdefg', '1:3'), 'bc') - self.assertEqual(slice_filter('abcdefg', '0::2'), 'aceg') - - def test_unordered_list(self): - self.assertEqual(unordered_list(['item 1', 'item 2']), - '\t<li>item 1</li>\n\t<li>item 2</li>') - self.assertEqual(unordered_list(['item 1', ['item 1.1']]), - '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>') - - self.assertEqual( - unordered_list(['item 1', ['item 1.1', 'item1.2'], 'item 2']), - '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t\t<li>item1.2' - '</li>\n\t</ul>\n\t</li>\n\t<li>item 2</li>') - - self.assertEqual( - unordered_list(['item 1', ['item 1.1', ['item 1.1.1', ['item 1.1.1.1']]]]), - '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1\n\t\t<ul>\n\t\t\t<li>' - 'item 1.1.1\n\t\t\t<ul>\n\t\t\t\t<li>item 1.1.1.1</li>\n\t\t\t' - '</ul>\n\t\t\t</li>\n\t\t</ul>\n\t\t</li>\n\t</ul>\n\t</li>') - - self.assertEqual(unordered_list( - ['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]), - '\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>' - 'Lawrence</li>\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>' - '\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>') - - @python_2_unicode_compatible - class ULItem(object): - def __init__(self, title): - self.title = title - - def __str__(self): - return 'ulitem-%s' % str(self.title) - - a = ULItem('a') - b = ULItem('b') - self.assertEqual(unordered_list([a, b]), '\t<li>ulitem-a</li>\n\t<li>ulitem-b</li>') - - def item_generator(): - yield a - yield b - - self.assertEqual(unordered_list(item_generator()), '\t<li>ulitem-a</li>\n\t<li>ulitem-b</li>') - - # Old format for unordered lists should still work - with warnings.catch_warnings(record=True): - warnings.simplefilter("always") - - self.assertEqual(unordered_list(['item 1', []]), '\t<li>item 1</li>') - - self.assertEqual(unordered_list(['item 1', [['item 1.1', []]]]), - '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>') - - self.assertEqual(unordered_list(['item 1', [['item 1.1', []], - ['item 1.2', []]]]), '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1' - '</li>\n\t\t<li>item 1.2</li>\n\t</ul>\n\t</li>') - - self.assertEqual(unordered_list(['States', [['Kansas', [['Lawrence', - []], ['Topeka', []]]], ['Illinois', []]]]), '\t<li>States\n\t' - '<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>Lawrence</li>' - '\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>\n\t\t<li>' - 'Illinois</li>\n\t</ul>\n\t</li>') - - def test_add(self): - self.assertEqual(add('1', '2'), 3) - - def test_get_digit(self): - self.assertEqual(get_digit(123, 1), 3) - self.assertEqual(get_digit(123, 2), 2) - self.assertEqual(get_digit(123, 3), 1) - self.assertEqual(get_digit(123, 4), 0) - self.assertEqual(get_digit(123, 0), 123) - self.assertEqual(get_digit('xyz', 0), 'xyz') - - def test_date(self): - # real testing of date() is in dateformat.py - self.assertEqual(date(datetime.datetime(2005, 12, 29), "d F Y"), - '29 December 2005') - self.assertEqual(date(datetime.datetime(2005, 12, 29), r'jS \o\f F'), - '29th of December') - - def test_time(self): - # real testing of time() is done in dateformat.py - self.assertEqual(time(datetime.time(13), "h"), '01') - self.assertEqual(time(datetime.time(0), "h"), '12') - - def test_timesince(self): - # real testing is done in timesince.py, where we can provide our own 'now' - # NOTE: \xa0 avoids wrapping between value and unit - self.assertEqual( - timesince_filter(datetime.datetime.now() - datetime.timedelta(1)), - '1\xa0day') - - self.assertEqual( - timesince_filter(datetime.datetime(2005, 12, 29), - datetime.datetime(2005, 12, 30)), - '1\xa0day') - - def test_timeuntil(self): - # NOTE: \xa0 avoids wrapping between value and unit - self.assertEqual( - timeuntil_filter(datetime.datetime.now() + datetime.timedelta(1, 1)), - '1\xa0day') - - self.assertEqual( - timeuntil_filter(datetime.datetime(2005, 12, 30), - datetime.datetime(2005, 12, 29)), - '1\xa0day') - - def test_default(self): - self.assertEqual(default("val", "default"), 'val') - self.assertEqual(default(None, "default"), 'default') - self.assertEqual(default('', "default"), 'default') - - def test_if_none(self): - self.assertEqual(default_if_none("val", "default"), 'val') - self.assertEqual(default_if_none(None, "default"), 'default') - self.assertEqual(default_if_none('', "default"), '') - - def test_divisibleby(self): - self.assertEqual(divisibleby(4, 2), True) - self.assertEqual(divisibleby(4, 3), False) - - def test_yesno(self): - self.assertEqual(yesno(True), 'yes') - self.assertEqual(yesno(False), 'no') - self.assertEqual(yesno(None), 'maybe') - self.assertEqual(yesno(True, 'certainly,get out of town,perhaps'), - 'certainly') - self.assertEqual(yesno(False, 'certainly,get out of town,perhaps'), - 'get out of town') - self.assertEqual(yesno(None, 'certainly,get out of town,perhaps'), - 'perhaps') - self.assertEqual(yesno(None, 'certainly,get out of town'), - 'get out of town') - - def test_filesizeformat(self): - # NOTE: \xa0 avoids wrapping between value and unit - self.assertEqual(filesizeformat(1023), '1023\xa0bytes') - self.assertEqual(filesizeformat(1024), '1.0\xa0KB') - self.assertEqual(filesizeformat(10 * 1024), '10.0\xa0KB') - self.assertEqual(filesizeformat(1024 * 1024 - 1), '1024.0\xa0KB') - self.assertEqual(filesizeformat(1024 * 1024), '1.0\xa0MB') - self.assertEqual(filesizeformat(1024 * 1024 * 50), '50.0\xa0MB') - self.assertEqual(filesizeformat(1024 * 1024 * 1024 - 1), '1024.0\xa0MB') - self.assertEqual(filesizeformat(1024 * 1024 * 1024), '1.0\xa0GB') - self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024), '1.0\xa0TB') - self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024 * 1024), '1.0\xa0PB') - self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024 * 1024 * 2000), '2000.0\xa0PB') - self.assertEqual(filesizeformat(complex(1, -1)), '0\xa0bytes') - self.assertEqual(filesizeformat(""), '0\xa0bytes') - self.assertEqual(filesizeformat("\N{GREEK SMALL LETTER ALPHA}"), '0\xa0bytes') - - def test_pluralize(self): - self.assertEqual(pluralize(1), '') - self.assertEqual(pluralize(0), 's') - self.assertEqual(pluralize(2), 's') - - # Ticket #22798 - self.assertEqual(pluralize(0.5), 's') - self.assertEqual(pluralize(1.5), 's') - - self.assertEqual(pluralize(decimal.Decimal(1)), '') - self.assertEqual(pluralize(decimal.Decimal(0)), 's') - self.assertEqual(pluralize(decimal.Decimal(2)), 's') - self.assertEqual(pluralize([1]), '') - self.assertEqual(pluralize([]), 's') - self.assertEqual(pluralize([1, 2, 3]), 's') - self.assertEqual(pluralize(1, 'es'), '') - self.assertEqual(pluralize(0, 'es'), 'es') - self.assertEqual(pluralize(2, 'es'), 'es') - self.assertEqual(pluralize(1, 'y,ies'), 'y') - self.assertEqual(pluralize(0, 'y,ies'), 'ies') - self.assertEqual(pluralize(2, 'y,ies'), 'ies') - self.assertEqual(pluralize(0, 'y,ies,error'), '') - - def test_phone2numeric(self): - self.assertEqual(phone2numeric_filter('0800 flowers'), '0800 3569377') - - def test_non_string_input(self): - # Filters shouldn't break if passed non-strings - self.assertEqual(addslashes(123), '123') - self.assertEqual(linenumbers(123), '1. 123') - self.assertEqual(lower(123), '123') - self.assertEqual(make_list(123), ['1', '2', '3']) - self.assertEqual(slugify(123), '123') - self.assertEqual(title(123), '123') - self.assertEqual(truncatewords(123, 2), '123') - self.assertEqual(upper(123), '123') - self.assertEqual(urlencode(123), '123') - self.assertEqual(urlize(123), '123') - self.assertEqual(urlizetrunc(123, 1), '123') - self.assertEqual(wordcount(123), 1) - self.assertEqual(wordwrap(123, 2), '123') - self.assertEqual(ljust('123', 4), '123 ') - self.assertEqual(rjust('123', 4), ' 123') - self.assertEqual(center('123', 5), ' 123 ') - self.assertEqual(center('123', 6), ' 123 ') - self.assertEqual(cut(123, '2'), '13') - self.assertEqual(escape(123), '123') - self.assertEqual(linebreaks_filter(123), '<p>123</p>') - self.assertEqual(linebreaksbr(123), '123') - with warnings.catch_warnings(record=True): - warnings.simplefilter("always") - self.assertEqual(removetags(123, 'a'), '123') - self.assertEqual(striptags(123), '123') - - -class DefaultFiltersI18NTests(TestCase): - - def test_localized_filesizeformat(self): - # NOTE: \xa0 avoids wrapping between value and unit - with self.settings(USE_L10N=True), translation.override('de'): - self.assertEqual(filesizeformat(1023), '1023\xa0Bytes') - self.assertEqual(filesizeformat(1024), '1,0\xa0KB') - self.assertEqual(filesizeformat(10 * 1024), '10,0\xa0KB') - self.assertEqual(filesizeformat(1024 * 1024 - 1), '1024,0\xa0KB') - self.assertEqual(filesizeformat(1024 * 1024), '1,0\xa0MB') - self.assertEqual(filesizeformat(1024 * 1024 * 50), '50,0\xa0MB') - self.assertEqual(filesizeformat(1024 * 1024 * 1024 - 1), '1024,0\xa0MB') - self.assertEqual(filesizeformat(1024 * 1024 * 1024), '1,0\xa0GB') - self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024), '1,0\xa0TB') - self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024 * 1024), '1,0\xa0PB') - self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024 * 1024 * 2000), '2000,0\xa0PB') - self.assertEqual(filesizeformat(complex(1, -1)), '0\xa0Bytes') - self.assertEqual(filesizeformat(""), '0\xa0Bytes') - self.assertEqual(filesizeformat("\N{GREEK SMALL LETTER ALPHA}"), '0\xa0Bytes') diff --git a/tests/template_tests/filter_tests/test_add.py b/tests/template_tests/filter_tests/test_add.py index 9faf81dfa5..802c1cfe19 100644 --- a/tests/template_tests/filter_tests/test_add.py +++ b/tests/template_tests/filter_tests/test_add.py @@ -1,5 +1,6 @@ from datetime import date, timedelta +from django.template.defaultfilters import add from django.test import SimpleTestCase from ..utils import render, setup @@ -44,3 +45,9 @@ class AddTests(SimpleTestCase): def test_add07(self): output = render('add07', {'d': date(2000, 1, 1), 't': timedelta(10)}) self.assertEqual(output, 'Jan. 11, 2000') + + +class FunctionTests(SimpleTestCase): + + def test_add(self): + self.assertEqual(add('1', '2'), 3) diff --git a/tests/template_tests/filter_tests/test_addslashes.py b/tests/template_tests/filter_tests/test_addslashes.py index 4d712b4bd4..7be84c0220 100644 --- a/tests/template_tests/filter_tests/test_addslashes.py +++ b/tests/template_tests/filter_tests/test_addslashes.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import addslashes from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -15,3 +16,18 @@ class AddslashesTests(SimpleTestCase): def test_addslashes02(self): output = render('addslashes02', {"a": "<a>'", "b": mark_safe("<a>'")}) self.assertEqual(output, r"<a>\' <a>\'") + + +class FunctionTests(SimpleTestCase): + + def test_quotes(self): + self.assertEqual( + addslashes('"double quotes" and \'single quotes\''), + '\\"double quotes\\" and \\\'single quotes\\\'', + ) + + def test_backslashes(self): + self.assertEqual(addslashes(r'\ : backslashes, too'), '\\\\ : backslashes, too') + + def test_non_string_input(self): + self.assertEqual(addslashes(123), '123') diff --git a/tests/template_tests/filter_tests/test_capfirst.py b/tests/template_tests/filter_tests/test_capfirst.py index 07546ad6c7..d7a28130f9 100644 --- a/tests/template_tests/filter_tests/test_capfirst.py +++ b/tests/template_tests/filter_tests/test_capfirst.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import capfirst from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -15,3 +16,9 @@ class CapfirstTests(SimpleTestCase): def test_capfirst02(self): output = render('capfirst02', {'a': 'fred>', 'b': mark_safe('fred>')}) self.assertEqual(output, 'Fred> Fred>') + + +class FunctionTests(SimpleTestCase): + + def test_capfirst(self): + self.assertEqual(capfirst('hello world'), 'Hello world') diff --git a/tests/template_tests/filter_tests/test_center.py b/tests/template_tests/filter_tests/test_center.py index 6f10f99a85..0dbb1002b7 100644 --- a/tests/template_tests/filter_tests/test_center.py +++ b/tests/template_tests/filter_tests/test_center.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import center from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -16,3 +17,12 @@ class CenterTests(SimpleTestCase): def test_center02(self): output = render('center02', {"a": "a&b", "b": mark_safe("a&b")}) self.assertEqual(output, ". a&b . . a&b .") + + +class FunctionTests(SimpleTestCase): + + def test_center(self): + self.assertEqual(center('test', 6), ' test ') + + def test_non_string_input(self): + self.assertEqual(center(123, 5), ' 123 ') diff --git a/tests/template_tests/filter_tests/test_cut.py b/tests/template_tests/filter_tests/test_cut.py index 68568df30c..fde23266ba 100644 --- a/tests/template_tests/filter_tests/test_cut.py +++ b/tests/template_tests/filter_tests/test_cut.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import cut from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -37,3 +38,18 @@ class CutTests(SimpleTestCase): def test_cut06(self): output = render('cut06', {"a": "x&y", "b": mark_safe("x&y")}) self.assertEqual(output, "x&y x&ampy") + + +class FunctionTests(SimpleTestCase): + + def test_character(self): + self.assertEqual(cut('a string to be mangled', 'a'), ' string to be mngled') + + def test_characters(self): + self.assertEqual(cut('a string to be mangled', 'ng'), 'a stri to be maled') + + def test_non_matching_string(self): + self.assertEqual(cut('a string to be mangled', 'strings'), 'a string to be mangled') + + def test_non_string_input(self): + self.assertEqual(cut(123, '2'), '13') diff --git a/tests/template_tests/filter_tests/test_date.py b/tests/template_tests/filter_tests/test_date.py index cbec356908..e546dae430 100644 --- a/tests/template_tests/filter_tests/test_date.py +++ b/tests/template_tests/filter_tests/test_date.py @@ -1,5 +1,7 @@ from datetime import datetime, time +from django.template.defaultfilters import date +from django.test import SimpleTestCase from django.utils import timezone from .timezone_utils import TimezoneTestCase @@ -58,3 +60,12 @@ class DateTests(TimezoneTestCase): def test_date09(self): output = render('date09', {'t': time(0, 0)}) self.assertEqual(output, '00:00') + + +class FunctionTests(SimpleTestCase): + + def test_date(self): + self.assertEqual(date(datetime(2005, 12, 29), "d F Y"), '29 December 2005') + + def test_escape_characters(self): + self.assertEqual(date(datetime(2005, 12, 29), r'jS \o\f F'), '29th of December') diff --git a/tests/template_tests/filter_tests/test_default.py b/tests/template_tests/filter_tests/test_default.py index 790f60cd3b..766957ba35 100644 --- a/tests/template_tests/filter_tests/test_default.py +++ b/tests/template_tests/filter_tests/test_default.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import default from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -45,3 +46,15 @@ class DefaultIfNoneTests(SimpleTestCase): def test_default_if_none02(self): output = render('default_if_none02', {"a": None}) self.assertEqual(output, "x<") + + +class FunctionTests(SimpleTestCase): + + def test_value(self): + self.assertEqual(default('val', 'default'), 'val') + + def test_none(self): + self.assertEqual(default(None, 'default'), 'default') + + def test_empty_string(self): + self.assertEqual(default('', 'default'), 'default') diff --git a/tests/template_tests/filter_tests/test_default_if_none.py b/tests/template_tests/filter_tests/test_default_if_none.py new file mode 100644 index 0000000000..45bd666913 --- /dev/null +++ b/tests/template_tests/filter_tests/test_default_if_none.py @@ -0,0 +1,14 @@ +from django.template.defaultfilters import default_if_none +from django.test import SimpleTestCase + + +class FunctionTests(SimpleTestCase): + + def test_value(self): + self.assertEqual(default_if_none("val", 'default'), 'val') + + def test_none(self): + self.assertEqual(default_if_none(None, 'default'), 'default') + + def test_empty_string(self): + self.assertEqual(default_if_none('', 'default'), '') diff --git a/tests/template_tests/filter_tests/test_dictsort.py b/tests/template_tests/filter_tests/test_dictsort.py new file mode 100644 index 0000000000..1d937a2dae --- /dev/null +++ b/tests/template_tests/filter_tests/test_dictsort.py @@ -0,0 +1,44 @@ +from django.template.defaultfilters import dictsort +from django.test import SimpleTestCase + + +class FunctionTests(SimpleTestCase): + + def test_sort(self): + sorted_dicts = dictsort( + [{'age': 23, 'name': 'Barbara-Ann'}, + {'age': 63, 'name': 'Ra Ra Rasputin'}, + {'name': 'Jonny B Goode', 'age': 18}], + 'age', + ) + + self.assertEqual( + [sorted(dict.items()) for dict in sorted_dicts], + [[('age', 18), ('name', 'Jonny B Goode')], + [('age', 23), ('name', 'Barbara-Ann')], + [('age', 63), ('name', 'Ra Ra Rasputin')]], + ) + + def test_dictsort_complex_sorting_key(self): + """ + Since dictsort uses template.Variable under the hood, it can sort + on keys like 'foo.bar'. + """ + data = [ + {'foo': {'bar': 1, 'baz': 'c'}}, + {'foo': {'bar': 2, 'baz': 'b'}}, + {'foo': {'bar': 3, 'baz': 'a'}}, + ] + sorted_data = dictsort(data, 'foo.baz') + + self.assertEqual([d['foo']['bar'] for d in sorted_data], [3, 2, 1]) + + def test_invalid_values(self): + """ + If dictsort is passed something other than a list of dictionaries, + fail silently. + """ + self.assertEqual(dictsort([1, 2, 3], 'age'), '') + self.assertEqual(dictsort('Hello!', 'age'), '') + self.assertEqual(dictsort({'a': 1}, 'age'), '') + self.assertEqual(dictsort(1, 'age'), '') diff --git a/tests/template_tests/filter_tests/test_dictsortreversed.py b/tests/template_tests/filter_tests/test_dictsortreversed.py new file mode 100644 index 0000000000..92229495fe --- /dev/null +++ b/tests/template_tests/filter_tests/test_dictsortreversed.py @@ -0,0 +1,30 @@ +from django.template.defaultfilters import dictsortreversed +from django.test import SimpleTestCase + + +class FunctionTests(SimpleTestCase): + + def test_sort(self): + sorted_dicts = dictsortreversed( + [{'age': 23, 'name': 'Barbara-Ann'}, + {'age': 63, 'name': 'Ra Ra Rasputin'}, + {'name': 'Jonny B Goode', 'age': 18}], + 'age', + ) + + self.assertEqual( + [sorted(dict.items()) for dict in sorted_dicts], + [[('age', 63), ('name', 'Ra Ra Rasputin')], + [('age', 23), ('name', 'Barbara-Ann')], + [('age', 18), ('name', 'Jonny B Goode')]], + ) + + def test_invalid_values(self): + """ + If dictsortreversed is passed something other than a list of + dictionaries, fail silently. + """ + self.assertEqual(dictsortreversed([1, 2, 3], 'age'), '') + self.assertEqual(dictsortreversed('Hello!', 'age'), '') + self.assertEqual(dictsortreversed({'a': 1}, 'age'), '') + self.assertEqual(dictsortreversed(1, 'age'), '') diff --git a/tests/template_tests/filter_tests/test_divisibleby.py b/tests/template_tests/filter_tests/test_divisibleby.py new file mode 100644 index 0000000000..2b3fe9aa4c --- /dev/null +++ b/tests/template_tests/filter_tests/test_divisibleby.py @@ -0,0 +1,11 @@ +from django.template.defaultfilters import divisibleby +from django.test import SimpleTestCase + + +class FunctionTests(SimpleTestCase): + + def test_true(self): + self.assertEqual(divisibleby(4, 2), True) + + def test_false(self): + self.assertEqual(divisibleby(4, 3), False) diff --git a/tests/template_tests/filter_tests/test_escape.py b/tests/template_tests/filter_tests/test_escape.py index 81f0f4037a..094bf575ce 100644 --- a/tests/template_tests/filter_tests/test_escape.py +++ b/tests/template_tests/filter_tests/test_escape.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import escape from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -31,3 +32,9 @@ class EscapeTests(SimpleTestCase): def test_escape04(self): output = render('escape04', {"a": "x&y"}) self.assertEqual(output, "x&y") + + +class FunctionTests(SimpleTestCase): + + def test_non_string_input(self): + self.assertEqual(escape(123), '123') diff --git a/tests/template_tests/filter_tests/test_escapejs.py b/tests/template_tests/filter_tests/test_escapejs.py index 82019022ec..d124be1667 100644 --- a/tests/template_tests/filter_tests/test_escapejs.py +++ b/tests/template_tests/filter_tests/test_escapejs.py @@ -1,3 +1,6 @@ +from __future__ import unicode_literals + +from django.template.defaultfilters import escapejs_filter from django.test import SimpleTestCase from ..utils import render, setup @@ -18,3 +21,33 @@ class EscapejsTests(SimpleTestCase): self.assertEqual(output, 'testing\\u000D\\u000Ajavascript ' '\\u0027string\\u0022 \\u003Cb\\u003E' 'escaping\\u003C/b\\u003E') + + +class FunctionTests(SimpleTestCase): + + def test_quotes(self): + self.assertEqual( + escapejs_filter('"double quotes" and \'single quotes\''), + '\\u0022double quotes\\u0022 and \\u0027single quotes\\u0027', + ) + + def test_backslashes(self): + self.assertEqual(escapejs_filter(r'\ : backslashes, too'), '\\u005C : backslashes, too') + + def test_whitespace(self): + self.assertEqual( + escapejs_filter('and lots of whitespace: \r\n\t\v\f\b'), + 'and lots of whitespace: \\u000D\\u000A\\u0009\\u000B\\u000C\\u0008', + ) + + def test_script(self): + self.assertEqual( + escapejs_filter(r'<script>and this</script>'), + '\\u003Cscript\\u003Eand this\\u003C/script\\u003E', + ) + + def test_paragraph_separator(self): + self.assertEqual( + escapejs_filter('paragraph separator:\u2029and line separator:\u2028'), + 'paragraph separator:\\u2029and line separator:\\u2028', + ) diff --git a/tests/template_tests/filter_tests/test_filesizeformat.py b/tests/template_tests/filter_tests/test_filesizeformat.py new file mode 100644 index 0000000000..c94da8c8d6 --- /dev/null +++ b/tests/template_tests/filter_tests/test_filesizeformat.py @@ -0,0 +1,41 @@ +from __future__ import unicode_literals + +from django.template.defaultfilters import filesizeformat +from django.test import SimpleTestCase +from django.utils import translation + + +class FunctionTests(SimpleTestCase): + + def test_formats(self): + self.assertEqual(filesizeformat(1023), '1023\xa0bytes') + self.assertEqual(filesizeformat(1024), '1.0\xa0KB') + self.assertEqual(filesizeformat(10 * 1024), '10.0\xa0KB') + self.assertEqual(filesizeformat(1024 * 1024 - 1), '1024.0\xa0KB') + self.assertEqual(filesizeformat(1024 * 1024), '1.0\xa0MB') + self.assertEqual(filesizeformat(1024 * 1024 * 50), '50.0\xa0MB') + self.assertEqual(filesizeformat(1024 * 1024 * 1024 - 1), '1024.0\xa0MB') + self.assertEqual(filesizeformat(1024 * 1024 * 1024), '1.0\xa0GB') + self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024), '1.0\xa0TB') + self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024 * 1024), '1.0\xa0PB') + self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024 * 1024 * 2000), '2000.0\xa0PB') + self.assertEqual(filesizeformat(complex(1, -1)), '0\xa0bytes') + self.assertEqual(filesizeformat(""), '0\xa0bytes') + self.assertEqual(filesizeformat("\N{GREEK SMALL LETTER ALPHA}"), '0\xa0bytes') + + def test_localized_formats(self): + with self.settings(USE_L10N=True), translation.override('de'): + self.assertEqual(filesizeformat(1023), '1023\xa0Bytes') + self.assertEqual(filesizeformat(1024), '1,0\xa0KB') + self.assertEqual(filesizeformat(10 * 1024), '10,0\xa0KB') + self.assertEqual(filesizeformat(1024 * 1024 - 1), '1024,0\xa0KB') + self.assertEqual(filesizeformat(1024 * 1024), '1,0\xa0MB') + self.assertEqual(filesizeformat(1024 * 1024 * 50), '50,0\xa0MB') + self.assertEqual(filesizeformat(1024 * 1024 * 1024 - 1), '1024,0\xa0MB') + self.assertEqual(filesizeformat(1024 * 1024 * 1024), '1,0\xa0GB') + self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024), '1,0\xa0TB') + self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024 * 1024), '1,0\xa0PB') + self.assertEqual(filesizeformat(1024 * 1024 * 1024 * 1024 * 1024 * 2000), '2000,0\xa0PB') + self.assertEqual(filesizeformat(complex(1, -1)), '0\xa0Bytes') + self.assertEqual(filesizeformat(""), '0\xa0Bytes') + self.assertEqual(filesizeformat("\N{GREEK SMALL LETTER ALPHA}"), '0\xa0Bytes') diff --git a/tests/template_tests/filter_tests/test_first.py b/tests/template_tests/filter_tests/test_first.py index 566a70c4ac..c7361dbd12 100644 --- a/tests/template_tests/filter_tests/test_first.py +++ b/tests/template_tests/filter_tests/test_first.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import first from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -15,3 +16,15 @@ class FirstTests(SimpleTestCase): def test_first02(self): output = render('first02', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}) self.assertEqual(output, "a&b a&b") + + +class FunctionTests(SimpleTestCase): + + def test_list(self): + self.assertEqual(first([0, 1, 2]), 0) + + def test_empty_string(self): + self.assertEqual(first(''), '') + + def test_string(self): + self.assertEqual(first('test'), 't') diff --git a/tests/template_tests/filter_tests/test_floatformat.py b/tests/template_tests/filter_tests/test_floatformat.py index a69278f958..466984b006 100644 --- a/tests/template_tests/filter_tests/test_floatformat.py +++ b/tests/template_tests/filter_tests/test_floatformat.py @@ -1,4 +1,12 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from decimal import Decimal, localcontext +from unittest import expectedFailure + +from django.template.defaultfilters import floatformat from django.test import SimpleTestCase +from django.utils import six from django.utils.safestring import mark_safe from ..utils import render, setup @@ -16,3 +24,86 @@ class FloatformatTests(SimpleTestCase): def test_floatformat02(self): output = render('floatformat02', {"a": "1.42", "b": mark_safe("1.42")}) self.assertEqual(output, "1.4 1.4") + + +class FunctionTests(SimpleTestCase): + + def test_inputs(self): + self.assertEqual(floatformat(7.7), '7.7') + self.assertEqual(floatformat(7.0), '7') + self.assertEqual(floatformat(0.7), '0.7') + self.assertEqual(floatformat(0.07), '0.1') + self.assertEqual(floatformat(0.007), '0.0') + self.assertEqual(floatformat(0.0), '0') + self.assertEqual(floatformat(7.7, 3), '7.700') + self.assertEqual(floatformat(6.000000, 3), '6.000') + self.assertEqual(floatformat(6.200000, 3), '6.200') + self.assertEqual(floatformat(6.200000, -3), '6.200') + self.assertEqual(floatformat(13.1031, -3), '13.103') + self.assertEqual(floatformat(11.1197, -2), '11.12') + self.assertEqual(floatformat(11.0000, -2), '11') + self.assertEqual(floatformat(11.000001, -2), '11.00') + self.assertEqual(floatformat(8.2798, 3), '8.280') + self.assertEqual(floatformat(5555.555, 2), '5555.56') + self.assertEqual(floatformat(001.3000, 2), '1.30') + self.assertEqual(floatformat(0.12345, 2), '0.12') + self.assertEqual(floatformat(Decimal('555.555'), 2), '555.56') + self.assertEqual(floatformat(Decimal('09.000')), '9') + self.assertEqual(floatformat('foo'), '') + self.assertEqual(floatformat(13.1031, 'bar'), '13.1031') + self.assertEqual(floatformat(18.125, 2), '18.13') + self.assertEqual(floatformat('foo', 'bar'), '') + self.assertEqual(floatformat('¿Cómo esta usted?'), '') + self.assertEqual(floatformat(None), '') + + def test_zero_values(self): + """ + Check that we're not converting to scientific notation. + """ + self.assertEqual(floatformat(0, 6), '0.000000') + self.assertEqual(floatformat(0, 7), '0.0000000') + self.assertEqual(floatformat(0, 10), '0.0000000000') + self.assertEqual(floatformat(0.000000000000000000015, 20), + '0.00000000000000000002') + + def test_infinity(self): + pos_inf = float(1e30000) + self.assertEqual(floatformat(pos_inf), six.text_type(pos_inf)) + + neg_inf = float(-1e30000) + self.assertEqual(floatformat(neg_inf), six.text_type(neg_inf)) + + nan = pos_inf / pos_inf + self.assertEqual(floatformat(nan), six.text_type(nan)) + + def test_float_dunder_method(self): + class FloatWrapper(object): + def __init__(self, value): + self.value = value + + def __float__(self): + return self.value + + self.assertEqual(floatformat(FloatWrapper(11.000001), -2), '11.00') + + def test_low_decimal_precision(self): + """ + #15789 + """ + with localcontext() as ctx: + ctx.prec = 2 + self.assertEqual(floatformat(1.2345, 2), '1.23') + self.assertEqual(floatformat(15.2042, -3), '15.204') + self.assertEqual(floatformat(1.2345, '2'), '1.23') + self.assertEqual(floatformat(15.2042, '-3'), '15.204') + self.assertEqual(floatformat(Decimal('1.2345'), 2), '1.23') + self.assertEqual(floatformat(Decimal('15.2042'), -3), '15.204') + + def test_many_zeroes(self): + self.assertEqual(floatformat(1.00000000000000015, 16), '1.0000000000000002') + + if six.PY2: + # The above test fails because of Python 2's float handling. Floats + # with many zeroes after the decimal point should be passed in as + # another type such as unicode or Decimal. + test_many_zeroes = expectedFailure(test_many_zeroes) diff --git a/tests/template_tests/filter_tests/test_force_escape.py b/tests/template_tests/filter_tests/test_force_escape.py index 1217e07793..b231d8e374 100644 --- a/tests/template_tests/filter_tests/test_force_escape.py +++ b/tests/template_tests/filter_tests/test_force_escape.py @@ -1,4 +1,9 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.template.defaultfilters import force_escape from django.test import SimpleTestCase +from django.utils.safestring import SafeData from ..utils import render, setup @@ -50,3 +55,17 @@ class ForceEscapeTests(SimpleTestCase): def test_force_escape08(self): output = render('force-escape08', {"a": "x&y"}) self.assertEqual(output, "x&y") + + +class FunctionTests(SimpleTestCase): + + def test_escape(self): + escaped = force_escape('<some html & special characters > here') + self.assertEqual(escaped, '<some html & special characters > here') + self.assertIsInstance(escaped, SafeData) + + def test_unicode(self): + self.assertEqual( + force_escape('<some html & special characters > here ĐÅ€£'), + '<some html & special characters > here \u0110\xc5\u20ac\xa3', + ) diff --git a/tests/template_tests/filter_tests/test_get_digit.py b/tests/template_tests/filter_tests/test_get_digit.py new file mode 100644 index 0000000000..1382408715 --- /dev/null +++ b/tests/template_tests/filter_tests/test_get_digit.py @@ -0,0 +1,15 @@ +from django.template.defaultfilters import get_digit +from django.test import SimpleTestCase + + +class FunctionTests(SimpleTestCase): + + def test_values(self): + self.assertEqual(get_digit(123, 1), 3) + self.assertEqual(get_digit(123, 2), 2) + self.assertEqual(get_digit(123, 3), 1) + self.assertEqual(get_digit(123, 4), 0) + self.assertEqual(get_digit(123, 0), 123) + + def test_string(self): + self.assertEqual(get_digit('xyz', 0), 'xyz') diff --git a/tests/template_tests/filter_tests/test_iriencode.py b/tests/template_tests/filter_tests/test_iriencode.py index b06f05b909..c44c54eb6a 100644 --- a/tests/template_tests/filter_tests/test_iriencode.py +++ b/tests/template_tests/filter_tests/test_iriencode.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.template.defaultfilters import iriencode, urlencode from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -28,3 +32,12 @@ class IriencodeTests(SimpleTestCase): def test_iriencode04(self): output = render('iriencode04', {'url': mark_safe('?test=1&me=2')}) self.assertEqual(output, '?test=1&me=2') + + +class FunctionTests(SimpleTestCase): + + def test_unicode(self): + self.assertEqual(iriencode('S\xf8r-Tr\xf8ndelag'), 'S%C3%B8r-Tr%C3%B8ndelag') + + def test_urlencoded(self): + self.assertEqual(iriencode(urlencode('fran\xe7ois & jill')), 'fran%C3%A7ois%20%26%20jill') diff --git a/tests/template_tests/filter_tests/test_join.py b/tests/template_tests/filter_tests/test_join.py index a6c93e7332..87a00d6d18 100644 --- a/tests/template_tests/filter_tests/test_join.py +++ b/tests/template_tests/filter_tests/test_join.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import join from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -47,3 +48,9 @@ class JoinTests(SimpleTestCase): def test_join08(self): output = render('join08', {'a': ['Alpha', 'Beta & me'], 'var': mark_safe(' & ')}) self.assertEqual(output, 'alpha & beta & me') + + +class FunctionTests(SimpleTestCase): + + def test_list(self): + self.assertEqual(join([0, 1, 2], 'glue'), '0glue1glue2') diff --git a/tests/template_tests/filter_tests/test_length.py b/tests/template_tests/filter_tests/test_length.py index f81912ce03..cd605aa785 100644 --- a/tests/template_tests/filter_tests/test_length.py +++ b/tests/template_tests/filter_tests/test_length.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import length from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -41,3 +42,15 @@ class LengthTests(SimpleTestCase): def test_length07(self): output = render('length07', {'None': None}) self.assertEqual(output, '0') + + +class FunctionTests(SimpleTestCase): + + def test_string(self): + self.assertEqual(length('1234'), 4) + + def test_safestring(self): + self.assertEqual(length(mark_safe('1234')), 4) + + def test_list(self): + self.assertEqual(length([1, 2, 3, 4]), 4) diff --git a/tests/template_tests/filter_tests/test_length_is.py b/tests/template_tests/filter_tests/test_length_is.py index 5d67d453d7..d0f547a3c2 100644 --- a/tests/template_tests/filter_tests/test_length_is.py +++ b/tests/template_tests/filter_tests/test_length_is.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import length_is from django.test import SimpleTestCase from ..utils import render, setup @@ -61,3 +62,14 @@ class LengthIsTests(SimpleTestCase): def test_length_is11(self): output = render('length_is11', {'none': None}) self.assertEqual(output, '') + + +class FunctionTests(SimpleTestCase): + + def test_empty_list(self): + self.assertEqual(length_is([], 0), True) + self.assertEqual(length_is([], 1), False) + + def test_string(self): + self.assertEqual(length_is('a', 1), True) + self.assertEqual(length_is('a', 10), False) diff --git a/tests/template_tests/filter_tests/test_linebreaks.py b/tests/template_tests/filter_tests/test_linebreaks.py index 924fc0aefa..852617ba7f 100644 --- a/tests/template_tests/filter_tests/test_linebreaks.py +++ b/tests/template_tests/filter_tests/test_linebreaks.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import linebreaks_filter from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -20,3 +21,21 @@ class LinebreaksTests(SimpleTestCase): 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>") + + +class FunctionTests(SimpleTestCase): + + def test_line(self): + self.assertEqual(linebreaks_filter('line 1'), '<p>line 1</p>') + + def test_newline(self): + self.assertEqual(linebreaks_filter('line 1\nline 2'), '<p>line 1<br />line 2</p>') + + def test_carriage(self): + self.assertEqual(linebreaks_filter('line 1\rline 2'), '<p>line 1<br />line 2</p>') + + def test_carriage_newline(self): + self.assertEqual(linebreaks_filter('line 1\r\nline 2'), '<p>line 1<br />line 2</p>') + + def test_non_string_input(self): + self.assertEqual(linebreaks_filter(123), '<p>123</p>') diff --git a/tests/template_tests/filter_tests/test_linebreaksbr.py b/tests/template_tests/filter_tests/test_linebreaksbr.py index c65b0973fb..39905d7fb0 100644 --- a/tests/template_tests/filter_tests/test_linebreaksbr.py +++ b/tests/template_tests/filter_tests/test_linebreaksbr.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import linebreaksbr from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -20,3 +21,18 @@ class LinebreaksbrTests(SimpleTestCase): def test_linebreaksbr02(self): output = render('linebreaksbr02', {"a": "x&\ny", "b": mark_safe("x&\ny")}) self.assertEqual(output, "x&<br />y x&<br />y") + + +class FunctionTests(SimpleTestCase): + + def test_newline(self): + self.assertEqual(linebreaksbr('line 1\nline 2'), 'line 1<br />line 2') + + def test_carriage(self): + self.assertEqual(linebreaksbr('line 1\rline 2'), 'line 1<br />line 2') + + def test_carriage_newline(self): + self.assertEqual(linebreaksbr('line 1\r\nline 2'), 'line 1<br />line 2') + + def test_non_string_input(self): + self.assertEqual(linebreaksbr(123), '123') diff --git a/tests/template_tests/filter_tests/test_linenumbers.py b/tests/template_tests/filter_tests/test_linenumbers.py index d74ce5dcfe..d7e93d9429 100644 --- a/tests/template_tests/filter_tests/test_linenumbers.py +++ b/tests/template_tests/filter_tests/test_linenumbers.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import linenumbers from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -28,3 +29,18 @@ class LinenumbersTests(SimpleTestCase): ) self.assertEqual(output, '1. one\n2. <two>\n3. three ' '1. one\n2. <two>\n3. three') + + +class FunctionTests(SimpleTestCase): + + def test_linenumbers(self): + self.assertEqual(linenumbers('line 1\nline 2'), '1. line 1\n2. line 2') + + def test_linenumbers2(self): + self.assertEqual( + linenumbers('\n'.join(['x'] * 10)), + '01. x\n02. x\n03. x\n04. x\n05. x\n06. x\n07. x\n08. x\n09. x\n10. x', + ) + + def test_non_string_input(self): + self.assertEqual(linenumbers(123), '1. 123') diff --git a/tests/template_tests/filter_tests/test_ljust.py b/tests/template_tests/filter_tests/test_ljust.py index e5b0f84a8f..a13764d328 100644 --- a/tests/template_tests/filter_tests/test_ljust.py +++ b/tests/template_tests/filter_tests/test_ljust.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import ljust from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -15,3 +16,16 @@ class LjustTests(SimpleTestCase): def test_ljust02(self): output = render('ljust02', {"a": "a&b", "b": mark_safe("a&b")}) self.assertEqual(output, ".a&b . .a&b .") + + +class FunctionTests(SimpleTestCase): + + def test_ljust(self): + self.assertEqual(ljust('test', 10), 'test ') + self.assertEqual(ljust('test', 3), 'test') + + def test_less_than_string_length(self): + self.assertEqual(ljust('test', 3), 'test') + + def test_non_string_input(self): + self.assertEqual(ljust(123, 4), '123 ') diff --git a/tests/template_tests/filter_tests/test_lower.py b/tests/template_tests/filter_tests/test_lower.py index 1443386062..c6e792bc32 100644 --- a/tests/template_tests/filter_tests/test_lower.py +++ b/tests/template_tests/filter_tests/test_lower.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.template.defaultfilters import lower from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -15,3 +19,16 @@ class LowerTests(SimpleTestCase): def test_lower02(self): output = render('lower02', {"a": "Apple & banana", "b": mark_safe("Apple & banana")}) self.assertEqual(output, "apple & banana apple & banana") + + +class FunctionTests(SimpleTestCase): + + def test_lower(self): + self.assertEqual(lower('TEST'), 'test') + + def test_unicode(self): + # uppercase E umlaut + self.assertEqual(lower('\xcb'), '\xeb') + + def test_non_string_input(self): + self.assertEqual(lower(123), '123') diff --git a/tests/template_tests/filter_tests/test_make_list.py b/tests/template_tests/filter_tests/test_make_list.py index 42cfbfaf56..638893cafe 100644 --- a/tests/template_tests/filter_tests/test_make_list.py +++ b/tests/template_tests/filter_tests/test_make_list.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import make_list from django.test import SimpleTestCase from django.test.utils import str_prefix from django.utils.safestring import mark_safe @@ -31,3 +32,12 @@ class MakeListTests(SimpleTestCase): def test_make_list04(self): output = render('make_list04', {"a": mark_safe("&")}) self.assertEqual(output, str_prefix("[%(_)s'&']")) + + +class FunctionTests(SimpleTestCase): + + def test_string(self): + self.assertEqual(make_list('abc'), ['a', 'b', 'c']) + + def test_integer(self): + self.assertEqual(make_list(1234), ['1', '2', '3', '4']) diff --git a/tests/template_tests/filter_tests/test_phone2numeric.py b/tests/template_tests/filter_tests/test_phone2numeric.py index 8b899d70a3..d684ed9621 100644 --- a/tests/template_tests/filter_tests/test_phone2numeric.py +++ b/tests/template_tests/filter_tests/test_phone2numeric.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import phone2numeric_filter from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -33,3 +34,9 @@ class Phone2numericTests(SimpleTestCase): output, '469 729672225-5867464 37647 226 53835 749 747833 49662787!' ) + + +class FunctionTests(SimpleTestCase): + + def test_phone2numeric(self): + self.assertEqual(phone2numeric_filter('0800 flowers'), '0800 3569377') diff --git a/tests/template_tests/filter_tests/test_pluralize.py b/tests/template_tests/filter_tests/test_pluralize.py new file mode 100644 index 0000000000..16371da8be --- /dev/null +++ b/tests/template_tests/filter_tests/test_pluralize.py @@ -0,0 +1,35 @@ +from decimal import Decimal + +from django.template.defaultfilters import pluralize +from django.test import SimpleTestCase + + +class FunctionTests(SimpleTestCase): + + def test_integers(self): + self.assertEqual(pluralize(1), '') + self.assertEqual(pluralize(0), 's') + self.assertEqual(pluralize(2), 's') + + def test_floats(self): + self.assertEqual(pluralize(0.5), 's') + self.assertEqual(pluralize(1.5), 's') + + def test_decimals(self): + self.assertEqual(pluralize(Decimal(1)), '') + self.assertEqual(pluralize(Decimal(0)), 's') + self.assertEqual(pluralize(Decimal(2)), 's') + + def test_lists(self): + self.assertEqual(pluralize([1]), '') + self.assertEqual(pluralize([]), 's') + self.assertEqual(pluralize([1, 2, 3]), 's') + + def test_suffixes(self): + self.assertEqual(pluralize(1, 'es'), '') + self.assertEqual(pluralize(0, 'es'), 'es') + self.assertEqual(pluralize(2, 'es'), 'es') + self.assertEqual(pluralize(1, 'y,ies'), 'y') + self.assertEqual(pluralize(0, 'y,ies'), 'ies') + self.assertEqual(pluralize(2, 'y,ies'), 'ies') + self.assertEqual(pluralize(0, 'y,ies,error'), '') diff --git a/tests/template_tests/filter_tests/test_removetags.py b/tests/template_tests/filter_tests/test_removetags.py index 7abe810fd8..3e8842a48d 100644 --- a/tests/template_tests/filter_tests/test_removetags.py +++ b/tests/template_tests/filter_tests/test_removetags.py @@ -1,5 +1,6 @@ import warnings +from django.template.defaultfilters import removetags from django.test import SimpleTestCase from django.utils.deprecation import RemovedInDjango20Warning from django.utils.safestring import mark_safe @@ -35,3 +36,22 @@ class RemovetagsTests(SimpleTestCase): }, ) self.assertEqual(output, 'x <p>y</p> x <p>y</p>') + + +class FunctionTests(SimpleTestCase): + + def test_removetags(self): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', RemovedInDjango20Warning) + self.assertEqual( + removetags( + 'some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags', + 'script img', + ), + 'some <b>html</b> with alert("You smell") disallowed tags', + ) + + def test_non_string_input(self): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', RemovedInDjango20Warning) + self.assertEqual(removetags(123, 'a'), '123') diff --git a/tests/template_tests/filter_tests/test_rjust.py b/tests/template_tests/filter_tests/test_rjust.py index e20ce36706..38e8ba0e59 100644 --- a/tests/template_tests/filter_tests/test_rjust.py +++ b/tests/template_tests/filter_tests/test_rjust.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import rjust from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -15,3 +16,15 @@ class RjustTests(SimpleTestCase): def test_rjust02(self): output = render('rjust02', {"a": "a&b", "b": mark_safe("a&b")}) self.assertEqual(output, ". a&b. . a&b.") + + +class FunctionTests(SimpleTestCase): + + def test_rjust(self): + self.assertEqual(rjust('test', 10), ' test') + + def test_less_than_string_length(self): + self.assertEqual(rjust('test', 3), 'test') + + def test_non_string_input(self): + self.assertEqual(rjust(123, 4), ' 123') diff --git a/tests/template_tests/filter_tests/test_slice.py b/tests/template_tests/filter_tests/test_slice.py index c66f1f2241..5ceee207b3 100644 --- a/tests/template_tests/filter_tests/test_slice.py +++ b/tests/template_tests/filter_tests/test_slice.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import slice_filter from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -15,3 +16,24 @@ class SliceTests(SimpleTestCase): def test_slice02(self): output = render('slice02', {'a': 'a&b', 'b': mark_safe('a&b')}) self.assertEqual(output, '&b &b') + + +class FunctionTests(SimpleTestCase): + + def test_zero_length(self): + self.assertEqual(slice_filter('abcdefg', '0'), '') + + def test_index(self): + self.assertEqual(slice_filter('abcdefg', '1'), 'a') + + def test_negative_index(self): + self.assertEqual(slice_filter('abcdefg', '-1'), 'abcdef') + + def test_range(self): + self.assertEqual(slice_filter('abcdefg', '1:2'), 'b') + + def test_range_multiple(self): + self.assertEqual(slice_filter('abcdefg', '1:3'), 'bc') + + def test_range_step(self): + self.assertEqual(slice_filter('abcdefg', '0::2'), 'aceg') diff --git a/tests/template_tests/filter_tests/test_slugify.py b/tests/template_tests/filter_tests/test_slugify.py index d18502b27c..7761547714 100644 --- a/tests/template_tests/filter_tests/test_slugify.py +++ b/tests/template_tests/filter_tests/test_slugify.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.template.defaultfilters import slugify from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -19,3 +23,21 @@ class SlugifyTests(SimpleTestCase): def test_slugify02(self): output = render('slugify02', {'a': 'a & b', 'b': mark_safe('a & b')}) self.assertEqual(output, 'a-b a-amp-b') + + +class FunctionTests(SimpleTestCase): + + def test_slugify(self): + self.assertEqual( + slugify(' Jack & Jill like numbers 1,2,3 and 4 and silly characters ?%.$!/'), + 'jack-jill-like-numbers-123-and-4-and-silly-characters', + ) + + def test_unicode(self): + self.assertEqual( + slugify("Un \xe9l\xe9phant \xe0 l'or\xe9e du bois"), + 'un-elephant-a-loree-du-bois', + ) + + def test_non_string_input(self): + self.assertEqual(slugify(123), '123') diff --git a/tests/template_tests/filter_tests/test_stringformat.py b/tests/template_tests/filter_tests/test_stringformat.py index ef762f2e0a..b353920354 100644 --- a/tests/template_tests/filter_tests/test_stringformat.py +++ b/tests/template_tests/filter_tests/test_stringformat.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import stringformat from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -20,3 +21,12 @@ class StringformatTests(SimpleTestCase): def test_stringformat02(self): output = render('stringformat02', {'a': 'a<b', 'b': mark_safe('a<b')}) self.assertEqual(output, '. a<b. . a<b.') + + +class FunctionTests(SimpleTestCase): + + def test_format(self): + self.assertEqual(stringformat(1, '03d'), '001') + + def test_invalid(self): + self.assertEqual(stringformat(1, 'z'), '') diff --git a/tests/template_tests/filter_tests/test_striptags.py b/tests/template_tests/filter_tests/test_striptags.py index e2e60c2cab..f45a48cdde 100644 --- a/tests/template_tests/filter_tests/test_striptags.py +++ b/tests/template_tests/filter_tests/test_striptags.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import striptags from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -27,3 +28,15 @@ class StriptagsTests(SimpleTestCase): }, ) self.assertEqual(output, 'x y x y') + + +class FunctionTests(SimpleTestCase): + + def test_strip(self): + self.assertEqual( + striptags('some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags'), + 'some html with alert("You smell") disallowed tags', + ) + + def test_non_string_input(self): + self.assertEqual(striptags(123), '123') diff --git a/tests/template_tests/filter_tests/test_time.py b/tests/template_tests/filter_tests/test_time.py index a7fa5026cd..5f6373e4f6 100644 --- a/tests/template_tests/filter_tests/test_time.py +++ b/tests/template_tests/filter_tests/test_time.py @@ -1,5 +1,7 @@ from datetime import time +from django.template.defaultfilters import time as time_filter +from django.test import SimpleTestCase from django.utils import timezone from .timezone_utils import TimezoneTestCase @@ -40,3 +42,10 @@ class TimeTests(TimezoneTestCase): def test_time06(self): output = render('time06', {'obj': 'non-datetime-value'}) self.assertEqual(output, '') + + +class FunctionTests(SimpleTestCase): + + def test_inputs(self): + self.assertEqual(time_filter(time(13), 'h'), '01') + self.assertEqual(time_filter(time(0), 'h'), '12') diff --git a/tests/template_tests/filter_tests/test_timesince.py b/tests/template_tests/filter_tests/test_timesince.py index 999358a7f2..12349e6d50 100644 --- a/tests/template_tests/filter_tests/test_timesince.py +++ b/tests/template_tests/filter_tests/test_timesince.py @@ -2,6 +2,8 @@ from __future__ import unicode_literals from datetime import datetime, timedelta +from django.template.defaultfilters import timesince_filter +from django.test import SimpleTestCase from django.test.utils import requires_tz_support from .timezone_utils import TimezoneTestCase @@ -116,3 +118,12 @@ class TimesinceTests(TimezoneTestCase): def test_timesince18(self): output = render('timesince18', {'a': self.today, 'b': self.today + timedelta(hours=24)}) self.assertEqual(output, '1\xa0day') + + +class FunctionTests(SimpleTestCase): + + def test_since_now(self): + self.assertEqual(timesince_filter(datetime.now() - timedelta(1)), '1\xa0day') + + def test_explicit_date(self): + self.assertEqual(timesince_filter(datetime(2005, 12, 29), datetime(2005, 12, 30)), '1\xa0day') diff --git a/tests/template_tests/filter_tests/test_timeuntil.py b/tests/template_tests/filter_tests/test_timeuntil.py index 1662bb605c..a723b34e5e 100644 --- a/tests/template_tests/filter_tests/test_timeuntil.py +++ b/tests/template_tests/filter_tests/test_timeuntil.py @@ -2,6 +2,8 @@ from __future__ import unicode_literals from datetime import datetime, timedelta +from django.template.defaultfilters import timeuntil_filter +from django.test import SimpleTestCase from django.test.utils import requires_tz_support from .timezone_utils import TimezoneTestCase @@ -92,3 +94,12 @@ class TimeuntilTests(TimezoneTestCase): def test_timeuntil14(self): output = render('timeuntil14', {'a': self.today, 'b': self.today - timedelta(hours=24)}) self.assertEqual(output, '1\xa0day') + + +class FunctionTests(SimpleTestCase): + + def test_until_now(self): + self.assertEqual(timeuntil_filter(datetime.now() + timedelta(1, 1)), '1\xa0day') + + def test_explicit_date(self): + self.assertEqual(timeuntil_filter(datetime(2005, 12, 30), datetime(2005, 12, 29)), '1\xa0day') diff --git a/tests/template_tests/filter_tests/test_title.py b/tests/template_tests/filter_tests/test_title.py index fc14330b67..67aa910733 100644 --- a/tests/template_tests/filter_tests/test_title.py +++ b/tests/template_tests/filter_tests/test_title.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.template.defaultfilters import title from django.test import SimpleTestCase from ..utils import render, setup @@ -14,3 +18,15 @@ class TitleTests(SimpleTestCase): def test_title2(self): output = render('title2', {'a': '555 WEST 53RD STREET'}) self.assertEqual(output, '555 West 53rd Street') + + +class FunctionTests(SimpleTestCase): + + def test_title(self): + self.assertEqual(title('a nice title, isn\'t it?'), "A Nice Title, Isn't It?") + + def test_unicode(self): + self.assertEqual(title('discoth\xe8que'), 'Discoth\xe8que') + + def test_non_string_input(self): + self.assertEqual(title(123), '123') diff --git a/tests/template_tests/filter_tests/test_truncatechars_html.py b/tests/template_tests/filter_tests/test_truncatechars_html.py new file mode 100644 index 0000000000..cf2623d740 --- /dev/null +++ b/tests/template_tests/filter_tests/test_truncatechars_html.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.template.defaultfilters import truncatechars_html +from django.test import SimpleTestCase + + +class FunctionTests(SimpleTestCase): + + def test_truncate_zero(self): + self.assertEqual(truncatechars_html('<p>one <a href="#">two - three <br>four</a> five</p>', 0), '...') + + def test_truncate(self): + self.assertEqual( + truncatechars_html('<p>one <a href="#">two - three <br>four</a> five</p>', 6), + '<p>one...</p>', + ) + + def test_truncate2(self): + self.assertEqual( + truncatechars_html('<p>one <a href="#">two - three <br>four</a> five</p>', 11), + '<p>one <a href="#">two ...</a></p>', + ) + + def test_truncate3(self): + self.assertEqual( + truncatechars_html('<p>one <a href="#">two - three <br>four</a> five</p>', 100), + '<p>one <a href="#">two - three <br>four</a> five</p>', + ) + + def test_truncate_unicode(self): + self.assertEqual(truncatechars_html('<b>\xc5ngstr\xf6m</b> was here', 5), '<b>\xc5n...</b>') + + def test_truncate_something(self): + self.assertEqual(truncatechars_html('a<b>b</b>c', 3), 'a<b>b</b>c') diff --git a/tests/template_tests/filter_tests/test_truncatewords.py b/tests/template_tests/filter_tests/test_truncatewords.py index 6f64d439f3..f9a3647085 100644 --- a/tests/template_tests/filter_tests/test_truncatewords.py +++ b/tests/template_tests/filter_tests/test_truncatewords.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import truncatewords from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -16,3 +17,30 @@ class TruncatewordsTests(SimpleTestCase): def test_truncatewords02(self): output = render('truncatewords02', {'a': 'alpha & bravo', 'b': mark_safe('alpha & bravo')}) self.assertEqual(output, 'alpha & ... alpha & ...') + + +class FunctionTests(SimpleTestCase): + + def test_truncate(self): + self.assertEqual(truncatewords('A sentence with a few words in it', 1), 'A ...') + + def test_truncate2(self): + self.assertEqual( + truncatewords('A sentence with a few words in it', 5), + 'A sentence with a few ...', + ) + + def test_overtruncate(self): + self.assertEqual( + truncatewords('A sentence with a few words in it', 100), + 'A sentence with a few words in it', + ) + + def test_invalid_number(self): + self.assertEqual( + truncatewords('A sentence with a few words in it', 'not a number'), + 'A sentence with a few words in it', + ) + + def test_non_string_input(self): + self.assertEqual(truncatewords(123, 2), '123') diff --git a/tests/template_tests/filter_tests/test_truncatewords_html.py b/tests/template_tests/filter_tests/test_truncatewords_html.py new file mode 100644 index 0000000000..aec2abf2d4 --- /dev/null +++ b/tests/template_tests/filter_tests/test_truncatewords_html.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.template.defaultfilters import truncatewords_html +from django.test import SimpleTestCase + + +class FunctionTests(SimpleTestCase): + + def test_truncate_zero(self): + self.assertEqual(truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 0), '') + + def test_truncate(self): + self.assertEqual( + truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 2), + '<p>one <a href="#">two ...</a></p>', + ) + + def test_truncate2(self): + self.assertEqual( + truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 4), + '<p>one <a href="#">two - three <br>four ...</a></p>', + ) + + def test_truncate3(self): + self.assertEqual( + truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 5), + '<p>one <a href="#">two - three <br>four</a> five</p>', + ) + + def test_truncate4(self): + self.assertEqual( + truncatewords_html('<p>one <a href="#">two - three <br>four</a> five</p>', 100), + '<p>one <a href="#">two - three <br>four</a> five</p>', + ) + + def test_truncate_unicode(self): + self.assertEqual(truncatewords_html('\xc5ngstr\xf6m was here', 1), '\xc5ngstr\xf6m ...') + + def test_truncate_complex(self): + self.assertEqual( + truncatewords_html('<i>Buenos días! ¿Cómo está?</i>', 3), + '<i>Buenos días! ¿Cómo ...</i>', + ) diff --git a/tests/template_tests/filter_tests/test_unordered_list.py b/tests/template_tests/filter_tests/test_unordered_list.py index 73eee2fb34..8575551b08 100644 --- a/tests/template_tests/filter_tests/test_unordered_list.py +++ b/tests/template_tests/filter_tests/test_unordered_list.py @@ -1,7 +1,9 @@ import warnings +from django.template.defaultfilters import unordered_list from django.test import SimpleTestCase from django.utils.deprecation import RemovedInDjango20Warning +from django.utils.encoding import python_2_unicode_compatible from django.utils.safestring import mark_safe from ..utils import render, setup @@ -73,3 +75,83 @@ class DeprecatedUnorderedListSyntaxTests(SimpleTestCase): 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>') + + +class FunctionTests(SimpleTestCase): + + def test_list(self): + self.assertEqual(unordered_list(['item 1', 'item 2']), '\t<li>item 1</li>\n\t<li>item 2</li>') + + def test_nested(self): + self.assertEqual( + unordered_list(['item 1', ['item 1.1']]), + '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>', + ) + + def test_nested2(self): + self.assertEqual( + unordered_list(['item 1', ['item 1.1', 'item1.2'], 'item 2']), + '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t\t<li>item1.2' + '</li>\n\t</ul>\n\t</li>\n\t<li>item 2</li>', + ) + + def test_nested_multiple(self): + self.assertEqual( + unordered_list(['item 1', ['item 1.1', ['item 1.1.1', ['item 1.1.1.1']]]]), + '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1\n\t\t<ul>\n\t\t\t<li>' + 'item 1.1.1\n\t\t\t<ul>\n\t\t\t\t<li>item 1.1.1.1</li>\n\t\t\t' + '</ul>\n\t\t\t</li>\n\t\t</ul>\n\t\t</li>\n\t</ul>\n\t</li>', + ) + + def test_nested_multiple2(self): + self.assertEqual( + unordered_list(['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]), + '\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>' + 'Lawrence</li>\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>' + '\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>', + ) + + def test_ulitem(self): + @python_2_unicode_compatible + class ULItem(object): + def __init__(self, title): + self.title = title + + def __str__(self): + return 'ulitem-%s' % str(self.title) + + a = ULItem('a') + b = ULItem('b') + self.assertEqual(unordered_list([a, b]), '\t<li>ulitem-a</li>\n\t<li>ulitem-b</li>') + + def item_generator(): + yield a + yield b + + self.assertEqual(unordered_list(item_generator()), '\t<li>ulitem-a</li>\n\t<li>ulitem-b</li>') + + def test_legacy(self): + """ + Old format for unordered lists should still work + """ + with warnings.catch_warnings(): + warnings.simplefilter('ignore', RemovedInDjango20Warning) + + self.assertEqual(unordered_list(['item 1', []]), '\t<li>item 1</li>') + + self.assertEqual( + unordered_list(['item 1', [['item 1.1', []]]]), + '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>', + ) + + self.assertEqual( + unordered_list(['item 1', [['item 1.1', []], + ['item 1.2', []]]]), '\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1' + '</li>\n\t\t<li>item 1.2</li>\n\t</ul>\n\t</li>', + ) + + self.assertEqual( + unordered_list(['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]), + '\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>Lawrence</li>' + '\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>', + ) diff --git a/tests/template_tests/filter_tests/test_upper.py b/tests/template_tests/filter_tests/test_upper.py index b1fa5fcc06..b1708ce524 100644 --- a/tests/template_tests/filter_tests/test_upper.py +++ b/tests/template_tests/filter_tests/test_upper.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.template.defaultfilters import upper from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -19,3 +23,16 @@ class UpperTests(SimpleTestCase): def test_upper02(self): output = render('upper02', {'a': 'a & b', 'b': mark_safe('a & b')}) self.assertEqual(output, 'A & B A &AMP; B') + + +class FunctionTests(SimpleTestCase): + + def test_upper(self): + self.assertEqual(upper('Mixed case input'), 'MIXED CASE INPUT') + + def test_unicode(self): + # lowercase e umlaut + self.assertEqual(upper('\xeb'), '\xcb') + + def test_non_string_input(self): + self.assertEqual(upper(123), '123') diff --git a/tests/template_tests/filter_tests/test_urlencode.py b/tests/template_tests/filter_tests/test_urlencode.py index ea68188c15..eca2b3f405 100644 --- a/tests/template_tests/filter_tests/test_urlencode.py +++ b/tests/template_tests/filter_tests/test_urlencode.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.template.defaultfilters import urlencode from django.test import SimpleTestCase from ..utils import render, setup @@ -14,3 +18,12 @@ class UrlencodeTests(SimpleTestCase): def test_urlencode02(self): output = render('urlencode02', {'urlbit': 'escape/slash'}) self.assertEqual(output, '/test/escape%2Fslash/') + + +class FunctionTests(SimpleTestCase): + + def test_urlencode(self): + self.assertEqual(urlencode('fran\xe7ois & jill'), 'fran%C3%A7ois%20%26%20jill') + + def test_non_string_input(self): + self.assertEqual(urlencode(1), '1') diff --git a/tests/template_tests/filter_tests/test_urlize.py b/tests/template_tests/filter_tests/test_urlize.py index 567f38ee4b..ef23e5e5f0 100644 --- a/tests/template_tests/filter_tests/test_urlize.py +++ b/tests/template_tests/filter_tests/test_urlize.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.template.defaultfilters import urlize from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -68,3 +72,239 @@ class UrlizeTests(SimpleTestCase): output, 'Email me at <<a href="mailto:me@example.com">me@example.com</a>>', ) + + +class FunctionTests(SimpleTestCase): + + def test_urls(self): + self.assertEqual( + urlize('http://google.com'), + '<a href="http://google.com" rel="nofollow">http://google.com</a>', + ) + self.assertEqual( + urlize('http://google.com/'), + '<a href="http://google.com/" rel="nofollow">http://google.com/</a>', + ) + self.assertEqual( + urlize('www.google.com'), + '<a href="http://www.google.com" rel="nofollow">www.google.com</a>', + ) + self.assertEqual( + urlize('djangoproject.org'), + '<a href="http://djangoproject.org" rel="nofollow">djangoproject.org</a>', + ) + self.assertEqual( + urlize('djangoproject.org/'), + '<a href="http://djangoproject.org/" rel="nofollow">djangoproject.org/</a>', + ) + + def test_email(self): + self.assertEqual( + urlize('info@djangoproject.org'), + '<a href="mailto:info@djangoproject.org">info@djangoproject.org</a>', + ) + + def test_word_with_dot(self): + self.assertEqual(urlize('some.organization'), 'some.organization'), + + def test_https(self): + self.assertEqual( + urlize('https://google.com'), + '<a href="https://google.com" rel="nofollow">https://google.com</a>', + ) + + def test_quoting(self): + """ + #9655 - Check urlize doesn't overquote already quoted urls. The + teststring is the urlquoted version of 'http://hi.baidu.com/重新开始' + """ + self.assertEqual( + urlize('http://hi.baidu.com/%E9%87%8D%E6%96%B0%E5%BC%80%E5%A7%8B'), + '<a href="http://hi.baidu.com/%E9%87%8D%E6%96%B0%E5%BC%80%E5%A7%8B" rel="nofollow">' + 'http://hi.baidu.com/%E9%87%8D%E6%96%B0%E5%BC%80%E5%A7%8B</a>', + ) + + def test_urlencoded(self): + self.assertEqual( + urlize('www.mystore.com/30%OffCoupons!'), + '<a href="http://www.mystore.com/30%25OffCoupons" rel="nofollow">' + 'www.mystore.com/30%OffCoupons</a>!', + ) + self.assertEqual( + urlize('http://en.wikipedia.org/wiki/Caf%C3%A9'), + '<a href="http://en.wikipedia.org/wiki/Caf%C3%A9" rel="nofollow">' + 'http://en.wikipedia.org/wiki/Caf%C3%A9</a>', + ) + + def test_unicode(self): + self.assertEqual( + urlize('http://en.wikipedia.org/wiki/Café'), + '<a href="http://en.wikipedia.org/wiki/Caf%C3%A9" rel="nofollow">' + 'http://en.wikipedia.org/wiki/Café</a>', + ) + + def test_parenthesis(self): + """ + #11911 - Check urlize keeps balanced parentheses + """ + self.assertEqual( + urlize('http://en.wikipedia.org/wiki/Django_(web_framework)'), + '<a href="http://en.wikipedia.org/wiki/Django_(web_framework)" rel="nofollow">' + 'http://en.wikipedia.org/wiki/Django_(web_framework)</a>', + ) + self.assertEqual( + urlize('(see http://en.wikipedia.org/wiki/Django_(web_framework))'), + '(see <a href="http://en.wikipedia.org/wiki/Django_(web_framework)" rel="nofollow">' + 'http://en.wikipedia.org/wiki/Django_(web_framework)</a>)', + ) + + def test_nofollow(self): + """ + #12183 - Check urlize adds nofollow properly - see #12183 + """ + self.assertEqual( + urlize('foo@bar.com or www.bar.com'), + '<a href="mailto:foo@bar.com">foo@bar.com</a> or ' + '<a href="http://www.bar.com" rel="nofollow">www.bar.com</a>', + ) + + def test_idn(self): + """ + #13704 - Check urlize handles IDN correctly + """ + self.assertEqual(urlize('http://c✶.ws'), '<a href="http://xn--c-lgq.ws" rel="nofollow">http://c✶.ws</a>') + self.assertEqual(urlize('www.c✶.ws'), '<a href="http://www.xn--c-lgq.ws" rel="nofollow">www.c✶.ws</a>') + self.assertEqual(urlize('c✶.org'), '<a href="http://xn--c-lgq.org" rel="nofollow">c✶.org</a>') + self.assertEqual(urlize('info@c✶.org'), '<a href="mailto:info@xn--c-lgq.org">info@c✶.org</a>') + + def test_malformed(self): + """ + #16395 - Check urlize doesn't highlight malformed URIs + """ + self.assertEqual(urlize('http:///www.google.com'), 'http:///www.google.com') + self.assertEqual(urlize('http://.google.com'), 'http://.google.com') + self.assertEqual(urlize('http://@foo.com'), 'http://@foo.com') + + def test_tlds(self): + """ + #16656 - Check urlize accepts more TLDs + """ + self.assertEqual(urlize('usa.gov'), '<a href="http://usa.gov" rel="nofollow">usa.gov</a>') + + def test_invalid_email(self): + """ + #17592 - Check urlize don't crash on invalid email with dot-starting + domain + """ + self.assertEqual(urlize('email@.stream.ru'), 'email@.stream.ru') + + def test_uppercase(self): + """ + #18071 - Check urlize accepts uppercased URL schemes + """ + self.assertEqual( + urlize('HTTPS://github.com/'), + '<a href="https://github.com/" rel="nofollow">HTTPS://github.com/</a>', + ) + + def test_trailing_period(self): + """ + #18644 - Check urlize trims trailing period when followed by parenthesis + """ + self.assertEqual( + urlize('(Go to http://www.example.com/foo.)'), + '(Go to <a href="http://www.example.com/foo" rel="nofollow">http://www.example.com/foo</a>.)', + ) + + def test_brackets(self): + """ + #19070 - Check urlize handles brackets properly + """ + self.assertEqual( + urlize('[see www.example.com]'), + '[see <a href="http://www.example.com" rel="nofollow">www.example.com</a>]', + ) + self.assertEqual( + urlize('see test[at[example.com'), + 'see <a href="http://test[at[example.com" rel="nofollow">test[at[example.com</a>', + ) + self.assertEqual( + urlize('[http://168.192.0.1](http://168.192.0.1)'), + '[<a href="http://168.192.0.1](http://168.192.0.1)" rel="nofollow">' + 'http://168.192.0.1](http://168.192.0.1)</a>', + ) + + def test_ipv4(self): + self.assertEqual( + urlize('http://192.168.0.15/api/9'), + '<a href="http://192.168.0.15/api/9" rel="nofollow">http://192.168.0.15/api/9</a>', + ) + + def test_ipv6(self): + self.assertEqual( + urlize('http://[2001:db8:cafe::2]/api/9'), + '<a href="http://[2001:db8:cafe::2]/api/9" rel="nofollow">http://[2001:db8:cafe::2]/api/9</a>', + ) + + def test_quotation_marks(self): + """ + #20364 - Check urlize correctly include quotation marks in links + """ + self.assertEqual( + urlize('before "hi@example.com" afterwards'), + 'before "<a href="mailto:hi@example.com">hi@example.com</a>" afterwards', + ) + self.assertEqual( + urlize('before hi@example.com" afterwards'), + 'before <a href="mailto:hi@example.com">hi@example.com</a>" afterwards', + ) + self.assertEqual( + urlize('before "hi@example.com afterwards'), + 'before "<a href="mailto:hi@example.com">hi@example.com</a> afterwards', + ) + self.assertEqual( + urlize('before \'hi@example.com\' afterwards'), + 'before \'<a href="mailto:hi@example.com">hi@example.com</a>\' afterwards', + ) + self.assertEqual( + urlize('before hi@example.com\' afterwards'), + 'before <a href="mailto:hi@example.com">hi@example.com</a>\' afterwards', + ) + self.assertEqual( + urlize('before \'hi@example.com afterwards'), + 'before \'<a href="mailto:hi@example.com">hi@example.com</a> afterwards', + ) + + def test_quote_commas(self): + """ + #20364 - Check urlize copes with commas following URLs in quotes + """ + self.assertEqual( + urlize('Email us at "hi@example.com", or phone us at +xx.yy'), + 'Email us at "<a href="mailto:hi@example.com">hi@example.com</a>", or phone us at +xx.yy', + ) + + def test_exclamation_marks(self): + """ + #23715 - Check urlize correctly handles exclamation marks after TLDs + or query string + """ + self.assertEqual( + urlize('Go to djangoproject.com! and enjoy.'), + 'Go to <a href="http://djangoproject.com" rel="nofollow">djangoproject.com</a>! and enjoy.', + ) + self.assertEqual( + urlize('Search for google.com/?q=! and see.'), + 'Search for <a href="http://google.com/?q=" rel="nofollow">google.com/?q=</a>! and see.', + ) + self.assertEqual( + urlize('Search for google.com/?q=dj!`? and see.'), + 'Search for <a href="http://google.com/?q=dj%21%60%3F" rel="nofollow">google.com/?q=dj!`?</a> and see.', + ) + self.assertEqual( + urlize('Search for google.com/?q=dj!`?! and see.'), + 'Search for <a href="http://google.com/?q=dj%21%60%3F" rel="nofollow">google.com/?q=dj!`?</a>! and see.', + ) + + def test_non_string_input(self): + self.assertEqual(urlize(123), '123') diff --git a/tests/template_tests/filter_tests/test_urlizetrunc.py b/tests/template_tests/filter_tests/test_urlizetrunc.py index 19f5f1dcae..0190016372 100644 --- a/tests/template_tests/filter_tests/test_urlizetrunc.py +++ b/tests/template_tests/filter_tests/test_urlizetrunc.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import urlizetrunc from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -36,3 +37,44 @@ class UrlizetruncTests(SimpleTestCase): '"Unsafe" <a href="http://example.com/x=&y=" rel="nofollow">http:...</a> ' '"Safe" <a href="http://example.com?x=&y=" rel="nofollow">http:...</a>' ) + + +class FunctionTests(SimpleTestCase): + + def test_truncate(self): + uri = 'http://31characteruri.com/test/' + self.assertEqual(len(uri), 31) + + self.assertEqual( + urlizetrunc(uri, 31), + '<a href="http://31characteruri.com/test/" rel="nofollow">' + 'http://31characteruri.com/test/</a>', + ) + + self.assertEqual( + urlizetrunc(uri, 30), + '<a href="http://31characteruri.com/test/" rel="nofollow">' + 'http://31characteruri.com/t...</a>', + ) + + self.assertEqual( + urlizetrunc(uri, 2), + '<a href="http://31characteruri.com/test/"' + ' rel="nofollow">...</a>', + ) + + def test_overtruncate(self): + self.assertEqual( + urlizetrunc('http://short.com/', 20), '<a href=' + '"http://short.com/" rel="nofollow">http://short.com/</a>', + ) + + def test_query_string(self): + self.assertEqual( + urlizetrunc('http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=', 20), + '<a href="http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&' + 'meta=" rel="nofollow">http://www.google...</a>', + ) + + def test_non_string_input(self): + self.assertEqual(urlizetrunc(123, 1), '123') diff --git a/tests/template_tests/filter_tests/test_wordcount.py b/tests/template_tests/filter_tests/test_wordcount.py index 8c1e43f539..69a73b976a 100644 --- a/tests/template_tests/filter_tests/test_wordcount.py +++ b/tests/template_tests/filter_tests/test_wordcount.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import wordcount from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -15,3 +16,18 @@ class WordcountTests(SimpleTestCase): def test_wordcount02(self): output = render('wordcount02', {'a': 'a & b', 'b': mark_safe('a & b')}) self.assertEqual(output, '3 3') + + +class FunctionTests(SimpleTestCase): + + def test_empty_string(self): + self.assertEqual(wordcount(''), 0) + + def test_count_one(self): + self.assertEqual(wordcount('oneword'), 1) + + def test_count_multiple(self): + self.assertEqual(wordcount('lots of words'), 3) + + def test_non_string_input(self): + self.assertEqual(wordcount(123), 1) diff --git a/tests/template_tests/filter_tests/test_wordwrap.py b/tests/template_tests/filter_tests/test_wordwrap.py index 7b6489ca0f..808d9ee7a0 100644 --- a/tests/template_tests/filter_tests/test_wordwrap.py +++ b/tests/template_tests/filter_tests/test_wordwrap.py @@ -1,3 +1,4 @@ +from django.template.defaultfilters import wordwrap from django.test import SimpleTestCase from django.utils.safestring import mark_safe @@ -16,3 +17,27 @@ class WordwrapTests(SimpleTestCase): def test_wordwrap02(self): output = render('wordwrap02', {'a': 'a & b', 'b': mark_safe('a & b')}) self.assertEqual(output, 'a &\nb a &\nb') + + +class FunctionTests(SimpleTestCase): + + def test_wrap(self): + self.assertEqual( + wordwrap('this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14), + 'this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI\'m afraid', + ) + + def test_indent(self): + self.assertEqual( + wordwrap('this is a short paragraph of text.\n But this line should be indented', 14), + 'this is a\nshort\nparagraph of\ntext.\n But this\nline should be\nindented', + ) + + def test_indent2(self): + self.assertEqual( + wordwrap('this is a short paragraph of text.\n But this line should be indented', 15), + 'this is a short\nparagraph of\ntext.\n But this line\nshould be\nindented', + ) + + def test_non_string_input(self): + self.assertEqual(wordwrap(123, 2), '123') diff --git a/tests/template_tests/filter_tests/test_yesno.py b/tests/template_tests/filter_tests/test_yesno.py new file mode 100644 index 0000000000..43ea447caa --- /dev/null +++ b/tests/template_tests/filter_tests/test_yesno.py @@ -0,0 +1,26 @@ +from django.template.defaultfilters import yesno +from django.test import SimpleTestCase + + +class FunctionTests(SimpleTestCase): + + def test_true(self): + self.assertEqual(yesno(True), 'yes') + + def test_false(self): + self.assertEqual(yesno(False), 'no') + + def test_none(self): + self.assertEqual(yesno(None), 'maybe') + + def test_true_arguments(self): + self.assertEqual(yesno(True, 'certainly,get out of town,perhaps'), 'certainly') + + def test_false_arguments(self): + self.assertEqual(yesno(False, 'certainly,get out of town,perhaps'), 'get out of town') + + def test_none_two_arguments(self): + self.assertEqual(yesno(None, 'certainly,get out of town'), 'get out of town') + + def test_none_three_arguments(self): + self.assertEqual(yesno(None, 'certainly,get out of town,perhaps'), 'perhaps')