| Index: appengine/components/components/third_party/markupsafe/tests.py
|
| diff --git a/appengine/components/components/third_party/markupsafe/tests.py b/appengine/components/components/third_party/markupsafe/tests.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..6369936296e2905865b20c7f52170357bc870d8c
|
| --- /dev/null
|
| +++ b/appengine/components/components/third_party/markupsafe/tests.py
|
| @@ -0,0 +1,179 @@
|
| +# -*- coding: utf-8 -*-
|
| +import gc
|
| +import sys
|
| +import unittest
|
| +from markupsafe import Markup, escape, escape_silent
|
| +from markupsafe._compat import text_type
|
| +
|
| +
|
| +class MarkupTestCase(unittest.TestCase):
|
| +
|
| + def test_adding(self):
|
| + # adding two strings should escape the unsafe one
|
| + unsafe = '<script type="application/x-some-script">alert("foo");</script>'
|
| + safe = Markup('<em>username</em>')
|
| + assert unsafe + safe == text_type(escape(unsafe)) + text_type(safe)
|
| +
|
| + def test_string_interpolation(self):
|
| + # string interpolations are safe to use too
|
| + assert Markup('<em>%s</em>') % '<bad user>' == \
|
| + '<em><bad user></em>'
|
| + assert Markup('<em>%(username)s</em>') % {
|
| + 'username': '<bad user>'
|
| + } == '<em><bad user></em>'
|
| +
|
| + assert Markup('%i') % 3.14 == '3'
|
| + assert Markup('%.2f') % 3.14 == '3.14'
|
| +
|
| + def test_type_behavior(self):
|
| + # an escaped object is markup too
|
| + assert type(Markup('foo') + 'bar') is Markup
|
| +
|
| + # and it implements __html__ by returning itself
|
| + x = Markup("foo")
|
| + assert x.__html__() is x
|
| +
|
| + def test_html_interop(self):
|
| + # it also knows how to treat __html__ objects
|
| + class Foo(object):
|
| + def __html__(self):
|
| + return '<em>awesome</em>'
|
| + def __unicode__(self):
|
| + return 'awesome'
|
| + __str__ = __unicode__
|
| + assert Markup(Foo()) == '<em>awesome</em>'
|
| + assert Markup('<strong>%s</strong>') % Foo() == \
|
| + '<strong><em>awesome</em></strong>'
|
| +
|
| + def test_tuple_interpol(self):
|
| + self.assertEqual(Markup('<em>%s:%s</em>') % (
|
| + '<foo>',
|
| + '<bar>',
|
| + ), Markup(u'<em><foo>:<bar></em>'))
|
| +
|
| + def test_dict_interpol(self):
|
| + self.assertEqual(Markup('<em>%(foo)s</em>') % {
|
| + 'foo': '<foo>',
|
| + }, Markup(u'<em><foo></em>'))
|
| + self.assertEqual(Markup('<em>%(foo)s:%(bar)s</em>') % {
|
| + 'foo': '<foo>',
|
| + 'bar': '<bar>',
|
| + }, Markup(u'<em><foo>:<bar></em>'))
|
| +
|
| + def test_escaping(self):
|
| + # escaping and unescaping
|
| + assert escape('"<>&\'') == '"<>&''
|
| + assert Markup("<em>Foo & Bar</em>").striptags() == "Foo & Bar"
|
| + assert Markup("<test>").unescape() == "<test>"
|
| +
|
| + def test_formatting(self):
|
| + for actual, expected in (
|
| + (Markup('%i') % 3.14, '3'),
|
| + (Markup('%.2f') % 3.14159, '3.14'),
|
| + (Markup('%s %s %s') % ('<', 123, '>'), '< 123 >'),
|
| + (Markup('<em>{awesome}</em>').format(awesome='<awesome>'),
|
| + '<em><awesome></em>'),
|
| + (Markup('{0[1][bar]}').format([0, {'bar': '<bar/>'}]),
|
| + '<bar/>'),
|
| + (Markup('{0[1][bar]}').format([0, {'bar': Markup('<bar/>')}]),
|
| + '<bar/>')):
|
| + assert actual == expected, "%r should be %r!" % (actual, expected)
|
| +
|
| + # This is new in 2.7
|
| + if sys.version_info >= (2, 7):
|
| + def test_formatting_empty(self):
|
| + formatted = Markup('{}').format(0)
|
| + assert formatted == Markup('0')
|
| +
|
| + def test_custom_formatting(self):
|
| + class HasHTMLOnly(object):
|
| + def __html__(self):
|
| + return Markup('<foo>')
|
| +
|
| + class HasHTMLAndFormat(object):
|
| + def __html__(self):
|
| + return Markup('<foo>')
|
| + def __html_format__(self, spec):
|
| + return Markup('<FORMAT>')
|
| +
|
| + assert Markup('{0}').format(HasHTMLOnly()) == Markup('<foo>')
|
| + assert Markup('{0}').format(HasHTMLAndFormat()) == Markup('<FORMAT>')
|
| +
|
| + def test_complex_custom_formatting(self):
|
| + class User(object):
|
| + def __init__(self, id, username):
|
| + self.id = id
|
| + self.username = username
|
| + def __html_format__(self, format_spec):
|
| + if format_spec == 'link':
|
| + return Markup('<a href="/user/{0}">{1}</a>').format(
|
| + self.id,
|
| + self.__html__(),
|
| + )
|
| + elif format_spec:
|
| + raise ValueError('Invalid format spec')
|
| + return self.__html__()
|
| + def __html__(self):
|
| + return Markup('<span class=user>{0}</span>').format(self.username)
|
| +
|
| + user = User(1, 'foo')
|
| + assert Markup('<p>User: {0:link}').format(user) == \
|
| + Markup('<p>User: <a href="/user/1"><span class=user>foo</span></a>')
|
| +
|
| + def test_all_set(self):
|
| + import markupsafe as markup
|
| + for item in markup.__all__:
|
| + getattr(markup, item)
|
| +
|
| + def test_escape_silent(self):
|
| + assert escape_silent(None) == Markup()
|
| + assert escape(None) == Markup(None)
|
| + assert escape_silent('<foo>') == Markup(u'<foo>')
|
| +
|
| + def test_splitting(self):
|
| + self.assertEqual(Markup('a b').split(), [
|
| + Markup('a'),
|
| + Markup('b')
|
| + ])
|
| + self.assertEqual(Markup('a b').rsplit(), [
|
| + Markup('a'),
|
| + Markup('b')
|
| + ])
|
| + self.assertEqual(Markup('a\nb').splitlines(), [
|
| + Markup('a'),
|
| + Markup('b')
|
| + ])
|
| +
|
| + def test_mul(self):
|
| + self.assertEqual(Markup('a') * 3, Markup('aaa'))
|
| +
|
| +
|
| +class MarkupLeakTestCase(unittest.TestCase):
|
| +
|
| + def test_markup_leaks(self):
|
| + counts = set()
|
| + for count in range(20):
|
| + for item in range(1000):
|
| + escape("foo")
|
| + escape("<foo>")
|
| + escape(u"foo")
|
| + escape(u"<foo>")
|
| + counts.add(len(gc.get_objects()))
|
| + assert len(counts) == 1, 'ouch, c extension seems to leak objects'
|
| +
|
| +
|
| +def suite():
|
| + suite = unittest.TestSuite()
|
| + suite.addTest(unittest.makeSuite(MarkupTestCase))
|
| +
|
| + # this test only tests the c extension
|
| + if not hasattr(escape, 'func_code'):
|
| + suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
|
| +
|
| + return suite
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + unittest.main(defaultTest='suite')
|
| +
|
| +# vim:sts=4:sw=4:et:
|
|
|