1# -*- coding: utf-8 -*- 2# 3# Copyright (C) 2005-2021 Edgewall Software 4# Copyright (C) 2005-2007 Christopher Lenz <cmlenz@gmx.de> 5# All rights reserved. 6# 7# This software is licensed as described in the file COPYING, which 8# you should have received as part of this distribution. The terms 9# are also available at https://trac.edgewall.org/wiki/TracLicense. 10# 11# This software consists of voluntary contributions made by many 12# individuals. For the exact contribution history, see the revision 13# history and logs, available at https://trac.edgewall.org/log/. 14 15import doctest 16import unittest 17 18from trac.util.text import jinja2template 19import trac.web.href 20 21 22class HrefTestCase(unittest.TestCase): 23 """Unit tests for Href URL builder.""" 24 25 def test_non_empty_base(self): 26 """Build URLs with a non-empty base.""" 27 href = trac.web.href.Href('/base') 28 self.assertEqual('/base', href()) 29 self.assertEqual('/base', href('/')) 30 self.assertEqual('/base/sub', href('sub')) 31 self.assertEqual('/base/sub', href('/sub/')) 32 self.assertEqual('/base/sub/other', href('sub', 'other')) 33 self.assertEqual('/base/sub/other', href('sub', None, 'other')) 34 self.assertEqual('/base/sub/other', href('sub', '', 'other')) 35 self.assertEqual('/base/sub/other', href('sub', '', '', 'other')) 36 self.assertEqual('/base/sub/other', href('', 'sub', 'other')) 37 self.assertEqual('/base/sub/other/', href('sub', 'other', '')) 38 self.assertEqual('/base/with%20special%26chars', 39 href('with special&chars')) 40 self.assertIn(href('page', param='value', other='other value', more=None), [ 41 '/base/page?param=value&other=other+value', 42 '/base/page?other=other+value¶m=value']) 43 self.assertEqual('/base/page?param=multiple¶m=values', 44 href('page', param=['multiple', 'values'])) 45 46 self.assertEqual('/base/path/to/file/', href + '/path/to/file/') 47 self.assertEqual('/base/path/to/file', href + 'path/to/file') 48 self.assertEqual('/base', href + '') 49 50 def test_base_with_trailing_slash(self): 51 """Build URLs with a base with a trailing slash.""" 52 href = trac.web.href.Href('/base/') 53 self.assertEqual('/base', href()) 54 self.assertEqual('/base', href('/')) 55 self.assertEqual('/base/sub', href('sub')) 56 self.assertEqual('/base/sub', href('/sub/')) 57 58 self.assertEqual('/base/path/to/file/', href + '/path/to/file/') 59 self.assertEqual('/base/path/to/file', href + 'path/to/file') 60 self.assertEqual('/base', href + '') 61 62 def test_empty_base(self): 63 """Build URLs with an empty base.""" 64 href = trac.web.href.Href('') 65 self.assertEqual('/', href()) 66 self.assertEqual('/', href('/')) 67 self.assertEqual('/sub', href('sub')) 68 self.assertEqual('/sub', href('/sub/')) 69 self.assertEqual('/sub/other', href('sub', 'other')) 70 self.assertEqual('/sub/other', href('sub', None, 'other')) 71 self.assertEqual('/sub/other', href('sub', '', 'other')) 72 self.assertEqual('/sub/other', href('sub', '', '', 'other')) 73 self.assertEqual('/sub/other', href('', 'sub', 'other')) 74 self.assertEqual('/sub/other/', href('sub', 'other', '')) 75 self.assertEqual('/with%20special%26chars', 76 href('with special&chars')) 77 self.assertIn( 78 href('page', param='value', other='other value', more=None), 79 ['/page?param=value&other=other+value', 80 '/page?other=other+value¶m=value']) 81 self.assertEqual('/page?param=multiple¶m=values', 82 href('page', param=['multiple', 'values'])) 83 84 self.assertEqual('/path/to/file/', href + '/path/to/file/') 85 self.assertEqual('/path/to/file', href + 'path/to/file') 86 self.assertEqual('/', href + '') 87 self.assertEqual('/?name=val', href + '?name=val') 88 89 def test_params_subclasses(self): 90 """Parameters passed using subclasses of dict, list and tuple.""" 91 class MyDict(dict): 92 pass 93 class MyList(list): 94 pass 95 class MyTuple(tuple): 96 pass 97 href = trac.web.href.Href('/base') 98 self.assertEqual('/base?param=test¶m=other', 99 href(param=MyList(['test', 'other']))) 100 self.assertEqual('/base?param=test¶m=other', 101 href(param=MyTuple(['test', 'other']))) 102 self.assertIn(href(MyDict(param='value', other='other value')), [ 103 '/base?param=value&other=other+value', 104 '/base?other=other+value¶m=value']) 105 self.assertEqual('/base?param=value&other=other+value', 106 href(MyList([('param', 'value'), ('other', 'other value')]))) 107 self.assertEqual('/base?param=value&other=other+value', 108 href(MyTuple([('param', 'value'), ('other', 'other value')]))) 109 110 def test_add_unicode(self): 111 href = trac.web.href.Href('/base') 112 self.assertEqual('/base/p%C3%A4th/to/%20/file/', 113 href + '/päth/to/ /file/') 114 self.assertEqual('/base/p%C3%A4th/to/%20/file', 115 href + 'päth/to/ /file') 116 self.assertEqual('/base?type=def%C3%A9ct&or&type=abc%20def', 117 href + '?type=deféct&or&type=abc def') 118 self.assertEqual('/base/p%C3%A4th/to/file/' 119 '?type=def%C3%A9ct&or&type=abc%20def', 120 href + '/päth/to/file/?type=deféct&or&type=abc def') 121 self.assertEqual('/base/p%C3%A4th/to/file' 122 '?type=def%C3%A9ct&or&type=abc%20def', 123 href + 'päth/to/file?type=deféct&or&type=abc def') 124 125 def test_jinja2(self): 126 # https://trac.edgewall.org/ticket/13244 127 128 data = {'href': trac.web.href.Href('http://localhost/base')} 129 self.assertEqual( 130 '<a href="http://localhost/base">anchor</a>', 131 self._render_template('<a href="${href()}">anchor</a>', data)) 132 self.assertEqual( 133 'URL: http://localhost/base', 134 self._render_template('URL: ${href()}', data, text=True)) 135 136 def _render_template(self, template, data, text=False): 137 t = jinja2template(template, text=text) 138 return t.render(**data) 139 140 141def test_suite(): 142 suite = unittest.TestSuite() 143 suite.addTest(doctest.DocTestSuite(trac.web.href)) 144 suite.addTest(unittest.makeSuite(HrefTestCase)) 145 return suite 146 147if __name__ == '__main__': 148 unittest.main(defaultTest='test_suite') 149