1
# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
2
# See LICENSE for details.
5
Tests for L{twisted.words.xish.domish}, a DOM-like library for XMPP.
8
from twisted.trial import unittest
9
from twisted.words.xish import domish
12
class DomishTestCase(unittest.TestCase):
13
def testEscaping(self):
15
self.assertEquals(domish.escapeToXml(s), "&<>'\"")
16
self.assertEquals(domish.escapeToXml(s, 1), "&<>'"")
18
def testNamespaceObject(self):
19
ns = domish.Namespace("testns")
20
self.assertEquals(ns.foo, ("testns", "foo"))
22
def testElementInit(self):
23
e = domish.Element((None, "foo"))
24
self.assertEquals(e.name, "foo")
25
self.assertEquals(e.uri, None)
26
self.assertEquals(e.defaultUri, None)
27
self.assertEquals(e.parent, None)
29
e = domish.Element(("", "foo"))
30
self.assertEquals(e.name, "foo")
31
self.assertEquals(e.uri, "")
32
self.assertEquals(e.defaultUri, "")
33
self.assertEquals(e.parent, None)
35
e = domish.Element(("testns", "foo"))
36
self.assertEquals(e.name, "foo")
37
self.assertEquals(e.uri, "testns")
38
self.assertEquals(e.defaultUri, "testns")
39
self.assertEquals(e.parent, None)
41
e = domish.Element(("testns", "foo"), "test2ns")
42
self.assertEquals(e.name, "foo")
43
self.assertEquals(e.uri, "testns")
44
self.assertEquals(e.defaultUri, "test2ns")
46
def testChildOps(self):
47
e = domish.Element(("testns", "foo"))
48
e.addContent("somecontent")
49
b2 = e.addElement(("testns2", "bar2"))
50
e["attrib1"] = "value1"
51
e[("testns2", "attrib2")] = "value2"
57
# Check content merging
58
self.assertEquals(e.children[-1], "abc123")
60
# Check str()/content extraction
61
self.assertEquals(str(e), "somecontent")
63
# Check direct child accessor
64
self.assertEquals(e.bar2, b2)
65
e.bar2.addContent("subcontent")
66
e.bar2["bar2value"] = "somevalue"
69
self.assertEquals(e.children[1], e.bar2)
70
self.assertEquals(e.children[2], e.bar)
73
self.assertEquals(e["attrib1"], "value1")
75
self.assertEquals(e.hasAttribute("attrib1"), 0)
76
self.assertEquals(e.hasAttribute("attrib2"), 0)
77
self.assertEquals(e[("testns2", "attrib2")], "value2")
80
def test_elements(self):
82
Calling C{elements} without arguments on a L{domish.Element} returns
83
all child elements, whatever the qualfied name.
85
e = domish.Element((u"testns", u"foo"))
86
c1 = e.addElement(u"name")
87
c2 = e.addElement((u"testns2", u"baz"))
88
c3 = e.addElement(u"quux")
89
c4 = e.addElement((u"testns", u"name"))
91
elts = list(e.elements())
93
self.assertIn(c1, elts)
94
self.assertIn(c2, elts)
95
self.assertIn(c3, elts)
96
self.assertIn(c4, elts)
99
def test_elementsWithQN(self):
101
Calling C{elements} with a namespace and local name on a
102
L{domish.Element} returns all child elements with that qualified name.
104
e = domish.Element((u"testns", u"foo"))
105
c1 = e.addElement(u"name")
106
c2 = e.addElement((u"testns2", u"baz"))
107
c3 = e.addElement(u"quux")
108
c4 = e.addElement((u"testns", u"name"))
110
elts = list(e.elements(u"testns", u"name"))
112
self.assertIn(c1, elts)
113
self.assertNotIn(c2, elts)
114
self.assertNotIn(c3, elts)
115
self.assertIn(c4, elts)
119
class DomishStreamTestsMixin:
121
Mixin defining tests for different stream implementations.
123
@ivar streamClass: A no-argument callable which will be used to create an
124
XML parser which can produce a stream of elements from incremental
128
self.doc_started = False
129
self.doc_ended = False
132
self.stream = self.streamClass()
133
self.stream.DocumentStartEvent = self._docStarted
134
self.stream.ElementEvent = self.elements.append
135
self.stream.DocumentEndEvent = self._docEnded
137
def _docStarted(self, root):
139
self.doc_started = True
142
self.doc_ended = True
144
def doTest(self, xml):
145
self.stream.parse(xml)
147
def testHarness(self):
148
xml = "<root><child/><child2/></root>"
149
self.stream.parse(xml)
150
self.assertEquals(self.doc_started, True)
151
self.assertEquals(self.root.name, 'root')
152
self.assertEquals(self.elements[0].name, 'child')
153
self.assertEquals(self.elements[1].name, 'child2')
154
self.assertEquals(self.doc_ended, True)
157
xml = "<stream:stream xmlns:stream='etherx' xmlns='jabber'>\n" + \
158
" <message to='bar'>" + \
159
" <x xmlns='xdelay'>some&data></x>" + \
163
self.stream.parse(xml)
164
self.assertEquals(self.root.name, 'stream')
165
self.assertEquals(self.root.uri, 'etherx')
166
self.assertEquals(self.elements[0].name, 'message')
167
self.assertEquals(self.elements[0].uri, 'jabber')
168
self.assertEquals(self.elements[0]['to'], 'bar')
169
self.assertEquals(self.elements[0].x.uri, 'xdelay')
170
self.assertEquals(unicode(self.elements[0].x), 'some&data>')
172
def testNoRootNS(self):
173
xml = "<stream><error xmlns='etherx'/></stream>"
175
self.stream.parse(xml)
176
self.assertEquals(self.root.uri, '')
177
self.assertEquals(self.elements[0].uri, 'etherx')
179
def testNoDefaultNS(self):
180
xml = "<stream:stream xmlns:stream='etherx'><error/></stream:stream>"""
182
self.stream.parse(xml)
183
self.assertEquals(self.root.uri, 'etherx')
184
self.assertEquals(self.root.defaultUri, '')
185
self.assertEquals(self.elements[0].uri, '')
186
self.assertEquals(self.elements[0].defaultUri, '')
188
def testChildDefaultNS(self):
189
xml = "<root xmlns='testns'><child/></root>"
191
self.stream.parse(xml)
192
self.assertEquals(self.root.uri, 'testns')
193
self.assertEquals(self.elements[0].uri, 'testns')
195
def testEmptyChildNS(self):
196
xml = "<root xmlns='testns'><child1><child2 xmlns=''/></child1></root>"
198
self.stream.parse(xml)
199
self.assertEquals(self.elements[0].child2.uri, '')
201
def testChildPrefix(self):
202
xml = "<root xmlns='testns' xmlns:foo='testns2'><foo:child/></root>"
204
self.stream.parse(xml)
205
self.assertEquals(self.root.localPrefixes['foo'], 'testns2')
206
self.assertEquals(self.elements[0].uri, 'testns2')
208
def testUnclosedElement(self):
209
self.assertRaises(domish.ParserError, self.stream.parse,
210
"<root><error></root>")
212
def test_namespaceReuse(self):
214
Test that reuse of namespaces does affect an element's serialization.
216
When one element uses a prefix for a certain namespace, this is
217
stored in the C{localPrefixes} attribute of the element. We want
218
to make sure that elements created after such use, won't have this
219
prefix end up in their C{localPrefixes} attribute, too.
223
<foo:child1 xmlns:foo='testns'/>
224
<child2 xmlns='testns'/>
227
self.stream.parse(xml)
228
self.assertEquals('child1', self.elements[0].name)
229
self.assertEquals('testns', self.elements[0].uri)
230
self.assertEquals('', self.elements[0].defaultUri)
231
self.assertEquals({'foo': 'testns'}, self.elements[0].localPrefixes)
232
self.assertEquals('child2', self.elements[1].name)
233
self.assertEquals('testns', self.elements[1].uri)
234
self.assertEquals('testns', self.elements[1].defaultUri)
235
self.assertEquals({}, self.elements[1].localPrefixes)
239
class DomishExpatStreamTestCase(DomishStreamTestsMixin, unittest.TestCase):
241
Tests for L{domish.ExpatElementStream}, the expat-based element stream
244
streamClass = domish.ExpatElementStream
249
skip = "pyexpat is required for ExpatElementStream tests."
253
class DomishSuxStreamTestCase(DomishStreamTestsMixin, unittest.TestCase):
255
Tests for L{domish.SuxElementStream}, the L{twisted.web.sux}-based element
256
stream implementation.
258
streamClass = domish.SuxElementStream
260
if domish.SuxElementStream is None:
261
skip = "twisted.web is required for SuxElementStream tests."
265
class SerializerTests(unittest.TestCase):
266
def testNoNamespace(self):
267
e = domish.Element((None, "foo"))
268
self.assertEquals(e.toXml(), "<foo/>")
269
self.assertEquals(e.toXml(closeElement = 0), "<foo>")
271
def testDefaultNamespace(self):
272
e = domish.Element(("testns", "foo"))
273
self.assertEquals(e.toXml(), "<foo xmlns='testns'/>")
275
def testOtherNamespace(self):
276
e = domish.Element(("testns", "foo"), "testns2")
277
self.assertEquals(e.toXml({'testns': 'bar'}),
278
"<bar:foo xmlns:bar='testns' xmlns='testns2'/>")
280
def testChildDefaultNamespace(self):
281
e = domish.Element(("testns", "foo"))
283
self.assertEquals(e.toXml(), "<foo xmlns='testns'><bar/></foo>")
285
def testChildSameNamespace(self):
286
e = domish.Element(("testns", "foo"))
287
e.addElement(("testns", "bar"))
288
self.assertEquals(e.toXml(), "<foo xmlns='testns'><bar/></foo>")
290
def testChildSameDefaultNamespace(self):
291
e = domish.Element(("testns", "foo"))
292
e.addElement("bar", "testns")
293
self.assertEquals(e.toXml(), "<foo xmlns='testns'><bar/></foo>")
295
def testChildOtherDefaultNamespace(self):
296
e = domish.Element(("testns", "foo"))
297
e.addElement(("testns2", "bar"), 'testns2')
298
self.assertEquals(e.toXml(), "<foo xmlns='testns'><bar xmlns='testns2'/></foo>")
300
def testOnlyChildDefaultNamespace(self):
301
e = domish.Element((None, "foo"))
302
e.addElement(("ns2", "bar"), 'ns2')
303
self.assertEquals(e.toXml(), "<foo><bar xmlns='ns2'/></foo>")
305
def testOnlyChildDefaultNamespace2(self):
306
e = domish.Element((None, "foo"))
308
self.assertEquals(e.toXml(), "<foo><bar/></foo>")
310
def testChildInDefaultNamespace(self):
311
e = domish.Element(("testns", "foo"), "testns2")
312
e.addElement(("testns2", "bar"))
313
self.assertEquals(e.toXml(), "<xn0:foo xmlns:xn0='testns' xmlns='testns2'><bar/></xn0:foo>")
315
def testQualifiedAttribute(self):
316
e = domish.Element((None, "foo"),
317
attribs = {("testns2", "bar"): "baz"})
318
self.assertEquals(e.toXml(), "<foo xmlns:xn0='testns2' xn0:bar='baz'/>")
320
def testQualifiedAttributeDefaultNS(self):
321
e = domish.Element(("testns", "foo"),
322
attribs = {("testns", "bar"): "baz"})
323
self.assertEquals(e.toXml(), "<foo xmlns='testns' xmlns:xn0='testns' xn0:bar='baz'/>")
325
def testTwoChilds(self):
326
e = domish.Element(('', "foo"))
327
child1 = e.addElement(("testns", "bar"), "testns2")
328
child1.addElement(('testns2', 'quux'))
329
child2 = e.addElement(("testns3", "baz"), "testns4")
330
child2.addElement(('testns', 'quux'))
331
self.assertEquals(e.toXml(), "<foo><xn0:bar xmlns:xn0='testns' xmlns='testns2'><quux/></xn0:bar><xn1:baz xmlns:xn1='testns3' xmlns='testns4'><xn0:quux xmlns:xn0='testns'/></xn1:baz></foo>")
333
def testXMLNamespace(self):
334
e = domish.Element((None, "foo"),
335
attribs = {("http://www.w3.org/XML/1998/namespace",
337
self.assertEquals(e.toXml(), "<foo xml:lang='en_US'/>")
339
def testQualifiedAttributeGivenListOfPrefixes(self):
340
e = domish.Element((None, "foo"),
341
attribs = {("testns2", "bar"): "baz"})
342
self.assertEquals(e.toXml({"testns2": "qux"}),
343
"<foo xmlns:qux='testns2' qux:bar='baz'/>")
345
def testNSPrefix(self):
346
e = domish.Element((None, "foo"),
347
attribs = {("testns2", "bar"): "baz"})
348
c = e.addElement(("testns2", "qux"))
349
c[("testns2", "bar")] = "quux"
351
self.assertEquals(e.toXml(), "<foo xmlns:xn0='testns2' xn0:bar='baz'><xn0:qux xn0:bar='quux'/></foo>")
353
def testDefaultNSPrefix(self):
354
e = domish.Element((None, "foo"),
355
attribs = {("testns2", "bar"): "baz"})
356
c = e.addElement(("testns2", "qux"))
357
c[("testns2", "bar")] = "quux"
360
self.assertEquals(e.toXml(), "<foo xmlns:xn0='testns2' xn0:bar='baz'><xn0:qux xn0:bar='quux'><xn0:foo/></xn0:qux></foo>")
362
def testPrefixScope(self):
363
e = domish.Element(('testns', 'foo'))
365
self.assertEquals(e.toXml(prefixes={'testns': 'bar'},
366
prefixesInScope=['bar']),
369
def testLocalPrefixes(self):
370
e = domish.Element(('testns', 'foo'), localPrefixes={'bar': 'testns'})
371
self.assertEquals(e.toXml(), "<bar:foo xmlns:bar='testns'/>")
373
def testLocalPrefixesWithChild(self):
374
e = domish.Element(('testns', 'foo'), localPrefixes={'bar': 'testns'})
376
self.assertIdentical(e.baz.defaultUri, None)
377
self.assertEquals(e.toXml(), "<bar:foo xmlns:bar='testns'><baz/></bar:foo>")
379
def test_prefixesReuse(self):
381
Test that prefixes passed to serialization are not modified.
383
This test makes sure that passing a dictionary of prefixes repeatedly
384
to C{toXml} of elements does not cause serialization errors. A
385
previous implementation changed the passed in dictionary internally,
386
causing havoc later on.
388
prefixes = {'testns': 'foo'}
390
# test passing of dictionary
391
s = domish.SerializerClass(prefixes=prefixes)
392
self.assertNotIdentical(prefixes, s.prefixes)
394
# test proper serialization on prefixes reuse
395
e = domish.Element(('testns2', 'foo'),
396
localPrefixes={'quux': 'testns2'})
397
self.assertEquals("<quux:foo xmlns:quux='testns2'/>",
398
e.toXml(prefixes=prefixes))
399
e = domish.Element(('testns2', 'foo'))
400
self.assertEquals("<foo xmlns='testns2'/>",
401
e.toXml(prefixes=prefixes))
403
def testRawXMLSerialization(self):
404
e = domish.Element((None, "foo"))
405
e.addRawXml("<abc123>")
406
# The testcase below should NOT generate valid XML -- that's
407
# the whole point of using the raw XML call -- it's the callers
408
# responsiblity to ensure that the data inserted is valid
409
self.assertEquals(e.toXml(), "<foo><abc123></foo>")
411
def testRawXMLWithUnicodeSerialization(self):
412
e = domish.Element((None, "foo"))
413
e.addRawXml(u"<degree>\u00B0</degree>")
414
self.assertEquals(e.toXml(), u"<foo><degree>\u00B0</degree></foo>")
416
def testUnicodeSerialization(self):
417
e = domish.Element((None, "foo"))
418
e["test"] = u"my value\u0221e"
419
e.addContent(u"A degree symbol...\u00B0")
420
self.assertEquals(e.toXml(),
421
u"<foo test='my value\u0221e'>A degree symbol...\u00B0</foo>")