source: wokkel/test/test_muc.py @ 120:9548851ca5ac

wokkel-muc-client-support-24
Last change on this file since 120:9548851ca5ac was 120:9548851ca5ac, checked in by Christopher Zorn <tofu@…>, 14 years ago

implement error conditions

File size: 13.1 KB
Line 
1# Copyright (c) 2003-2008 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 import error
14from twisted.words.protocols.jabber.jid import JID
15
16from wokkel import data_form, iwokkel, muc, shim, disco
17from wokkel.generic import parseXml
18from wokkel.test.helpers import XmlStreamStub
19
20try:
21    from twisted.words.protocols.jabber.xmlstream import toResponse
22except ImportError:
23    from wokkel.compat import toResponse
24
25
26def calledAsync(fn):
27    """
28    Function wrapper that fires a deferred upon calling the given function.
29    """
30    d = defer.Deferred()
31
32    def func(*args, **kwargs):
33        try:
34            result = fn(*args, **kwargs)
35        except:
36            d.errback()
37        else:
38            d.callback(result)
39
40    return d, func
41
42
43class MucClientTest(unittest.TestCase):
44    timeout = 2
45
46    def setUp(self):
47        self.stub = XmlStreamStub()
48        self.protocol = muc.MUCClient()
49        self.protocol.xmlstream = self.stub.xmlstream
50        self.protocol.connectionInitialized()
51        self.test_room = 'test'
52        self.test_srv  = 'conference.example.org'
53        self.test_nick = 'Nick'
54
55        self.room_jid = JID(self.test_room+'@'+self.test_srv+'/'+self.test_nick)
56
57        self.user_jid = JID('test@jabber.org/Testing')
58
59    def _createRoom(self):
60        """A helper method to create a test room.
61        """
62        # create a room
63        self.current_room = muc.Room(self.test_room, self.test_srv, self.test_nick)
64        self.protocol._setRoom(self.current_room)
65
66
67    def test_interface(self):
68        """
69        Do instances of L{muc.MUCClient} provide L{iwokkel.IMUCClient}?
70        """
71        verify.verifyObject(iwokkel.IMUCClient, self.protocol)
72
73
74    def test_userJoinedRoom(self):
75        """The client receives presence from an entity joining the room.
76        """
77        p = muc.UserPresence()
78        p['to'] = self.user_jid.full()
79        p['from'] = self.room_jid.full()
80
81        # create a room
82        self._createRoom()
83
84        def userPresence(room, user):
85            self.failUnless(room.name==self.test_room, 'Wrong room name')
86            self.failUnless(room.inRoster(user), 'User not in roster')
87                           
88       
89        d, self.protocol.userJoinedRoom = calledAsync(userPresence)
90        self.stub.send(p)
91        return d
92
93
94    def test_groupChat(self):
95        """The client receives a groupchat message from an entity in the room.
96        """
97        m = muc.GroupChat('test@test.com',body='test')
98        m['from'] = self.room_jid.full()
99
100        self._createRoom()
101
102        def groupChat(room, user, message):
103            self.failUnless(message=='test', "Wrong group chat message")
104            self.failUnless(room.name==self.test_room, 'Wrong room name')
105                           
106       
107        d, self.protocol.receivedGroupChat = calledAsync(groupChat)
108        self.stub.send(m)
109        return d
110
111
112    def test_discoServerSupport(self):
113        """Disco support from client to server.
114        """
115        test_srv = 'shakespeare.lit'
116
117        def cb(query):
118            # check namespace
119            self.failUnless(query.uri==disco.NS_INFO, 'Wrong namespace')
120           
121
122        d = self.protocol.disco(test_srv)
123        d.addCallback(cb)
124
125        iq = self.stub.output[-1]
126       
127        # send back a response
128        response = toResponse(iq, 'result')
129        response.addElement('query', disco.NS_INFO)
130        # need to add information to response
131        response.query.addChild(disco.DiscoFeature(muc.NS_MUC))
132        response.query.addChild(disco.DiscoIdentity(category='conference',
133                                                    name='Macbeth Chat Service',
134                                                    type='text'))
135       
136        self.stub.send(response)
137        return d
138       
139
140       
141    def test_joinRoom(self):
142        """Joining a room
143        """
144       
145        def cb(room):
146            self.assertEquals(self.test_room, room.name)
147
148        d = self.protocol.join(self.test_srv, self.test_room, self.test_nick)
149        d.addCallback(cb)
150
151        prs = self.stub.output[-1]
152        self.failUnless(prs.name=='presence', "Need to be presence")
153        self.failUnless(getattr(prs, 'x', None), 'No muc x element')
154
155        # send back user presence, they joined       
156        response = muc.UserPresence(frm=self.test_room+'@'+self.test_srv+'/'+self.test_nick)
157        self.stub.send(response)
158        return d
159
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    def test_partRoom(self):
188        """Client leaves a room
189        """
190        def cb(left):
191            self.failUnless(left, 'did not leave room')
192
193
194        d = self.protocol.leave(self.room_jid)
195        d.addCallback(cb)
196
197        prs = self.stub.output[-1]
198       
199        self.failUnless(prs['type']=='unavailable', 'Unavailable is not being sent')
200       
201        response = prs
202        response['from'] = response['to']
203        response['to'] = 'test@jabber.org'
204
205        self.stub.send(response)
206        return d
207       
208
209    def test_userPartsRoom(self):
210        """An entity leaves the room, a presence of type unavailable is received by the client.
211        """
212
213        p = muc.UnavailableUserPresence()
214        p['to'] = self.user_jid.full()
215        p['from'] = self.room_jid.full()
216
217        # create a room
218        self._createRoom()
219        # add user to room
220        u = muc.User(self.room_jid.resource)
221
222        room = self.protocol._getRoom(self.room_jid)
223        room.addUser(u)
224
225        def userPresence(room, user):
226            self.failUnless(room.name==self.test_room, 'Wrong room name')
227            self.failUnless(room.inRoster(user)==False, 'User in roster')
228                           
229        d, self.protocol.userLeftRoom = calledAsync(userPresence)
230        self.stub.send(p)
231        return d
232       
233
234    def test_ban(self):
235        """Ban an entity in a room.
236        """
237        banned = JID('ban@jabber.org/TroubleMakger')
238        def cb(banned):
239            self.failUnless(banned, 'Did not ban user')
240
241           
242        d = self.protocol.ban(self.room_jid, banned, self.user_jid, reason='Spam')
243        d.addCallback(cb)
244
245        iq = self.stub.output[-1]
246       
247        self.failUnless(xpath.matches("/iq[@type='set' and @to='%s']/query/item[@affiliation='outcast']" % (self.room_jid.userhost(),), iq), 'Wrong ban stanza')
248
249        response = toResponse(iq, 'result')
250
251        self.stub.send(response)
252
253        return d
254
255
256    def test_kick(self):
257        """Kick an entity from a room.
258        """
259        kicked = JID('kick@jabber.org/TroubleMakger')
260        def cb(kicked):
261            self.failUnless(kicked, 'Did not kick user')
262
263           
264        d = self.protocol.kick(self.room_jid, kicked, self.user_jid, reason='Spam')
265        d.addCallback(cb)
266
267        iq = self.stub.output[-1]
268       
269        self.failUnless(xpath.matches("/iq[@type='set' and @to='%s']/query/item[@affiliation='none']" % (self.room_jid.userhost(),), iq), 'Wrong kick stanza')
270
271        response = toResponse(iq, 'result')
272
273        self.stub.send(response)
274
275        return d
276
277       
278
279    def test_password(self):
280        """Sending a password via presence to a password protected room.
281        """
282       
283        self.protocol.password(self.room_jid, 'secret')
284       
285        prs = self.stub.output[-1]
286       
287        self.failUnless(xpath.matches("/presence[@to='%s']/x/password[text()='secret']" % (self.room_jid.full(),), prs), 'Wrong presence stanza')
288
289
290    def test_history(self):
291        """Receiving history on room join.
292        """
293        m = muc.HistoryMessage(self.room_jid.userhost(), self.protocol._makeTimeStamp(), body='test')
294        m['from'] = self.room_jid.full()
295       
296        self._createRoom()
297
298        def roomHistory(room, user, body, stamp, frm=None):
299            self.failUnless(body=='test', "wrong message body")
300            self.failUnless(stamp, 'Does not have a history stamp')
301                   
302
303        d, self.protocol.receivedHistory = calledAsync(roomHistory)
304        self.stub.send(m)
305        return d
306
307
308    def test_oneToOneChat(self):
309        """Converting a one to one chat to a multi-user chat.
310        """
311        archive = []
312        thread = "e0ffe42b28561960c6b12b944a092794b9683a38"
313        # create messages
314        msg = domish.Element((None, 'message'))
315        msg['to'] = 'testing@example.com'
316        msg['type'] = 'chat'
317        msg.addElement('body', None, 'test')
318        msg.addElement('thread', None, thread)
319
320        archive.append(msg)
321
322        msg = domish.Element((None, 'message'))
323        msg['to'] = 'testing2@example.com'
324        msg['type'] = 'chat'
325        msg.addElement('body', None, 'yo')
326        msg.addElement('thread', None, thread)
327
328        archive.append(msg)
329
330        self.protocol.history(self.room_jid.userhost(), archive)
331
332
333        while len(self.stub.output)>0:
334            m = self.stub.output.pop()
335            # check for delay element
336            self.failUnless(m.name=='message', 'Wrong stanza')
337            self.failUnless(xpath.matches("/message/delay", m), 'Invalid history stanza')
338       
339
340    def test_invite(self):
341        """Invite a user to a room
342        """
343        other_jid = 'test@jabber.org'
344
345        self.protocol.invite(other_jid, 'This is a test')
346
347        msg = self.stub.output[-1]
348
349        self.failUnless(xpath.matches("/message[@to='%s']/x/invite/reason" % (other_jid,), msg), 'Wrong message type')
350
351
352       
353    def test_privateMessage(self):
354        """Send private messages to muc entities.
355        """
356        other_nick = self.room_jid.userhost()+'/OtherNick'
357
358        self.protocol.chat(other_nick, 'This is a test')
359
360        msg = self.stub.output[-1]
361
362        self.failUnless(xpath.matches("/message[@type='chat' and @to='%s']/body" % (other_nick,), msg), 'Wrong message type')
363
364
365    def test_register(self):
366        """Client registering with a room. http://xmpp.org/extensions/xep-0045.html#register
367
368        """
369       
370        def cb(iq):
371            # check for a result
372            self.failUnless(iq['type']=='result', 'We did not get a result')
373       
374        d = self.protocol.register(self.room_jid.userhost())
375        d.addCallback(cb)
376
377        iq = self.stub.output[-1]
378        self.failUnless(xpath.matches("/iq/query[@xmlns='%s']" % (muc.NS_REQUEST), iq), 'Invalid iq register request')
379       
380        response = toResponse(iq, 'result')
381       
382        self.stub.send(response)
383        return d
384
385    def test_voice(self):
386        """ Client requesting voice for a room.
387        """
388        self.protocol.voice(self.room_jid.userhost())
389
390        m = self.stub.output[-1]
391       
392        self.failUnless(xpath.matches("/message/x[@type='submit']/field/value[text()='%s']" % (muc.NS_MUC_REQUEST,), m), 'Invalid voice message stanza')
393
394
395    def test_roomConfigure(self):
396        """ Default configure and changing the room name.
397        """
398
399        def cb(iq):
400            self.failUnless(iq['type']=='result', 'Not a result')
401           
402
403        fields = []
404
405        fields.append(data_form.Field(label='Natural-Language Room Name',
406                                      var='muc#roomconfig_roomname',
407                                      value=self.test_room))
408       
409        d = self.protocol.configure(self.room_jid.userhost(), fields)
410        d.addCallback(cb)
411
412        iq = self.stub.output[-1]
413        self.failUnless(xpath.matches("/iq/query[@xmlns='%s']/x"% (muc.NS_MUC_OWNER,), iq), 'Bad configure request')
414       
415        response = toResponse(iq, 'result')
416        self.stub.send(response)
417        return d
418
419
420    def test_nickChange(self):
421        """Send a nick change to the server.
422        """
423        test_nick = 'newNick'
424       
425        self._createRoom()
426
427        def cb(room):
428            self.assertEquals(self.test_room, room.name)
429            self.assertEquals(test_nick, room.nick)
430
431        d = self.protocol.nick(self.room_jid, test_nick)
432        d.addCallback(cb)
433
434        prs = self.stub.output[-1]
435        self.failUnless(prs.name=='presence', "Need to be presence")
436        self.failUnless(getattr(prs, 'x', None), 'No muc x element')
437
438        # send back user presence, they joined       
439        response = muc.UserPresence(frm=self.test_room+'@'+self.test_srv+'/'+test_nick)
440       
441        self.stub.send(response)
442        return d
443
444       
Note: See TracBrowser for help on using the repository browser.