source: wokkel/test/test_generic.py @ 185:a7e10201fb3c

Last change on this file since 185:a7e10201fb3c was 185:a7e10201fb3c, checked in by Ralph Meijer <ralphm@…>, 7 years ago

Do proper fallback for Request.stanzaType.

If stanzaType is not passed to the constructor of
wokkel.generic.Request, it should default to the value in the class
variable, not get.

Author: ralphm
Fixes: #80

  • Property exe set to *
File size: 10.8 KB
Line 
1# Copyright (c) Ralph Meijer.
2# See LICENSE for details.
3
4"""
5Tests for L{wokkel.generic}.
6"""
7
8import re
9
10from twisted.python import deprecate
11from twisted.python.versions import Version
12from twisted.trial import unittest
13from twisted.trial.util import suppress as SUPPRESS
14from twisted.words.xish import domish
15from twisted.words.protocols.jabber.jid import JID
16
17from wokkel import generic
18from wokkel.test.helpers import XmlStreamStub
19
20NS_VERSION = 'jabber:iq:version'
21
22class VersionHandlerTest(unittest.TestCase):
23    """
24    Tests for L{wokkel.generic.VersionHandler}.
25    """
26
27    def test_onVersion(self):
28        """
29        Test response to incoming version request.
30        """
31        self.stub = XmlStreamStub()
32        self.protocol = generic.VersionHandler('Test', '0.1.0')
33        self.protocol.xmlstream = self.stub.xmlstream
34        self.protocol.send = self.stub.xmlstream.send
35        self.protocol.connectionInitialized()
36
37        iq = domish.Element((None, 'iq'))
38        iq['from'] = 'user@example.org/Home'
39        iq['to'] = 'example.org'
40        iq['type'] = 'get'
41        iq.addElement((NS_VERSION, 'query'))
42        self.stub.send(iq)
43
44        response = self.stub.output[-1]
45        self.assertEquals('user@example.org/Home', response['to'])
46        self.assertEquals('example.org', response['from'])
47        self.assertEquals('result', response['type'])
48        self.assertEquals(NS_VERSION, response.query.uri)
49        elements = list(domish.generateElementsQNamed(response.query.children,
50                                                      'name', NS_VERSION))
51        self.assertEquals(1, len(elements))
52        self.assertEquals('Test', unicode(elements[0]))
53        elements = list(domish.generateElementsQNamed(response.query.children,
54                                                      'version', NS_VERSION))
55        self.assertEquals(1, len(elements))
56        self.assertEquals('0.1.0', unicode(elements[0]))
57
58
59
60class XmlPipeTest(unittest.TestCase):
61    """
62    Tests for L{wokkel.generic.XmlPipe}.
63    """
64
65    def setUp(self):
66        self.pipe = generic.XmlPipe()
67
68
69    def test_sendFromSource(self):
70        """
71        Send an element from the source and observe it from the sink.
72        """
73        def cb(obj):
74            called.append(obj)
75
76        called = []
77        self.pipe.sink.addObserver('/test[@xmlns="testns"]', cb)
78        element = domish.Element(('testns', 'test'))
79        self.pipe.source.send(element)
80        self.assertEquals([element], called)
81
82
83    def test_sendFromSink(self):
84        """
85        Send an element from the sink and observe it from the source.
86        """
87        def cb(obj):
88            called.append(obj)
89
90        called = []
91        self.pipe.source.addObserver('/test[@xmlns="testns"]', cb)
92        element = domish.Element(('testns', 'test'))
93        self.pipe.sink.send(element)
94        self.assertEquals([element], called)
95
96
97
98class StanzaTest(unittest.TestCase):
99    """
100    Tests for L{generic.Stanza}.
101    """
102
103    def test_fromElement(self):
104        xml = """
105        <message type='chat' from='other@example.org' to='user@example.org'/>
106        """
107
108        stanza = generic.Stanza.fromElement(generic.parseXml(xml))
109        self.assertEqual('chat', stanza.stanzaType)
110        self.assertEqual(JID('other@example.org'), stanza.sender)
111        self.assertEqual(JID('user@example.org'), stanza.recipient)
112
113
114    def test_fromElementChildParser(self):
115        """
116        Child elements for which no parser is defined are ignored.
117        """
118        xml = """
119        <message from='other@example.org' to='user@example.org'>
120          <x xmlns='http://example.org/'/>
121        </message>
122        """
123
124        class Message(generic.Stanza):
125            childParsers = {('http://example.org/', 'x'): '_childParser_x'}
126            elements = []
127
128            def _childParser_x(self, element):
129                self.elements.append(element)
130
131        message = Message.fromElement(generic.parseXml(xml))
132        self.assertEqual(1, len(message.elements))
133
134
135    def test_fromElementChildParserAll(self):
136        """
137        Child elements for which no parser is defined are ignored.
138        """
139        xml = """
140        <message from='other@example.org' to='user@example.org'>
141          <x xmlns='http://example.org/'/>
142        </message>
143        """
144
145        class Message(generic.Stanza):
146            childParsers = {None: '_childParser'}
147            elements = []
148
149            def _childParser(self, element):
150                self.elements.append(element)
151
152        message = Message.fromElement(generic.parseXml(xml))
153        self.assertEqual(1, len(message.elements))
154
155
156    def test_fromElementChildParserUnknown(self):
157        """
158        Child elements for which no parser is defined are ignored.
159        """
160        xml = """
161        <message from='other@example.org' to='user@example.org'>
162          <x xmlns='http://example.org/'/>
163        </message>
164        """
165        generic.Stanza.fromElement(generic.parseXml(xml))
166
167
168
169
170class RequestTest(unittest.TestCase):
171    """
172    Tests for L{generic.Request}.
173    """
174
175    def setUp(self):
176        self.request = generic.Request()
177
178
179    def test_requestParser(self):
180        """
181        The request's child element is passed to requestParser.
182        """
183        xml = """
184        <iq type='get'>
185          <query xmlns='jabber:iq:version'/>
186        </iq>
187        """
188
189        class VersionRequest(generic.Request):
190            elements = []
191
192            def parseRequest(self, element):
193                self.elements.append((element.uri, element.name))
194
195        request = VersionRequest.fromElement(generic.parseXml(xml))
196        self.assertEqual([(NS_VERSION, 'query')], request.elements)
197
198
199    def test_toElementStanzaKind(self):
200        """
201        A request is an iq stanza.
202        """
203        element = self.request.toElement()
204        self.assertIdentical(None, element.uri)
205        self.assertEquals('iq', element.name)
206
207
208    def test_toElementStanzaType(self):
209        """
210        The request has type 'get'.
211        """
212        self.assertEquals('get', self.request.stanzaType)
213        element = self.request.toElement()
214        self.assertEquals('get', element.getAttribute('type'))
215
216
217    def test_toElementStanzaTypeSet(self):
218        """
219        The request has type 'set'.
220        """
221        self.request.stanzaType = 'set'
222        element = self.request.toElement()
223        self.assertEquals('set', element.getAttribute('type'))
224
225
226    def test_toElementStanzaID(self):
227        """
228        A request, when rendered, has an identifier.
229        """
230        element = self.request.toElement()
231        self.assertNotIdentical(None, self.request.stanzaID)
232        self.assertEquals(self.request.stanzaID, element.getAttribute('id'))
233
234
235    def test_toElementRecipient(self):
236        """
237        A request without recipient, has no 'to' attribute.
238        """
239        self.request = generic.Request(recipient=JID('other@example.org'))
240        self.assertEquals(JID('other@example.org'), self.request.recipient)
241        element = self.request.toElement()
242        self.assertEquals(u'other@example.org', element.getAttribute('to'))
243
244
245    def test_toElementRecipientNone(self):
246        """
247        A request without recipient, has no 'to' attribute.
248        """
249        element = self.request.toElement()
250        self.assertFalse(element.hasAttribute('to'))
251
252
253    def test_toElementSender(self):
254        """
255        A request with sender, has a 'from' attribute.
256        """
257        self.request = generic.Request(sender=JID('user@example.org'))
258        self.assertEquals(JID('user@example.org'), self.request.sender)
259        element = self.request.toElement()
260        self.assertEquals(u'user@example.org', element.getAttribute('from'))
261
262
263    def test_toElementSenderNone(self):
264        """
265        A request without sender, has no 'from' attribute.
266        """
267        element = self.request.toElement()
268        self.assertFalse(element.hasAttribute('from'))
269
270
271    def test_timeoutDefault(self):
272        """
273        The default is no timeout.
274        """
275        self.assertIdentical(None, self.request.timeout)
276
277
278    def test_stanzaTypeInit(self):
279        """
280        If stanzaType is passed in __init__, it overrides the class variable.
281        """
282
283        class SetRequest(generic.Request):
284            stanzaType = 'set'
285
286        request = SetRequest(stanzaType='get')
287        self.assertEqual('get', request.stanzaType)
288
289
290    def test_stanzaTypeClass(self):
291        """
292        If stanzaType is not passed in __init__, the class variable is used.
293        """
294
295        class SetRequest(generic.Request):
296            stanzaType = 'set'
297
298        request = SetRequest()
299        self.assertEqual('set', request.stanzaType)
300
301
302
303class PrepareIDNNameTests(unittest.TestCase):
304    """
305    Tests for L{wokkel.generic.prepareIDNName}.
306    """
307
308    suppress = [SUPPRESS(category=DeprecationWarning,
309                         message=re.escape(
310                             deprecate.getDeprecationWarningString(
311                                 generic.prepareIDNName,
312                                 Version("Wokkel", 0, 8, 0),
313                                 replacement="unicode.encode('idna')")))]
314
315
316    def test_deprecated(self):
317        """
318        prepareIDNName is deprecated.
319        """
320        self.callDeprecated((Version("Wokkel", 0, 8, 0),
321                             "unicode.encode('idna')"),
322                            generic.prepareIDNName, (b"example.com"))
323    test_deprecated.suppress = []
324
325
326    def test_bytestring(self):
327        """
328        An ASCII-encoded byte string is left as-is.
329        """
330        name = b"example.com"
331        result = generic.prepareIDNName(name)
332        self.assertEqual(b"example.com", result)
333
334
335    def test_unicode(self):
336        """
337        A unicode all-ASCII name is converted to an ASCII byte string.
338        """
339        name = u"example.com"
340        result = generic.prepareIDNName(name)
341        self.assertEqual(b"example.com", result)
342
343
344    def test_unicodeNonASCII(self):
345        """
346        A unicode with non-ASCII is converted to its ACE equivalent.
347        """
348        name = u"\u00e9chec.example.com"
349        result = generic.prepareIDNName(name)
350        self.assertEqual(b"xn--chec-9oa.example.com", result)
351
352
353    def test_unicodeHalfwidthIdeographicFullStop(self):
354        """
355        Exotic dots in unicode names are converted to Full Stop.
356        """
357        name = u"\u00e9chec.example\uff61com"
358        result = generic.prepareIDNName(name)
359        self.assertEqual(b"xn--chec-9oa.example.com", result)
360
361
362    def test_unicodeTrailingDot(self):
363        """
364        Unicode names with trailing dots retain the trailing dot.
365
366        L{encodings.idna.ToASCII} doesn't allow the empty string as the input,
367        hence the implementation needs to strip a trailing dot, and re-add it
368        after encoding the labels.
369        """
370        name = u"example.com."
371        result = generic.prepareIDNName(name)
372        self.assertEqual(b"example.com.", result)
Note: See TracBrowser for help on using the repository browser.