1
# -*- test-case-name: twisted.web.test.test_domhelpers -*-
2
# Copyright (c) 2001-2009 Twisted Matrix Laboratories.
3
# See LICENSE for details.
6
Specific tests for (some of) the methods in L{twisted.web.domhelpers}.
9
from xml.dom import minidom
11
from twisted.trial.unittest import TestCase
13
from twisted.web import microdom
15
from twisted.web import domhelpers
18
class DOMHelpersTestsMixin:
20
A mixin for L{TestCase} subclasses which defines test methods for
21
domhelpers functionality based on a DOM creation function provided by a
26
def test_getElementsByTagName(self):
27
doc1 = self.dom.parseString('<foo/>')
28
actual=domhelpers.getElementsByTagName(doc1, 'foo')[0].nodeName
30
self.assertEquals(actual, expected)
31
el1=doc1.documentElement
32
actual=domhelpers.getElementsByTagName(el1, 'foo')[0].nodeName
33
self.assertEqual(actual, expected)
35
doc2_xml='<a><foo in="a"/><b><foo in="b"/></b><c><foo in="c"/></c><foo in="d"/><foo in="ef"/><g><foo in="g"/><h><foo in="h"/></h></g></a>'
36
doc2 = self.dom.parseString(doc2_xml)
37
tag_list=domhelpers.getElementsByTagName(doc2, 'foo')
38
actual=''.join([node.getAttribute('in') for node in tag_list])
40
self.assertEquals(actual, expected)
41
el2=doc2.documentElement
42
tag_list=domhelpers.getElementsByTagName(el2, 'foo')
43
actual=''.join([node.getAttribute('in') for node in tag_list])
44
self.assertEqual(actual, expected)
63
doc3 = self.dom.parseString(doc3_xml)
64
tag_list=domhelpers.getElementsByTagName(doc3, 'foo')
65
actual=''.join([node.getAttribute('in') for node in tag_list])
67
self.assertEquals(actual, expected)
68
el3=doc3.documentElement
69
tag_list=domhelpers.getElementsByTagName(el3, 'foo')
70
actual=''.join([node.getAttribute('in') for node in tag_list])
71
self.assertEqual(actual, expected)
73
doc4_xml='<foo><bar></bar><baz><foo/></baz></foo>'
74
doc4 = self.dom.parseString(doc4_xml)
75
actual=domhelpers.getElementsByTagName(doc4, 'foo')
76
root=doc4.documentElement
77
expected=[root, root.childNodes[-1].childNodes[0]]
78
self.assertEquals(actual, expected)
79
actual=domhelpers.getElementsByTagName(root, 'foo')
80
self.assertEqual(actual, expected)
83
def test_gatherTextNodes(self):
84
doc1 = self.dom.parseString('<a>foo</a>')
85
actual=domhelpers.gatherTextNodes(doc1)
87
self.assertEqual(actual, expected)
88
actual=domhelpers.gatherTextNodes(doc1.documentElement)
89
self.assertEqual(actual, expected)
91
doc2_xml='<a>a<b>b</b><c>c</c>def<g>g<h>h</h></g></a>'
92
doc2 = self.dom.parseString(doc2_xml)
93
actual=domhelpers.gatherTextNodes(doc2)
95
self.assertEqual(actual, expected)
96
actual=domhelpers.gatherTextNodes(doc2.documentElement)
97
self.assertEqual(actual, expected)
99
doc3_xml=('<a>a<b>b<d>d<g>g</g><h>h</h></d><e>e<i>i</i></e></b>' +
100
'<c>c<f>f<j>j</j></f></c></a>')
101
doc3 = self.dom.parseString(doc3_xml)
102
actual=domhelpers.gatherTextNodes(doc3)
103
expected='abdgheicfj'
104
self.assertEqual(actual, expected)
105
actual=domhelpers.gatherTextNodes(doc3.documentElement)
106
self.assertEqual(actual, expected)
108
def test_clearNode(self):
109
doc1 = self.dom.parseString('<a><b><c><d/></c></b></a>')
110
a_node=doc1.documentElement
111
domhelpers.clearNode(a_node)
114
self.dom.Element('a').toxml())
116
doc2 = self.dom.parseString('<a><b><c><d/></c></b></a>')
117
b_node=doc2.documentElement.childNodes[0]
118
domhelpers.clearNode(b_node)
119
actual=doc2.documentElement.toxml()
120
expected = self.dom.Element('a')
121
expected.appendChild(self.dom.Element('b'))
122
self.assertEqual(actual, expected.toxml())
126
doc1 = self.dom.parseString('<a><b id="bar"/><c class="foo"/></a>')
127
node=domhelpers.get(doc1, "foo")
129
expected = self.dom.Element('c')
130
expected.setAttribute('class', 'foo')
131
self.assertEqual(actual, expected.toxml())
133
node=domhelpers.get(doc1, "bar")
135
expected = self.dom.Element('b')
136
expected.setAttribute('id', 'bar')
137
self.assertEqual(actual, expected.toxml())
139
self.assertRaises(domhelpers.NodeLookupError,
144
def test_getIfExists(self):
145
doc1 = self.dom.parseString('<a><b id="bar"/><c class="foo"/></a>')
146
node=domhelpers.getIfExists(doc1, "foo")
148
expected = self.dom.Element('c')
149
expected.setAttribute('class', 'foo')
150
self.assertEqual(actual, expected.toxml())
152
node=domhelpers.getIfExists(doc1, "pzork")
153
self.assertIdentical(node, None)
156
def test_getAndClear(self):
157
doc1 = self.dom.parseString('<a><b id="foo"><c></c></b></a>')
158
node=domhelpers.getAndClear(doc1, "foo")
160
expected = self.dom.Element('b')
161
expected.setAttribute('id', 'foo')
162
self.assertEqual(actual, expected.toxml())
165
def test_locateNodes(self):
166
doc1 = self.dom.parseString('<a><b foo="olive"><c foo="olive"/></b><d foo="poopy"/></a>')
167
node_list=domhelpers.locateNodes(
168
doc1.childNodes, 'foo', 'olive', noNesting=1)
169
actual=''.join([node.toxml() for node in node_list])
170
expected = self.dom.Element('b')
171
expected.setAttribute('foo', 'olive')
172
c = self.dom.Element('c')
173
c.setAttribute('foo', 'olive')
174
expected.appendChild(c)
176
self.assertEqual(actual, expected.toxml())
178
node_list=domhelpers.locateNodes(
179
doc1.childNodes, 'foo', 'olive', noNesting=0)
180
actual=''.join([node.toxml() for node in node_list])
181
self.assertEqual(actual, expected.toxml() + c.toxml())
184
def test_getParents(self):
185
doc1 = self.dom.parseString('<a><b><c><d/></c><e/></b><f/></a>')
186
node_list = domhelpers.getParents(
187
doc1.childNodes[0].childNodes[0].childNodes[0])
188
actual = ''.join([node.tagName for node in node_list
189
if hasattr(node, 'tagName')])
190
self.assertEqual(actual, 'cba')
193
def test_findElementsWithAttribute(self):
194
doc1 = self.dom.parseString('<a foo="1"><b foo="2"/><c foo="1"/><d/></a>')
195
node_list = domhelpers.findElementsWithAttribute(doc1, 'foo')
196
actual = ''.join([node.tagName for node in node_list])
197
self.assertEqual(actual, 'abc')
199
node_list = domhelpers.findElementsWithAttribute(doc1, 'foo', '1')
200
actual = ''.join([node.tagName for node in node_list])
201
self.assertEqual(actual, 'ac')
204
def test_findNodesNamed(self):
205
doc1 = self.dom.parseString('<doc><foo/><bar/><foo>a</foo></doc>')
206
node_list = domhelpers.findNodesNamed(doc1, 'foo')
207
actual = len(node_list)
208
self.assertEqual(actual, 2)
210
# NOT SURE WHAT THESE ARE SUPPOSED TO DO..
211
# def test_RawText FIXME
212
# def test_superSetAttribute FIXME
213
# def test_superPrependAttribute FIXME
214
# def test_superAppendAttribute FIXME
215
# def test_substitute FIXME
217
def test_escape(self):
218
j='this string " contains many & characters> xml< won\'t like'
219
expected='this string " contains many & characters> xml< won\'t like'
220
self.assertEqual(domhelpers.escape(j), expected)
222
def test_unescape(self):
223
j='this string " has && entities > < and some characters xml won\'t like<'
224
expected='this string " has && entities > < and some characters xml won\'t like<'
225
self.assertEqual(domhelpers.unescape(j), expected)
228
def test_getNodeText(self):
230
L{getNodeText} returns the concatenation of all the text data at or
231
beneath the node passed to it.
233
node = self.dom.parseString('<foo><bar>baz</bar><bar>quux</bar></foo>')
234
self.assertEqual(domhelpers.getNodeText(node), "bazquux")
238
class MicroDOMHelpersTests(DOMHelpersTestsMixin, TestCase):
241
def test_gatherTextNodesDropsWhitespace(self):
243
Microdom discards whitespace-only text nodes, so L{gatherTextNodes}
244
returns only the text from nodes which had non-whitespace characters.
254
doc4 = self.dom.parseString(doc4_xml)
255
actual = domhelpers.gatherTextNodes(doc4)
256
expected = '\n stuff\n '
257
self.assertEqual(actual, expected)
258
actual = domhelpers.gatherTextNodes(doc4.documentElement)
259
self.assertEqual(actual, expected)
262
def test_textEntitiesNotDecoded(self):
264
Microdom does not decode entities in text nodes.
266
doc5_xml='<x>Souffl&</x>'
267
doc5 = self.dom.parseString(doc5_xml)
268
actual=domhelpers.gatherTextNodes(doc5)
269
expected='Souffl&'
270
self.assertEqual(actual, expected)
271
actual=domhelpers.gatherTextNodes(doc5.documentElement)
272
self.assertEqual(actual, expected)
276
class MiniDOMHelpersTests(DOMHelpersTestsMixin, TestCase):
279
def test_textEntitiesDecoded(self):
281
Minidom does decode entities in text nodes.
283
doc5_xml='<x>Souffl&</x>'
284
doc5 = self.dom.parseString(doc5_xml)
285
actual=domhelpers.gatherTextNodes(doc5)
287
self.assertEqual(actual, expected)
288
actual=domhelpers.gatherTextNodes(doc5.documentElement)
289
self.assertEqual(actual, expected)
292
def test_getNodeUnicodeText(self):
294
L{domhelpers.getNodeText} returns a C{unicode} string when text
295
nodes are represented in the DOM with unicode, whether or not there
296
are non-ASCII characters present.
298
node = self.dom.parseString("<foo>bar</foo>")
299
text = domhelpers.getNodeText(node)
300
self.assertEqual(text, u"bar")
301
self.assertIsInstance(text, unicode)
303
node = self.dom.parseString(u"<foo>\N{SNOWMAN}</foo>".encode('utf-8'))
304
text = domhelpers.getNodeText(node)
305
self.assertEqual(text, u"\N{SNOWMAN}")
306
self.assertIsInstance(text, unicode)