1
# Copyright (c) 2004-2009 Divmod.
2
# See LICENSE for details.
6
from twisted.trial import unittest, util
8
from nevow import context
10
from nevow.flat.flatstan import _PrecompiledSlot
11
from nevow import loaders
12
from nevow import tags as t
14
class TestDocFactories(unittest.TestCase):
16
def _preprocessorTest(self, docFactory):
17
def preprocessor(uncompiled):
18
self.assertEquals(len(uncompiled), 1)
19
uncompiled = uncompiled[0]
20
self.assertEquals(uncompiled.tagName, 'div')
21
self.assertEquals(len(uncompiled.children), 2)
22
self.assertEquals(uncompiled.children[0].tagName, 'span')
23
self.assertEquals(uncompiled.children[0].children, ['Hello'])
24
self.assertEquals(uncompiled.children[1].tagName, 'span')
25
self.assertEquals(uncompiled.children[1].children, ['world'])
26
return t.div['goodbye.']
27
doc = docFactory.load(preprocessors=[preprocessor])
28
self.assertEquals(doc, ['<div>goodbye.</div>'])
31
def test_stanPreprocessors(self):
33
Test that the stan loader properly passes uncompiled documents to
34
preprocessors it is given.
36
factory = loaders.stan(
37
t.div[t.span['Hello'], t.span['world']])
38
return self._preprocessorTest(factory)
42
doc = t.ul(id='nav')[t.li['one'], t.li['two'], t.li['three']]
43
df = loaders.stan(doc)
44
self.assertEquals(df.load()[0], '<ul id="nav"><li>one</li><li>two</li><li>three</li></ul>')
47
def test_stanPrecompiled(self):
49
Test that a stan loader works with precompiled documents.
51
(This behavior will probably be deprecated soon, but we need to test
52
that it works right until we remove it.)
54
doc = flat.precompile(t.ul(id='nav')[t.li['one'], t.li['two'], t.slot('three')])
55
df = loaders.stan(doc)
57
self.assertEqual(loaded[0], '<ul id="nav"><li>one</li><li>two</li>')
58
self.failUnless(isinstance(loaded[1], _PrecompiledSlot))
59
self.assertEqual(loaded[1].name, 'three')
60
self.assertEqual(loaded[2], '</ul>')
63
def test_htmlstr(self):
64
doc = '<ul id="nav"><li>a</li><li>b</li><li>c</li></ul>'
65
df = loaders.htmlstr(doc)
66
self.assertEquals(df.load()[0], doc)
67
test_htmlstr.suppress = [
68
util.suppress(message=
69
r"\[v0.8\] htmlstr is deprecated because it's buggy. "
70
"Please start using xmlfile and/or xmlstr.")]
73
def test_htmlfile(self):
74
doc = '<ul id="nav"><li>a</li><li>b</li><li>c</li></ul>'
79
df = loaders.htmlfile(temp)
80
self.assertEquals(df.load()[0], doc)
81
test_htmlfile.suppress = [
82
util.suppress(message=
83
r"\[v0.8\] htmlfile is deprecated because it's buggy. "
84
"Please start using xmlfile and/or xmlstr.")]
87
def test_htmlfile_slots(self):
88
doc = '<nevow:slot name="foo">Hi there</nevow:slot>'
93
df = loaders.htmlfile(temp)
94
self.assertEquals(df.load()[0].children, ['Hi there'])
95
test_htmlfile_slots.suppress = [
96
util.suppress(message=
97
r"\[v0.8\] htmlfile is deprecated because it's buggy. "
98
"Please start using xmlfile and/or xmlstr.")]
101
def test_xmlstr(self):
102
doc = '<ul id="nav"><li>a</li><li>b</li><li>c</li></ul>'
103
df = loaders.xmlstr(doc)
104
self.assertEquals(df.load()[0], doc)
107
def test_xmlstrPreprocessors(self):
109
Test that the xmlstr loader properly passes uncompiled documents to
110
preprocessors it is given.
112
factory = loaders.xmlstr(
113
'<div><span>Hello</span><span>world</span></div>')
114
return self._preprocessorTest(factory)
117
def test_xmlfile(self):
118
doc = '<ul id="nav"><li>a</li><li>b</li><li>c</li></ul>'
123
df = loaders.xmlfile(temp)
124
self.assertEquals(df.load()[0], doc)
127
def test_xmlfilePreprocessors(self):
129
Test that the xmlstr loader properly passes uncompiled documents to
130
preprocessors it is given.
132
xmlFile = self.mktemp()
133
f = file(xmlFile, 'w')
134
f.write('<div><span>Hello</span><span>world</span></div>')
136
factory = loaders.xmlfile(xmlFile)
137
return self._preprocessorTest(factory)
140
def test_patterned(self):
141
"""Test fetching a specific part (a pattern) of the document.
143
doc = t.div[t.p[t.span(pattern='inner')['something']]]
144
df = loaders.stan(doc, pattern='inner')
145
self.assertEquals(df.load()[0].tagName, 'span')
146
self.assertEquals(df.load()[0].children[0], 'something')
149
def test_ignoreDocType(self):
150
doc = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n<html><body><p>Hello.</p></body></html>'''
151
df = loaders.xmlstr(doc, ignoreDocType=True)
152
self.assertEquals(flat.flatten(df), '<html><body><p>Hello.</p></body></html>')
154
def test_ignoreComment(self):
155
doc = '<!-- skip this --><p>Hello.</p>'
156
df = loaders.xmlstr(doc, ignoreComment=True)
157
self.assertEquals(flat.flatten(df), '<p>Hello.</p>')
160
class TestDocFactoriesCache(unittest.TestCase):
164
<p nevow:pattern="1">one</p>
165
<p nevow:pattern="2">two</p>
170
<div xmlns:nevow="http://nevow.com/ns/nevow/0.1">
171
<p nevow:pattern="1">one</p>
172
<p nevow:pattern="2">two</p>
176
stan = t.div[t.p(pattern='1')['one'],t.p(pattern='2')['two']]
180
loader = loaders.stan(self.stan)
181
self.assertEquals( id(loader.load()), id(loader.load()) )
183
loader = loaders.stan(self.stan, pattern='1')
184
self.assertEquals( id(loader.load()), id(loader.load()) )
186
l1 = loaders.stan(self.stan, pattern='1')
187
l2 = loaders.stan(self.stan, pattern='1')
188
self.assertNotEqual( id(l1.load()), id(l2.load()) )
190
l1 = loaders.stan(self.stan, pattern='1')
191
l2 = loaders.stan(self.stan, pattern='2')
192
self.assertNotEqual( id(l1.load()), id(l2.load()) )
195
def test_htmlstr(self):
196
loader = loaders.htmlstr(self.doc)
197
self.assertEquals( id(loader.load()), id(loader.load()) )
199
loader = loaders.htmlstr(self.doc, pattern='1')
200
self.assertEquals( id(loader.load()), id(loader.load()) )
202
l1 = loaders.htmlstr(self.doc, pattern='1')
203
l2 = loaders.htmlstr(self.doc, pattern='1')
204
self.assertNotEqual( id(l1.load()), id(l2.load()) )
206
l1 = loaders.htmlstr(self.doc, pattern='1')
207
l2 = loaders.htmlstr(self.doc, pattern='2')
208
self.assertNotEqual( id(l1.load()), id(l2.load()) )
209
test_htmlstr.suppress = [
210
util.suppress(message=
211
r"\[v0.8\] htmlstr is deprecated because it's buggy. "
212
"Please start using xmlfile and/or xmlstr.")]
215
def test_htmlfile(self):
221
loader = loaders.htmlfile(temp)
222
self.assertEquals( id(loader.load()), id(loader.load()) )
224
l1 = loaders.htmlfile(temp, pattern='1')
225
l2 = loaders.htmlfile(temp, pattern='1')
226
self.assertNotEqual( id(l1.load()), id(l2.load()) )
228
l1 = loaders.htmlfile(temp, pattern='1')
229
l2 = loaders.htmlfile(temp, pattern='2')
230
self.assertNotEqual( id(l1.load()), id(l2.load()) )
231
test_htmlfile.suppress = [
232
util.suppress(message=
233
r"\[v0.8\] htmlfile is deprecated because it's buggy. "
234
"Please start using xmlfile and/or xmlstr.")]
237
def test_htmlfileReload(self):
243
loader = loaders.htmlfile(temp)
245
self.assertEquals(id(r), id(loader.load()))
246
os.utime(temp, (os.path.getatime(temp), os.path.getmtime(temp)+5))
247
self.assertNotEqual(id(r), id(loader.load()))
248
test_htmlfileReload.suppress = [
249
util.suppress(message=
250
r"\[v0.8\] htmlfile is deprecated because it's buggy. "
251
"Please start using xmlfile and/or xmlstr.")]
255
def test_xmlstr(self):
257
loader = loaders.xmlstr(self.nsdoc)
258
self.assertEquals( id(loader.load()), id(loader.load()) )
260
loader = loaders.xmlstr(self.nsdoc, pattern='1')
261
self.assertEquals( id(loader.load()), id(loader.load()) )
263
l1 = loaders.xmlstr(self.nsdoc, pattern='1')
264
l2 = loaders.xmlstr(self.nsdoc, pattern='1')
265
self.assertNotEqual( id(l1.load()), id(l2.load()) )
267
l1 = loaders.xmlstr(self.nsdoc, pattern='1')
268
l2 = loaders.xmlstr(self.nsdoc, pattern='2')
269
self.assertNotEqual( id(l1.load()), id(l2.load()) )
272
def test_xmlSlotDefault(self):
274
An I{nevow:slot} tag in an XML template may have a I{default}
275
attribute specifying a value for the slot if it is not otherwise
279
<div xmlns:nevow="http://nevow.com/ns/nevow/0.1">
280
<nevow:slot name="1" />
281
<nevow:slot name="2" default="3" />
284
loader = loaders.xmlstr(slotsdoc)
285
loaded = loader.load()
286
self.assertEquals(loaded[1].default, None)
287
self.assertEquals(loaded[3].default, "3")
290
def test_xmlfile(self):
297
loader = loaders.xmlfile(temp)
298
self.assertEquals( id(loader.load()), id(loader.load()) )
300
loader = loaders.xmlfile(temp, pattern='1')
301
self.assertEquals( id(loader.load()), id(loader.load()) )
303
l1 = loaders.xmlfile(temp, pattern='1')
304
l2 = loaders.xmlfile(temp, pattern='1')
305
self.assertNotEqual( id(l1.load()), id(l2.load()) )
307
l1 = loaders.xmlfile(temp, pattern='1')
308
l2 = loaders.xmlfile(temp, pattern='2')
309
self.assertNotEqual( id(l1.load()), id(l2.load()) )
311
def test_xmlfileReload(self):
318
loader = loaders.xmlfile(temp)
320
self.assertEquals(id(r), id(loader.load()))
321
os.utime(temp, (os.path.getatime(temp), os.path.getmtime(temp)+5))
322
self.assertNotEqual(id(r), id(loader.load()))
324
def test_reloadAfterPrecompile(self):
332
f.write('<p>foo</p>')
336
ctx = context.WovenContext()
337
doc = loaders.htmlfile(temp)
338
pc = flat.precompile(flat.flatten(doc), ctx)
340
before = ''.join(flat.serialize(pc, ctx))
343
# Write the file with different content and make sure the
346
f.write('<p>bar</p>')
348
os.utime(temp, (os.path.getatime(temp), os.path.getmtime(temp)+5))
350
after = ''.join(flat.serialize(pc, ctx))
352
self.assertIn('foo', before)
353
self.assertIn('bar', after)
354
self.failIfEqual(before, after)
355
test_reloadAfterPrecompile.todo = \
356
'Fix so that disk templates are reloaded even after a precompile. ' \
357
'Probably just a matter of making the DocSerializer really lazy'
360
class TestContext(unittest.TestCase):
361
"""Check that each of the standard loaders supports load with and without a
367
self._withAndWithout(loaders.stan(doc))
369
def test_xmlstr(self):
371
self._withAndWithout(loaders.xmlstr(doc))
373
def test_xmlfile(self):
376
f.write('<p>hello</p>')
378
self._withAndWithout(loaders.xmlfile(temp))
380
def test_htmlstr(self):
382
self._withAndWithout(loaders.htmlstr(doc))
383
test_htmlstr.suppress = [
384
util.suppress(message=
385
r"\[v0.8\] htmlstr is deprecated because it's buggy. "
386
"Please start using xmlfile and/or xmlstr.")]
388
def test_htmlfile(self):
391
f.write('<p>hello</p>')
393
self._withAndWithout(loaders.htmlfile(temp))
394
test_htmlfile.suppress = [
395
util.suppress(message=
396
r"\[v0.8\] htmlfile is deprecated because it's buggy. "
397
"Please start using xmlfile and/or xmlstr.")]
399
def _withAndWithout(self, loader):
400
ctx = context.WovenContext()
401
self.assertEquals(loader.load(), ['<p>hello</p>'])
402
self.assertEquals(loader.load(ctx), ['<p>hello</p>'])
405
class TestParsing(unittest.TestCase):
407
def test_missingSpace(self):
408
doc = '<p xmlns:nevow="http://nevow.com/ns/nevow/0.1"><nevow:slot name="foo"/> <nevow:slot name="foo"/></p>'
409
## This used to say htmlstr, and this test failed because microdom ignores whitespace;
410
## This test passes fine using xmlstr. I am not going to fix this because microdom is too
411
## hard to fix. If you need this, switch to xmlstr.
412
result = loaders.xmlstr(doc).load()
413
# There should be a space between the two slots
414
self.assertEquals(result[2], ' ')