source: wokkel/test/test_muc.py @ 130:45c3ce4fe4eb

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

Another round of cleanups, renames. Also removed disco support.

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