Premiere version : mise en route du suivi.
[auf_roundup.git] / test / test_templating.py
1 import unittest
2 from cgi import FieldStorage, MiniFieldStorage
3
4 from roundup.cgi.templating import *
5 from test_actions import MockNull, true
6
7 class MockDatabase(MockNull):
8 def getclass(self, name):
9 return self.classes[name]
10
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
18
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))
31
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))
39
40 def test_HTMLDatabase_classes(self):
41 db = HTMLDatabase(self.client)
42 db._db.classes = {'issue':MockNull(), 'user': MockNull()}
43 db.classes()
44
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'])
61
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'])
72
73 class HTMLClassTestCase(TemplatingTestCase) :
74
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"]
90
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"]
106
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))
122
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)
145
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')
154
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):
162
163 def input_html4(**attrs):
164 def input_xhtml(**attrs):
165
166 class HTMLInputMixin:
167 def __init__(self):
168
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):
185
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):
197
198 class HTMLUserPermission:
199 def is_edit_ok(self):
200 def is_view_ok(self):
201 def _user_perm_check(self, type):
202
203 class HTMLUserClass(HTMLUserPermission, HTMLClass):
204
205 class HTMLUser(HTMLUserPermission, HTMLItem):
206 def __init__(self, client, classname, nodeid, anonymous=0):
207 def hasPermission(self, permission, classname=_marker):
208
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):
216
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):
225
226 class PasswordHTMLProperty(HTMLProperty):
227 def plain(self):
228 def field(self, size = 30):
229 def confirm(self, size = 30):
230
231 class NumberHTMLProperty(HTMLProperty):
232 def plain(self):
233 def field(self, size = 30):
234 def __int__(self):
235 def __float__(self):
236
237 class BooleanHTMLProperty(HTMLProperty):
238 def plain(self):
239 def field(self):
240
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):
248
249 class IntervalHTMLProperty(HTMLProperty):
250 def plain(self):
251 def pretty(self):
252 def field(self, size = 30):
253
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=[],
260
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=[],
271
272 def make_sort_function(db, classname, sort_on=None):
273 def sortfunc(a, b):
274
275 def find_sort_key(linkcl):
276
277 def handleListCGIValue(value):
278
279 class ShowDict:
280 def __init__(self, columns):
281 def __getitem__(self, name):
282
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):
294
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):
301
302 class TemplatingUtils:
303 def __init__(self, client):
304 def Batch(self, sequence, size, start, end=0, orphan=0, overlap=0):
305
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):
311
312 class Templates:
313 def __init__(self, dir):
314 def precompileTemplates(self):
315 def get(self, name, extension=None):
316 def __getitem__(self, name):
317
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 '''
323
324
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
331
332 if __name__ == '__main__':
333 runner = unittest.TextTestRunner()
334 unittest.main(testRunner=runner)
335
336 # vim: set et sts=4 sw=4 :