Code

- Indexer Xapian, made Xapian 1.2 compatible. Needs at least Xapian 1.0.0 now.
[roundup.git] / test / test_templating.py
1 import unittest
2 from cgi import FieldStorage, MiniFieldStorage
4 from roundup.cgi.templating import *
5 from test_actions import MockNull, true
7 class MockDatabase(MockNull):
8     def getclass(self, name):
9         return self.classes[name]
11 class TemplatingTestCase(unittest.TestCase):
12     def setUp(self):
13         self.form = FieldStorage()
14         self.client = MockNull()
15         self.client.db = db = MockDatabase()
16         db.security.hasPermission = lambda *args, **kw: True
17         self.client.form = self.form
19 class HTMLDatabaseTestCase(TemplatingTestCase):
20     def test_HTMLDatabase___getitem__(self):
21         db = HTMLDatabase(self.client)
22         self.assert_(isinstance(db['issue'], HTMLClass))
23         # following assertions are invalid
24         # since roundup/cgi/templating.py r1.173.
25         # HTMLItem is function, not class,
26         # but HTMLUserClass and HTMLUser are passed on.
27         # these classes are no more.  they have ceased to be.
28         #self.assert_(isinstance(db['user'], HTMLUserClass))
29         #self.assert_(isinstance(db['issue1'], HTMLItem))
30         #self.assert_(isinstance(db['user1'], HTMLUser))
32     def test_HTMLDatabase___getattr__(self):
33         db = HTMLDatabase(self.client)
34         self.assert_(isinstance(db.issue, HTMLClass))
35         # see comment in test_HTMLDatabase___getitem__
36         #self.assert_(isinstance(db.user, HTMLUserClass))
37         #self.assert_(isinstance(db.issue1, HTMLItem))
38         #self.assert_(isinstance(db.user1, HTMLUser))
40     def test_HTMLDatabase_classes(self):
41         db = HTMLDatabase(self.client)
42         db._db.classes = {'issue':MockNull(), 'user': MockNull()}
43         db.classes()
45 class FunctionsTestCase(TemplatingTestCase):
46     def test_lookupIds(self):
47         db = HTMLDatabase(self.client)
48         def lookup(key):
49             if key == 'ok':
50                 return '1'
51             if key == 'fail':
52                 raise KeyError, 'fail'
53             return key
54         db._db.classes = {'issue': MockNull(lookup=lookup)}
55         prop = MockNull(classname='issue')
56         self.assertEqual(lookupIds(db._db, prop, ['1','2']), ['1','2'])
57         self.assertEqual(lookupIds(db._db, prop, ['ok','2']), ['1','2'])
58         self.assertEqual(lookupIds(db._db, prop, ['ok', 'fail'], 1),
59             ['1', 'fail'])
60         self.assertEqual(lookupIds(db._db, prop, ['ok', 'fail']), ['1'])
62     def test_lookupKeys(self):
63         db = HTMLDatabase(self.client)
64         def get(entry, key):
65             return {'1': 'green', '2': 'eggs'}.get(entry, entry)
66         shrubbery = MockNull(get=get)
67         db._db.classes = {'shrubbery': shrubbery}
68         self.assertEqual(lookupKeys(shrubbery, 'spam', ['1','2']),
69             ['green', 'eggs'])
70         self.assertEqual(lookupKeys(shrubbery, 'spam', ['ok','2']), ['ok',
71             'eggs'])
73 class HTMLClassTestCase(TemplatingTestCase) :
75     def test_link(self):
76         """Make sure lookup of a Link property works even in the
77         presence of multiple values in the form."""
78         def lookup(key) :
79             self.assertEqual(key, key.strip())
80             return "Status%s"%key
81         self.form.list.append(MiniFieldStorage("status", "1"))
82         self.form.list.append(MiniFieldStorage("status", "2"))
83         status = hyperdb.Link("status")
84         self.client.db.classes = dict \
85             ( issue = MockNull(getprops = lambda : dict(status = status))
86             , status  = MockNull(get = lambda id, name : id, lookup = lookup)
87             )
88         cls = HTMLClass(self.client, "issue")
89         cls["status"]
91     def test_multilink(self):
92         """`lookup` of an item will fail if leading or trailing whitespace
93            has not been stripped.
94         """
95         def lookup(key) :
96             self.assertEqual(key, key.strip())
97             return "User%s"%key
98         self.form.list.append(MiniFieldStorage("nosy", "1, 2"))
99         nosy = hyperdb.Multilink("user")
100         self.client.db.classes = dict \
101             ( issue = MockNull(getprops = lambda : dict(nosy = nosy))
102             , user  = MockNull(get = lambda id, name : id, lookup = lookup)
103             )
104         cls = HTMLClass(self.client, "issue")
105         cls["nosy"]
107     def test_url_match(self):
108         '''Test the URL regular expression in StringHTMLProperty.
109         '''
110         def t(s, nothing=False, **groups):
111             m = StringHTMLProperty.hyper_re.search(s)
112             if nothing:
113                 if m:
114                     self.assertEquals(m, None, '%r matched (%r)'%(s, m.groupdict()))
115                 return
116             else:
117                 self.assertNotEquals(m, None, '%r did not match'%s)
118             d = m.groupdict()
119             for g in groups:
120                 self.assertEquals(d[g], groups[g], '%s %r != %r in %r'%(g, d[g],
121                     groups[g], s))
123         #t('123.321.123.321', 'url')
124         t('http://localhost/', url='http://localhost/')
125         t('http://roundup.net/', url='http://roundup.net/')
126         t('http://richard@localhost/', url='http://richard@localhost/')
127         t('http://richard:sekrit@localhost/',
128             url='http://richard:sekrit@localhost/')
129         t('<HTTP://roundup.net/>', url='HTTP://roundup.net/')
130         t('www.a.ex', url='www.a.ex')
131         t('foo.a.ex', nothing=True)
132         t('StDevValidTimeSeries.GetObservation', nothing=True)
133         t('http://a.ex', url='http://a.ex')
134         t('http://a.ex/?foo&bar=baz\\.@!$%()qwerty',
135             url='http://a.ex/?foo&bar=baz\\.@!$%()qwerty')
136         t('www.foo.net', url='www.foo.net')
137         t('richard@com.example', email='richard@com.example')
138         t('r@a.com', email='r@a.com')
139         t('i1', **{'class':'i', 'id':'1'})
140         t('item123', **{'class':'item', 'id':'123'})
141         t('www.user:pass@host.net', email='pass@host.net')
142         t('user:pass@www.host.net', url='user:pass@www.host.net')
143         t('123.35', nothing=True)
144         t('-.3535', nothing=True)
146     def test_url_replace(self):
147         p = StringHTMLProperty(self.client, 'test', '1', None, 'test', '')
148         def t(s): return p.hyper_re.sub(p._hyper_repl, s)
149         ae = self.assertEquals
150         ae(t('http://roundup.net/'), '<a href="http://roundup.net/">http://roundup.net/</a>')
151         ae(t('&lt;HTTP://roundup.net/&gt;'), '&lt;<a href="HTTP://roundup.net/">HTTP://roundup.net/</a>&gt;')
152         ae(t('&lt;www.roundup.net&gt;'), '&lt;<a href="http://www.roundup.net">www.roundup.net</a>&gt;')
153         ae(t('item123123123123'), 'item123123123123')
155 '''
156 class HTMLPermissions:
157     def is_edit_ok(self):
158     def is_view_ok(self):
159     def is_only_view_ok(self):
160     def view_check(self):
161     def edit_check(self):
163 def input_html4(**attrs):
164 def input_xhtml(**attrs):
166 class HTMLInputMixin:
167     def __init__(self):
169 class HTMLClass(HTMLInputMixin, HTMLPermissions):
170     def __init__(self, client, classname, anonymous=0):
171     def __repr__(self):
172     def __getitem__(self, item):
173     def __getattr__(self, attr):
174     def designator(self):
175     def getItem(self, itemid, num_re=re.compile('-?\d+')):
176     def properties(self, sort=1):
177     def list(self, sort_on=None):
178     def csv(self):
179     def propnames(self):
180     def filter(self, request=None, filterspec={}, sort=(None,None),
181     def classhelp(self, properties=None, label='(list)', width='500',
182     def submit(self, label="Submit New Entry"):
183     def history(self):
184     def renderWith(self, name, **kwargs):
186 class HTMLItem(HTMLInputMixin, HTMLPermissions):
187     def __init__(self, client, classname, nodeid, anonymous=0):
188     def __repr__(self):
189     def __getitem__(self, item):
190     def __getattr__(self, attr):
191     def designator(self):
192     def is_retired(self):
193     def submit(self, label="Submit Changes"):
194     def journal(self, direction='descending'):
195     def history(self, direction='descending', dre=re.compile('\d+')):
196     def renderQueryForm(self):
198 class HTMLUserPermission:
199     def is_edit_ok(self):
200     def is_view_ok(self):
201     def _user_perm_check(self, type):
203 class HTMLUserClass(HTMLUserPermission, HTMLClass):
205 class HTMLUser(HTMLUserPermission, HTMLItem):
206     def __init__(self, client, classname, nodeid, anonymous=0):
207     def hasPermission(self, permission, classname=_marker):
209 class HTMLProperty(HTMLInputMixin, HTMLPermissions):
210     def __init__(self, client, classname, nodeid, prop, name, value,
211     def __repr__(self):
212     def __str__(self):
213     def __cmp__(self, other):
214     def is_edit_ok(self):
215     def is_view_ok(self):
217 class StringHTMLProperty(HTMLProperty):
218     def _hyper_repl(self, match):
219     def hyperlinked(self):
220     def plain(self, escape=0, hyperlink=0):
221     def stext(self, escape=0):
222     def field(self, size = 30):
223     def multiline(self, escape=0, rows=5, cols=40):
224     def email(self, escape=1):
226 class PasswordHTMLProperty(HTMLProperty):
227     def plain(self):
228     def field(self, size = 30):
229     def confirm(self, size = 30):
231 class NumberHTMLProperty(HTMLProperty):
232     def plain(self):
233     def field(self, size = 30):
234     def __int__(self):
235     def __float__(self):
237 class BooleanHTMLProperty(HTMLProperty):
238     def plain(self):
239     def field(self):
241 class DateHTMLProperty(HTMLProperty):
242     def plain(self):
243     def now(self):
244     def field(self, size = 30):
245     def reldate(self, pretty=1):
246     def pretty(self, format=_marker):
247     def local(self, offset):
249 class IntervalHTMLProperty(HTMLProperty):
250     def plain(self):
251     def pretty(self):
252     def field(self, size = 30):
254 class LinkHTMLProperty(HTMLProperty):
255     def __init__(self, *args, **kw):
256     def __getattr__(self, attr):
257     def plain(self, escape=0):
258     def field(self, showid=0, size=None):
259     def menu(self, size=None, height=None, showid=0, additional=[],
261 class MultilinkHTMLProperty(HTMLProperty):
262     def __init__(self, *args, **kwargs):
263     def __len__(self):
264     def __getattr__(self, attr):
265     def __getitem__(self, num):
266     def __contains__(self, value):
267     def reverse(self):
268     def plain(self, escape=0):
269     def field(self, size=30, showid=0):
270     def menu(self, size=None, height=None, showid=0, additional=[],
272 def make_sort_function(db, classname, sort_on=None):
273     def sortfunc(a, b):
275 def find_sort_key(linkcl):
277 def handleListCGIValue(value):
279 class ShowDict:
280     def __init__(self, columns):
281     def __getitem__(self, name):
283 class HTMLRequest(HTMLInputMixin):
284     def __init__(self, client):
285     def _post_init(self):
286     def updateFromURL(self, url):
287     def update(self, kwargs):
288     def description(self):
289     def __str__(self):
290     def indexargs_form(self, columns=1, sort=1, group=1, filter=1,
291     def indexargs_url(self, url, args):
292     def base_javascript(self):
293     def batch(self):
295 class Batch(ZTUtils.Batch):
296     def __init__(self, client, sequence, size, start, end=0, orphan=0,
297     def __getitem__(self, index):
298     def propchanged(self, property):
299     def previous(self):
300     def next(self):
302 class TemplatingUtils:
303     def __init__(self, client):
304     def Batch(self, sequence, size, start, end=0, orphan=0, overlap=0):
306 class NoTemplate(Exception):
307 class Unauthorised(Exception):
308     def __init__(self, action, klass):
309     def __str__(self):
310 def find_template(dir, name, extension):
312 class Templates:
313     def __init__(self, dir):
314     def precompileTemplates(self):
315     def get(self, name, extension=None):
316     def __getitem__(self, name):
318 class RoundupPageTemplate(PageTemplate.PageTemplate):
319     def getContext(self, client, classname, request):
320     def render(self, client, classname, request, **options):
321     def __repr__(self):
322 '''
325 def test_suite():
326     suite = unittest.TestSuite()
327     suite.addTest(unittest.makeSuite(HTMLDatabaseTestCase))
328     suite.addTest(unittest.makeSuite(FunctionsTestCase))
329     suite.addTest(unittest.makeSuite(HTMLClassTestCase))
330     return suite
332 if __name__ == '__main__':
333     runner = unittest.TextTestRunner()
334     unittest.main(testRunner=runner)
336 # vim: set et sts=4 sw=4 :