source: wokkel/test/test_muc.py @ 129:29e517800b96

wokkel-muc-client-support-24
Last change on this file since 129:29e517800b96 was 129:29e517800b96, checked in by Ralph Meijer <ralphm@…>, 13 years ago

Whitespace and pyflakes changes.

File size: 15.7 KB
Line 
1# Copyright (c) 2003-2009 Ralph Meijer
2# See LICENSE for details.
3
4"""
5Tests for L{wokkel.muc}
6"""
7
8from zope.interface import verify
9
10from twisted.trial import unittest
11from twisted.internet import defer
12from twisted.words.xish import domish, xpath
13from twisted.words.protocols.jabber.jid import JID
14
15from wokkel import data_form, iwokkel, muc, disco
16from wokkel.test.helpers import XmlStreamStub
17
18from twisted.words.protocols.jabber.xmlstream import toResponse
19
20
21def calledAsync(fn):
22    """
23    Function wrapper that fires a deferred upon calling the given function.
24    """
25    d = defer.Deferred()
26
27    def func(*args, **kwargs):
28        try:
29            result = fn(*args, **kwargs)
30        except:
31            d.errback()
32        else:
33            d.callback(result)
34
35    return d, func
36
37
38
39class MucClientTest(unittest.TestCase):
40    timeout = 2
41
42    def setUp(self):
43        self.stub = XmlStreamStub()
44        self.protocol = muc.MUCClient()
45        self.protocol.xmlstream = self.stub.xmlstream
46        self.protocol.connectionInitialized()
47        self.test_room = 'test'
48        self.test_srv  = 'conference.example.org'
49        self.test_nick = 'Nick'
50
51        self.room_jid = JID(self.test_room+'@'+self.test_srv+'/'+self.test_nick)
52
53        self.user_jid = JID('test@jabber.org/Testing')
54
55
56    def _createRoom(self):
57        """A helper method to create a test room.
58        """
59        # create a room
60        self.current_room = muc.Room(self.test_room, self.test_srv, self.test_nick)
61        self.protocol._setRoom(self.current_room)
62
63
64    def test_interface(self):
65        """
66        Do instances of L{muc.MUCClient} provide L{iwokkel.IMUCClient}?
67        """
68        verify.verifyObject(iwokkel.IMUCClient, self.protocol)
69
70
71    def test_userJoinedRoom(self):
72        """The client receives presence from an entity joining the room.
73
74        This tests the class L{muc.UserPresence} and the userJoinedRoom event method.
75
76        The test sends the user presence and tests if the event method is called.
77
78        """
79        p = muc.UserPresence()
80        p['to'] = self.user_jid.full()
81        p['from'] = self.room_jid.full()
82
83        # create a room
84        self._createRoom()
85
86        def userPresence(room, user):
87            self.failUnless(room.name==self.test_room, 'Wrong room name')
88            self.failUnless(room.inRoster(user), 'User not in roster')
89
90
91        d, self.protocol.userJoinedRoom = calledAsync(userPresence)
92        self.stub.send(p)
93        return d
94
95
96    def test_groupChat(self):
97        """The client receives a groupchat message from an entity in the room.
98        """
99        m = muc.GroupChat('test@test.com',body='test')
100        m['from'] = self.room_jid.full()
101
102        self._createRoom()
103
104        def groupChat(room, user, message):
105            self.failUnless(message=='test', "Wrong group chat message")
106            self.failUnless(room.name==self.test_room, 'Wrong room name')
107
108
109        d, self.protocol.receivedGroupChat = calledAsync(groupChat)
110        self.stub.send(m)
111        return d
112
113
114    def test_discoServerSupport(self):
115        """Disco support from client to server.
116        """
117        test_srv = 'shakespeare.lit'
118
119        def cb(query):
120            # check namespace
121            self.failUnless(query.uri==disco.NS_INFO, 'Wrong namespace')
122
123
124        d = self.protocol.disco(test_srv)
125        d.addCallback(cb)
126
127        iq = self.stub.output[-1]
128
129        # send back a response
130        response = toResponse(iq, 'result')
131        response.addElement('query', disco.NS_INFO)
132        # need to add information to response
133        response.query.addChild(disco.DiscoFeature(muc.NS_MUC))
134        response.query.addChild(disco.DiscoIdentity(category='conference',
135                                                    name='Macbeth Chat Service',
136                                                    type='text'))
137
138        self.stub.send(response)
139        return d
140
141
142    def test_joinRoom(self):
143        """Joining a room
144        """
145
146        def cb(room):
147            self.assertEquals(self.test_room, room.name)
148
149        d = self.protocol.join(self.test_srv, self.test_room, self.test_nick)
150        d.addCallback(cb)
151
152        prs = self.stub.output[-1]
153        self.failUnless(prs.name=='presence', "Need to be presence")
154        self.failUnless(getattr(prs, 'x', None), 'No muc x element')
155
156        # send back user presence, they joined
157        response = muc.UserPresence(frm=self.test_room+'@'+self.test_srv+'/'+self.test_nick)
158        self.stub.send(response)
159        return d
160
161
162    def test_joinRoomForbidden(self):
163        """Client joining a room and getting a forbidden error.
164        """
165
166        def cb(error):
167
168            self.failUnless(error.value.mucCondition=='forbidden','Wrong muc condition')
169
170
171
172        d = self.protocol.join(self.test_srv, self.test_room, self.test_nick)
173        d.addBoth(cb)
174
175        prs = self.stub.output[-1]
176        self.failUnless(prs.name=='presence', "Need to be presence")
177        self.failUnless(getattr(prs, 'x', None), 'No muc x element')
178        # send back user presence, they joined
179
180        response = muc.PresenceError(error=muc.MUCError('auth',
181                                                        'forbidden'
182                                                        ),
183                                     frm=self.room_jid.full())
184        self.stub.send(response)
185        return d
186
187
188    def test_joinRoomBadJid(self):
189        """Client joining a room and getting a forbidden error.
190        """
191
192        def cb(error):
193
194            self.failUnless(error.value.mucCondition=='jid-malformed','Wrong muc condition')
195
196
197
198        d = self.protocol.join(self.test_srv, self.test_room, self.test_nick)
199        d.addBoth(cb)
200
201        prs = self.stub.output[-1]
202        self.failUnless(prs.name=='presence', "Need to be presence")
203        self.failUnless(getattr(prs, 'x', None), 'No muc x element')
204        # send back user presence, they joined
205
206        response = muc.PresenceError(error=muc.MUCError('modify',
207                                                        'jid-malformed'
208                                                        ),
209                                     frm=self.room_jid.full())
210        self.stub.send(response)
211        return d
212
213
214    def test_partRoom(self):
215        """Client leaves a room
216        """
217        def cb(left):
218            self.failUnless(left, 'did not leave room')
219
220
221        d = self.protocol.leave(self.room_jid)
222        d.addCallback(cb)
223
224        prs = self.stub.output[-1]
225
226        self.failUnless(prs['type']=='unavailable', 'Unavailable is not being sent')
227
228        response = prs
229        response['from'] = response['to']
230        response['to'] = 'test@jabber.org'
231
232        self.stub.send(response)
233        return d
234
235
236    def test_userPartsRoom(self):
237        """An entity leaves the room, a presence of type unavailable is received by the client.
238        """
239
240        p = muc.UnavailableUserPresence()
241        p['to'] = self.user_jid.full()
242        p['from'] = self.room_jid.full()
243
244        # create a room
245        self._createRoom()
246        # add user to room
247        u = muc.User(self.room_jid.resource)
248
249        room = self.protocol._getRoom(self.room_jid)
250        room.addUser(u)
251
252        def userPresence(room, user):
253            self.failUnless(room.name==self.test_room, 'Wrong room name')
254            self.failUnless(room.inRoster(user)==False, 'User in roster')
255
256        d, self.protocol.userLeftRoom = calledAsync(userPresence)
257        self.stub.send(p)
258        return d
259
260
261    def test_ban(self):
262        """Ban an entity in a room.
263        """
264        banned = JID('ban@jabber.org/TroubleMakger')
265        def cb(banned):
266            self.failUnless(banned, 'Did not ban user')
267
268
269        d = self.protocol.ban(self.room_jid, banned, self.user_jid, reason='Spam')
270        d.addCallback(cb)
271
272        iq = self.stub.output[-1]
273
274        self.failUnless(xpath.matches("/iq[@type='set' and @to='%s']/query/item[@affiliation='outcast']" % (self.room_jid.userhost(),), iq), 'Wrong ban stanza')
275
276        response = toResponse(iq, 'result')
277
278        self.stub.send(response)
279
280        return d
281
282
283    def test_kick(self):
284        """Kick an entity from a room.
285        """
286        kicked = JID('kick@jabber.org/TroubleMakger')
287        def cb(kicked):
288            self.failUnless(kicked, 'Did not kick user')
289
290
291        d = self.protocol.kick(self.room_jid, kicked, self.user_jid, reason='Spam')
292        d.addCallback(cb)
293
294        iq = self.stub.output[-1]
295
296        self.failUnless(xpath.matches("/iq[@type='set' and @to='%s']/query/item[@affiliation='none']" % (self.room_jid.userhost(),), iq), 'Wrong kick stanza')
297
298        response = toResponse(iq, 'result')
299
300        self.stub.send(response)
301
302        return d
303
304
305    def test_password(self):
306        """Sending a password via presence to a password protected room.
307        """
308
309        self.protocol.password(self.room_jid, 'secret')
310
311        prs = self.stub.output[-1]
312
313        self.failUnless(xpath.matches("/presence[@to='%s']/x/password[text()='secret']" % (self.room_jid.full(),), prs), 'Wrong presence stanza')
314
315
316    def test_history(self):
317        """Receiving history on room join.
318        """
319        m = muc.HistoryMessage(self.room_jid.userhost(), self.protocol._makeTimeStamp(), body='test')
320        m['from'] = self.room_jid.full()
321
322        self._createRoom()
323
324        def roomHistory(room, user, body, stamp, frm=None):
325            self.failUnless(body=='test', "wrong message body")
326            self.failUnless(stamp, 'Does not have a history stamp')
327
328
329        d, self.protocol.receivedHistory = calledAsync(roomHistory)
330        self.stub.send(m)
331        return d
332
333
334    def test_oneToOneChat(self):
335        """Converting a one to one chat to a multi-user chat.
336        """
337        archive = []
338        thread = "e0ffe42b28561960c6b12b944a092794b9683a38"
339        # create messages
340        msg = domish.Element((None, 'message'))
341        msg['to'] = 'testing@example.com'
342        msg['type'] = 'chat'
343        msg.addElement('body', None, 'test')
344        msg.addElement('thread', None, thread)
345
346        archive.append(msg)
347
348        msg = domish.Element((None, 'message'))
349        msg['to'] = 'testing2@example.com'
350        msg['type'] = 'chat'
351        msg.addElement('body', None, 'yo')
352        msg.addElement('thread', None, thread)
353
354        archive.append(msg)
355
356        self.protocol.history(self.room_jid, archive)
357
358
359        while len(self.stub.output)>0:
360            m = self.stub.output.pop()
361            # check for delay element
362            self.failUnless(m.name=='message', 'Wrong stanza')
363            self.failUnless(xpath.matches("/message/delay", m), 'Invalid history stanza')
364
365
366    def test_invite(self):
367        """Invite a user to a room
368        """
369        other_jid = 'test@jabber.org'
370
371        self.protocol.invite(other_jid, 'This is a test')
372
373        msg = self.stub.output[-1]
374
375        self.failUnless(xpath.matches("/message[@to='%s']/x/invite/reason" % (other_jid,), msg), 'Wrong message type')
376
377
378    def test_privateMessage(self):
379        """Send private messages to muc entities.
380        """
381        other_nick = self.room_jid.userhost()+'/OtherNick'
382
383        self.protocol.chat(other_nick, 'This is a test')
384
385        msg = self.stub.output[-1]
386
387        self.failUnless(xpath.matches("/message[@type='chat' and @to='%s']/body" % (other_nick,), msg), 'Wrong message type')
388
389
390    def test_register(self):
391        """Client registering with a room. http://xmpp.org/extensions/xep-0045.html#register
392
393        """
394
395        def cb(iq):
396            # check for a result
397            self.failUnless(iq['type']=='result', 'We did not get a result')
398
399        d = self.protocol.register(self.room_jid)
400        d.addCallback(cb)
401
402        iq = self.stub.output[-1]
403        self.failUnless(xpath.matches("/iq/query[@xmlns='%s']" % (muc.NS_REQUEST), iq), 'Invalid iq register request')
404
405        response = toResponse(iq, 'result')
406
407        self.stub.send(response)
408        return d
409
410
411    def test_voice(self):
412        """ Client requesting voice for a room.
413        """
414        self.protocol.voice(self.room_jid.userhost())
415
416        m = self.stub.output[-1]
417
418        self.failUnless(xpath.matches("/message/x[@type='submit']/field/value[text()='%s']" % (muc.NS_MUC_REQUEST,), m), 'Invalid voice message stanza')
419
420
421    def test_roomConfigure(self):
422        """ Default configure and changing the room name.
423        """
424
425        def cb(iq):
426            self.failUnless(iq['type']=='result', 'Not a result')
427
428
429        fields = []
430
431        fields.append(data_form.Field(label='Natural-Language Room Name',
432                                      var='muc#roomconfig_roomname',
433                                      value=self.test_room))
434
435        d = self.protocol.configure(self.room_jid.userhost(), fields)
436        d.addCallback(cb)
437
438        iq = self.stub.output[-1]
439        self.failUnless(xpath.matches("/iq/query[@xmlns='%s']/x"% (muc.NS_MUC_OWNER,), iq), 'Bad configure request')
440
441        response = toResponse(iq, 'result')
442        self.stub.send(response)
443        return d
444
445
446    def test_roomDestroy(self):
447        """ Destroy a room.
448        """
449
450        def cb(destroyed):
451            self.failUnless(destroyed==True, 'Room not destroyed.')
452
453        d = self.protocol.destroy(self.room_jid)
454        d.addCallback(cb)
455
456        iq = self.stub.output[-1]
457        self.failUnless(xpath.matches("/iq/query[@xmlns='%s']/destroy"% (muc.NS_MUC_OWNER,), iq), 'Bad configure request')
458
459        response = toResponse(iq, 'result')
460        self.stub.send(response)
461        return d
462
463
464    def test_nickChange(self):
465        """Send a nick change to the server.
466        """
467        test_nick = 'newNick'
468
469        self._createRoom()
470
471        def cb(room):
472            self.assertEquals(self.test_room, room.name)
473            self.assertEquals(test_nick, room.nick)
474
475        d = self.protocol.nick(self.room_jid, test_nick)
476        d.addCallback(cb)
477
478        prs = self.stub.output[-1]
479        self.failUnless(prs.name=='presence', "Need to be presence")
480        self.failUnless(getattr(prs, 'x', None), 'No muc x element')
481
482        # send back user presence, they joined
483        response = muc.UserPresence(frm=self.test_room+'@'+self.test_srv+'/'+test_nick)
484
485        self.stub.send(response)
486        return d
487
488
489    def test_grantVoice(self):
490        """Test granting voice to a user.
491
492        """
493        give_voice = JID('voice@jabber.org/TroubleMakger')
494        def cb(give_voice):
495            self.failUnless(give_voice, 'Did not give voice user')
496
497
498        d = self.protocol.grantVoice(self.user_jid, self.room_jid, give_voice)
499        d.addCallback(cb)
500
501        iq = self.stub.output[-1]
502
503        self.failUnless(xpath.matches("/iq[@type='set' and @to='%s']/query/item[@role='participant']" % (self.room_jid.userhost(),), iq), 'Wrong voice stanza')
504
505        response = toResponse(iq, 'result')
506
507        self.stub.send(response)
508
509        return d
510
511
512    def test_changeStatus(self):
513        """Change status
514        """
515        self._createRoom()
516        r = self.protocol._getRoom(self.room_jid)
517        u = muc.User(self.room_jid.resource)
518        r.addUser(u)
519
520        def cb(room):
521            self.assertEquals(self.test_room, room.name)
522            u = room.getUser(self.room_jid.resource)
523            self.failUnless(u is not None, 'User not found')
524            self.failUnless(u.status == 'testing MUC', 'Wrong status')
525            self.failUnless(u.show == 'xa', 'Wrong show')
526
527        d = self.protocol.status(self.room_jid, 'xa', 'testing MUC')
528        d.addCallback(cb)
529
530        prs = self.stub.output[-1]
531
532        self.failUnless(prs.name=='presence', "Need to be presence")
533        self.failUnless(getattr(prs, 'x', None), 'No muc x element')
534
535        # send back user presence, they joined
536        response = muc.UserPresence(frm=self.room_jid.full())
537        response.addElement('show', None, 'xa')
538        response.addElement('status', None, 'testing MUC')
539        self.stub.send(response)
540        return d
Note: See TracBrowser for help on using the repository browser.