source: wokkel/test/test_pubsub.py @ 47:895c67e2ed9f

Last change on this file since 47:895c67e2ed9f was 47:895c67e2ed9f, checked in by Ralph Meijer <ralphm@…>, 14 years ago

Track namespace constant name change in disco module and add minimal test.

Author: ralphm.

File size: 35.4 KB
Line 
1# Copyright (c) 2003-2008 Ralph Meijer
2# See LICENSE for details.
3
4"""
5Tests for L{wokkel.pubsub}
6"""
7
8from zope.interface import verify
9
10from twisted.trial import unittest
11from twisted.internet import defer
12from twisted.words.xish import domish
13from twisted.words.protocols.jabber import error
14from twisted.words.protocols.jabber.jid import JID
15
16from wokkel import data_form, iwokkel, pubsub, shim
17from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
18
19try:
20    from twisted.words.protocols.jabber.xmlstream import toResponse
21except ImportError:
22    from wokkel.compat import toResponse
23
24NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
25NS_PUBSUB_CONFIG = 'http://jabber.org/protocol/pubsub#node_config'
26NS_PUBSUB_ERRORS = 'http://jabber.org/protocol/pubsub#errors'
27NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event'
28NS_PUBSUB_OWNER = 'http://jabber.org/protocol/pubsub#owner'
29
30def calledAsync(fn):
31    """
32    Function wrapper that fires a deferred upon calling the given function.
33    """
34    d = defer.Deferred()
35
36    def func(*args, **kwargs):
37        try:
38            result = fn(*args, **kwargs)
39        except:
40            d.errback()
41        else:
42            d.callback(result)
43
44    return d, func
45
46
47class PubSubClientTest(unittest.TestCase):
48    timeout = 2
49
50    def setUp(self):
51        self.stub = XmlStreamStub()
52        self.protocol = pubsub.PubSubClient()
53        self.protocol.xmlstream = self.stub.xmlstream
54        self.protocol.connectionInitialized()
55
56
57    def test_interface(self):
58        """
59        Do instances of L{pubsub.PubSubClient} provide L{iwokkel.IPubSubClient}?
60        """
61        verify.verifyObject(iwokkel.IPubSubClient, self.protocol)
62
63
64    def test_eventItems(self):
65        """
66        Test receiving an items event resulting in a call to itemsReceived.
67        """
68        message = domish.Element((None, 'message'))
69        message['from'] = 'pubsub.example.org'
70        message['to'] = 'user@example.org/home'
71        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
72        items = event.addElement('items')
73        items['node'] = 'test'
74        item1 = items.addElement('item')
75        item1['id'] = 'item1'
76        item2 = items.addElement('retract')
77        item2['id'] = 'item2'
78        item3 = items.addElement('item')
79        item3['id'] = 'item3'
80
81        def itemsReceived(event):
82            self.assertEquals(JID('user@example.org/home'), event.recipient)
83            self.assertEquals(JID('pubsub.example.org'), event.sender)
84            self.assertEquals('test', event.nodeIdentifier)
85            self.assertEquals([item1, item2, item3], event.items)
86
87        d, self.protocol.itemsReceived = calledAsync(itemsReceived)
88        self.stub.send(message)
89        return d
90
91
92    def test_eventItemsCollection(self):
93        """
94        Test receiving an items event resulting in a call to itemsReceived.
95        """
96        message = domish.Element((None, 'message'))
97        message['from'] = 'pubsub.example.org'
98        message['to'] = 'user@example.org/home'
99        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
100        items = event.addElement('items')
101        items['node'] = 'test'
102
103        headers = shim.Headers([('Collection', 'collection')])
104        message.addChild(headers)
105
106        def itemsReceived(event):
107            self.assertEquals(JID('user@example.org/home'), event.recipient)
108            self.assertEquals(JID('pubsub.example.org'), event.sender)
109            self.assertEquals('test', event.nodeIdentifier)
110            self.assertEquals({'Collection': ['collection']}, event.headers)
111
112        d, self.protocol.itemsReceived = calledAsync(itemsReceived)
113        self.stub.send(message)
114        return d
115
116
117    def test_eventDelete(self):
118        """
119        Test receiving a delete event resulting in a call to deleteReceived.
120        """
121        message = domish.Element((None, 'message'))
122        message['from'] = 'pubsub.example.org'
123        message['to'] = 'user@example.org/home'
124        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
125        delete = event.addElement('delete')
126        delete['node'] = 'test'
127
128        def deleteReceived(event):
129            self.assertEquals(JID('user@example.org/home'), event.recipient)
130            self.assertEquals(JID('pubsub.example.org'), event.sender)
131            self.assertEquals('test', event.nodeIdentifier)
132
133        d, self.protocol.deleteReceived = calledAsync(deleteReceived)
134        self.stub.send(message)
135        return d
136
137
138    def test_eventDeleteRedirect(self):
139        """
140        Test receiving a delete event with a redirect URI.
141        """
142        message = domish.Element((None, 'message'))
143        message['from'] = 'pubsub.example.org'
144        message['to'] = 'user@example.org/home'
145        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
146        delete = event.addElement('delete')
147        delete['node'] = 'test'
148        uri = 'xmpp:pubsub.example.org?;node=test2'
149        delete.addElement('redirect')['uri'] = uri
150
151        def deleteReceived(event):
152            self.assertEquals(JID('user@example.org/home'), event.recipient)
153            self.assertEquals(JID('pubsub.example.org'), event.sender)
154            self.assertEquals('test', event.nodeIdentifier)
155            self.assertEquals(uri, event.redirectURI)
156
157        d, self.protocol.deleteReceived = calledAsync(deleteReceived)
158        self.stub.send(message)
159        return d
160
161
162    def test_event_purge(self):
163        """
164        Test receiving a purge event resulting in a call to purgeReceived.
165        """
166        message = domish.Element((None, 'message'))
167        message['from'] = 'pubsub.example.org'
168        message['to'] = 'user@example.org/home'
169        event = message.addElement((NS_PUBSUB_EVENT, 'event'))
170        items = event.addElement('purge')
171        items['node'] = 'test'
172
173        def purgeReceived(event):
174            self.assertEquals(JID('user@example.org/home'), event.recipient)
175            self.assertEquals(JID('pubsub.example.org'), event.sender)
176            self.assertEquals('test', event.nodeIdentifier)
177
178        d, self.protocol.purgeReceived = calledAsync(purgeReceived)
179        self.stub.send(message)
180        return d
181
182
183    def test_createNode(self):
184        """
185        Test sending create request.
186        """
187
188        def cb(nodeIdentifier):
189            self.assertEquals('test', nodeIdentifier)
190
191        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
192        d.addCallback(cb)
193
194        iq = self.stub.output[-1]
195        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
196        self.assertEquals('set', iq.getAttribute('type'))
197        self.assertEquals('pubsub', iq.pubsub.name)
198        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
199        children = list(domish.generateElementsQNamed(iq.pubsub.children,
200                                                      'create', NS_PUBSUB))
201        self.assertEquals(1, len(children))
202        child = children[0]
203        self.assertEquals('test', child['node'])
204
205        response = toResponse(iq, 'result')
206        self.stub.send(response)
207        return d
208
209
210    def test_createNodeInstant(self):
211        """
212        Test sending create request resulting in an instant node.
213        """
214
215        def cb(nodeIdentifier):
216            self.assertEquals('test', nodeIdentifier)
217
218        d = self.protocol.createNode(JID('pubsub.example.org'))
219        d.addCallback(cb)
220
221        iq = self.stub.output[-1]
222        children = list(domish.generateElementsQNamed(iq.pubsub.children,
223                                                      'create', NS_PUBSUB))
224        child = children[0]
225        self.assertFalse(child.hasAttribute('node'))
226
227        response = toResponse(iq, 'result')
228        command = response.addElement((NS_PUBSUB, 'pubsub'))
229        create = command.addElement('create')
230        create['node'] = 'test'
231        self.stub.send(response)
232        return d
233
234
235    def test_createNodeRenamed(self):
236        """
237        Test sending create request resulting in renamed node.
238        """
239
240        def cb(nodeIdentifier):
241            self.assertEquals('test2', nodeIdentifier)
242
243        d = self.protocol.createNode(JID('pubsub.example.org'), 'test')
244        d.addCallback(cb)
245
246        iq = self.stub.output[-1]
247        children = list(domish.generateElementsQNamed(iq.pubsub.children,
248                                                      'create', NS_PUBSUB))
249        child = children[0]
250        self.assertEquals('test', child['node'])
251
252        response = toResponse(iq, 'result')
253        command = response.addElement((NS_PUBSUB, 'pubsub'))
254        create = command.addElement('create')
255        create['node'] = 'test2'
256        self.stub.send(response)
257        return d
258
259
260    def test_deleteNode(self):
261        """
262        Test sending delete request.
263        """
264
265        d = self.protocol.deleteNode(JID('pubsub.example.org'), 'test')
266
267        iq = self.stub.output[-1]
268        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
269        self.assertEquals('set', iq.getAttribute('type'))
270        self.assertEquals('pubsub', iq.pubsub.name)
271        self.assertEquals(NS_PUBSUB_OWNER, iq.pubsub.uri)
272        children = list(domish.generateElementsQNamed(iq.pubsub.children,
273                                                      'delete', NS_PUBSUB_OWNER))
274        self.assertEquals(1, len(children))
275        child = children[0]
276        self.assertEquals('test', child['node'])
277
278        response = toResponse(iq, 'result')
279        self.stub.send(response)
280        return d
281
282
283    def test_publish(self):
284        """
285        Test sending publish request.
286        """
287
288        item = pubsub.Item()
289        d = self.protocol.publish(JID('pubsub.example.org'), 'test', [item])
290
291        iq = self.stub.output[-1]
292        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
293        self.assertEquals('set', iq.getAttribute('type'))
294        self.assertEquals('pubsub', iq.pubsub.name)
295        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
296        children = list(domish.generateElementsQNamed(iq.pubsub.children,
297                                                      'publish', NS_PUBSUB))
298        self.assertEquals(1, len(children))
299        child = children[0]
300        self.assertEquals('test', child['node'])
301        items = list(domish.generateElementsQNamed(child.children,
302                                                   'item', NS_PUBSUB))
303        self.assertEquals(1, len(items))
304        self.assertIdentical(item, items[0])
305
306        response = toResponse(iq, 'result')
307        self.stub.send(response)
308        return d
309
310
311    def test_publishNoItems(self):
312        """
313        Test sending publish request without items.
314        """
315
316        d = self.protocol.publish(JID('pubsub.example.org'), 'test')
317
318        iq = self.stub.output[-1]
319        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
320        self.assertEquals('set', iq.getAttribute('type'))
321        self.assertEquals('pubsub', iq.pubsub.name)
322        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
323        children = list(domish.generateElementsQNamed(iq.pubsub.children,
324                                                      'publish', NS_PUBSUB))
325        self.assertEquals(1, len(children))
326        child = children[0]
327        self.assertEquals('test', child['node'])
328
329        response = toResponse(iq, 'result')
330        self.stub.send(response)
331        return d
332
333
334    def test_subscribe(self):
335        """
336        Test sending subscription request.
337        """
338        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
339                                      JID('user@example.org'))
340
341        iq = self.stub.output[-1]
342        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
343        self.assertEquals('set', iq.getAttribute('type'))
344        self.assertEquals('pubsub', iq.pubsub.name)
345        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
346        children = list(domish.generateElementsQNamed(iq.pubsub.children,
347                                                      'subscribe', NS_PUBSUB))
348        self.assertEquals(1, len(children))
349        child = children[0]
350        self.assertEquals('test', child['node'])
351        self.assertEquals('user@example.org', child['jid'])
352
353        response = toResponse(iq, 'result')
354        pubsub = response.addElement((NS_PUBSUB, 'pubsub'))
355        subscription = pubsub.addElement('subscription')
356        subscription['node'] = 'test'
357        subscription['jid'] = 'user@example.org'
358        subscription['subscription'] = 'subscribed'
359        self.stub.send(response)
360        return d
361
362
363    def test_subscribePending(self):
364        """
365        Test sending subscription request that results in a pending
366        subscription.
367        """
368        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
369                                      JID('user@example.org'))
370
371        iq = self.stub.output[-1]
372        response = toResponse(iq, 'result')
373        command = response.addElement((NS_PUBSUB, 'pubsub'))
374        subscription = command.addElement('subscription')
375        subscription['node'] = 'test'
376        subscription['jid'] = 'user@example.org'
377        subscription['subscription'] = 'pending'
378        self.stub.send(response)
379        self.assertFailure(d, pubsub.SubscriptionPending)
380        return d
381
382
383    def test_subscribeUnconfigured(self):
384        """
385        Test sending subscription request that results in an unconfigured
386        subscription.
387        """
388        d = self.protocol.subscribe(JID('pubsub.example.org'), 'test',
389                                      JID('user@example.org'))
390
391        iq = self.stub.output[-1]
392        response = toResponse(iq, 'result')
393        command = response.addElement((NS_PUBSUB, 'pubsub'))
394        subscription = command.addElement('subscription')
395        subscription['node'] = 'test'
396        subscription['jid'] = 'user@example.org'
397        subscription['subscription'] = 'unconfigured'
398        self.stub.send(response)
399        self.assertFailure(d, pubsub.SubscriptionUnconfigured)
400        return d
401
402
403    def test_unsubscribe(self):
404        """
405        Test sending unsubscription request.
406        """
407        d = self.protocol.unsubscribe(JID('pubsub.example.org'), 'test',
408                                      JID('user@example.org'))
409
410        iq = self.stub.output[-1]
411        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
412        self.assertEquals('set', iq.getAttribute('type'))
413        self.assertEquals('pubsub', iq.pubsub.name)
414        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
415        children = list(domish.generateElementsQNamed(iq.pubsub.children,
416                                                      'unsubscribe', NS_PUBSUB))
417        self.assertEquals(1, len(children))
418        child = children[0]
419        self.assertEquals('test', child['node'])
420        self.assertEquals('user@example.org', child['jid'])
421
422        self.stub.send(toResponse(iq, 'result'))
423        return d
424
425
426    def test_items(self):
427        """
428        Test sending items request.
429        """
430        def cb(items):
431            self.assertEquals([], items)
432
433        d = self.protocol.items(JID('pubsub.example.org'), 'test')
434        d.addCallback(cb)
435
436        iq = self.stub.output[-1]
437        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
438        self.assertEquals('get', iq.getAttribute('type'))
439        self.assertEquals('pubsub', iq.pubsub.name)
440        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
441        children = list(domish.generateElementsQNamed(iq.pubsub.children,
442                                                      'items', NS_PUBSUB))
443        self.assertEquals(1, len(children))
444        child = children[0]
445        self.assertEquals('test', child['node'])
446
447        response = toResponse(iq, 'result')
448        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
449        items['node'] = 'test'
450
451        self.stub.send(response)
452
453        return d
454
455
456    def test_itemsMaxItems(self):
457        """
458        Test sending items request, with limit on the number of items.
459        """
460        def cb(items):
461            self.assertEquals(2, len(items))
462            self.assertEquals([item1, item2], items)
463
464        d = self.protocol.items(JID('pubsub.example.org'), 'test', maxItems=2)
465        d.addCallback(cb)
466
467        iq = self.stub.output[-1]
468        self.assertEquals('pubsub.example.org', iq.getAttribute('to'))
469        self.assertEquals('get', iq.getAttribute('type'))
470        self.assertEquals('pubsub', iq.pubsub.name)
471        self.assertEquals(NS_PUBSUB, iq.pubsub.uri)
472        children = list(domish.generateElementsQNamed(iq.pubsub.children,
473                                                      'items', NS_PUBSUB))
474        self.assertEquals(1, len(children))
475        child = children[0]
476        self.assertEquals('test', child['node'])
477        self.assertEquals('2', child['max_items'])
478
479        response = toResponse(iq, 'result')
480        items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items')
481        items['node'] = 'test'
482        item1 = items.addElement('item')
483        item1['id'] = 'item1'
484        item2 = items.addElement('item')
485        item2['id'] = 'item2'
486
487        self.stub.send(response)
488
489        return d
490
491
492
493class PubSubServiceTest(unittest.TestCase, TestableRequestHandlerMixin):
494    """
495    Tests for L{pubsub.PubSubService}.
496    """
497
498    def setUp(self):
499        self.stub = XmlStreamStub()
500        self.service = pubsub.PubSubService()
501        self.service.send = self.stub.xmlstream.send
502
503    def test_interface(self):
504        """
505        Do instances of L{pubsub.PubSubService} provide L{iwokkel.IPubSubService}?
506        """
507        verify.verifyObject(iwokkel.IPubSubService, self.service)
508
509
510    def test_getDiscoInfo(self):
511        """
512        Test getDiscoInfo calls getNodeInfo and returns some minimal info.
513        """
514        def cb(info):
515            self.assertEqual(2, len(info))
516
517        def getNodeInfo(requestor, target, nodeIdentifier):
518            return defer.succeed(None)
519
520        self.service.getNodeInfo = getNodeInfo
521        d = self.service.getDiscoInfo(JID('user@example.org/home'),
522                                      JID('pubsub.example.org'), '')
523        d.addCallback(cb)
524        return d
525
526
527    def test_onPublishNoNode(self):
528        """
529        The root node is always a collection, publishing is a bad request.
530        """
531        xml = """
532        <iq type='set' to='pubsub.example.org'
533                       from='user@example.org'>
534          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
535            <publish/>
536          </pubsub>
537        </iq>
538        """
539
540        def cb(result):
541            self.assertEquals('bad-request', result.condition)
542
543        d = self.handleRequest(xml)
544        self.assertFailure(d, error.StanzaError)
545        d.addCallback(cb)
546        return d
547
548
549    def test_onPublish(self):
550        """
551        A publish request should result in L{PubSubService.publish} being
552        called.
553        """
554
555        xml = """
556        <iq type='set' to='pubsub.example.org'
557                       from='user@example.org'>
558          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
559            <publish node='test'/>
560          </pubsub>
561        </iq>
562        """
563
564        def publish(requestor, service, nodeIdentifier, items):
565            self.assertEqual(JID('user@example.org'), requestor)
566            self.assertEqual(JID('pubsub.example.org'), service)
567            self.assertEqual('test', nodeIdentifier)
568            self.assertEqual([], items)
569            return defer.succeed(None)
570
571        self.service.publish = publish
572        return self.handleRequest(xml)
573
574
575    def test_onOptionsGet(self):
576        """
577        Subscription options are not supported.
578        """
579
580        xml = """
581        <iq type='get' to='pubsub.example.org'
582                       from='user@example.org'>
583          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
584            <options/>
585          </pubsub>
586        </iq>
587        """
588
589        def cb(result):
590            self.assertEquals('feature-not-implemented', result.condition)
591            self.assertEquals('unsupported', result.appCondition.name)
592            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
593
594        d = self.handleRequest(xml)
595        self.assertFailure(d, error.StanzaError)
596        d.addCallback(cb)
597        return d
598
599
600    def test_onSubscriptions(self):
601        """
602        A subscriptions request should result in
603        L{PubSubService.subscriptions} being called and the result prepared
604        for the response.
605        """
606
607        xml = """
608        <iq type='get' to='pubsub.example.org'
609                       from='user@example.org'>
610          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
611            <subscriptions/>
612          </pubsub>
613        </iq>
614        """
615
616        def cb(element):
617            self.assertEqual('pubsub', element.name)
618            self.assertEqual(NS_PUBSUB, element.uri)
619            self.assertEqual(NS_PUBSUB, element.subscriptions.uri)
620            children = list(element.subscriptions.elements())
621            self.assertEqual(1, len(children))
622            subscription = children[0]
623            self.assertEqual('subscription', subscription.name)
624            self.assertEqual(NS_PUBSUB, subscription.uri)
625            self.assertEqual('user@example.org', subscription['jid'])
626            self.assertEqual('test', subscription['node'])
627            self.assertEqual('subscribed', subscription['subscription'])
628
629
630        def subscriptions(requestor, service):
631            self.assertEqual(JID('user@example.org'), requestor)
632            self.assertEqual(JID('pubsub.example.org'), service)
633            subscription = pubsub.Subscription('test', JID('user@example.org'),
634                                               'subscribed')
635            return defer.succeed([subscription])
636
637        self.service.subscriptions = subscriptions
638        d = self.handleRequest(xml)
639        d.addCallback(cb)
640        return d
641
642
643    def test_onDefault(self):
644        """
645        A default request should result in
646        L{PubSubService.getDefaultConfiguration} being called.
647        """
648
649        xml = """
650        <iq type='get' to='pubsub.example.org'
651                       from='user@example.org'>
652          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
653            <default/>
654          </pubsub>
655        </iq>
656        """
657
658        def getConfigurationOptions():
659            return {
660                "pubsub#persist_items":
661                    {"type": "boolean",
662                     "label": "Persist items to storage"},
663                "pubsub#deliver_payloads":
664                    {"type": "boolean",
665                     "label": "Deliver payloads with event notifications"}
666                }
667
668        def getDefaultConfiguration(requestor, service, nodeType):
669            self.assertEqual(JID('user@example.org'), requestor)
670            self.assertEqual(JID('pubsub.example.org'), service)
671            self.assertEqual('leaf', nodeType)
672            return defer.succeed({})
673
674        def cb(element):
675            self.assertEqual('pubsub', element.name)
676            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
677            self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
678            form = data_form.Form.fromElement(element.default.x)
679            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
680
681        self.service.getConfigurationOptions = getConfigurationOptions
682        self.service.getDefaultConfiguration = getDefaultConfiguration
683        verify.verifyObject(iwokkel.IPubSubService, self.service)
684        d = self.handleRequest(xml)
685        d.addCallback(cb)
686        return d
687
688
689    def test_onConfigureGet(self):
690        """
691        On a node configuration get request L{PubSubService.getConfiguration}
692        is called and results in a data form with the configuration.
693        """
694
695        xml = """
696        <iq type='get' to='pubsub.example.org'
697                       from='user@example.org'>
698          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
699            <configure node='test'/>
700          </pubsub>
701        </iq>
702        """
703
704        def getConfigurationOptions():
705            return {
706                "pubsub#persist_items":
707                    {"type": "boolean",
708                     "label": "Persist items to storage"},
709                "pubsub#deliver_payloads":
710                    {"type": "boolean",
711                     "label": "Deliver payloads with event notifications"}
712                }
713
714        def getConfiguration(requestor, service, nodeIdentifier):
715            self.assertEqual(JID('user@example.org'), requestor)
716            self.assertEqual(JID('pubsub.example.org'), service)
717            self.assertEqual('test', nodeIdentifier)
718
719            return defer.succeed({'pubsub#deliver_payloads': '0',
720                                  'pubsub#persist_items': '1'})
721
722        def cb(element):
723            self.assertEqual('pubsub', element.name)
724            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
725            self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
726            form = data_form.Form.fromElement(element.configure.x)
727            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
728            fields = form.fields
729
730            self.assertIn('pubsub#deliver_payloads', fields)
731            field = fields['pubsub#deliver_payloads']
732            self.assertEqual('boolean', field.fieldType)
733            self.assertEqual(False, field.value)
734
735            self.assertIn('pubsub#persist_items', fields)
736            field = fields['pubsub#persist_items']
737            self.assertEqual('boolean', field.fieldType)
738            self.assertEqual(True, field.value)
739
740        self.service.getConfigurationOptions = getConfigurationOptions
741        self.service.getConfiguration = getConfiguration
742        d = self.handleRequest(xml)
743        d.addCallback(cb)
744        return d
745
746
747    def test_onConfigureSet(self):
748        """
749        On a node configuration set request the Data Form is parsed and
750        L{PubSubService.setConfiguration} is called with the passed options.
751        """
752
753        xml = """
754        <iq type='set' to='pubsub.example.org'
755                       from='user@example.org'>
756          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
757            <configure node='test'>
758              <x xmlns='jabber:x:data' type='submit'>
759                <field var='FORM_TYPE' type='hidden'>
760                  <value>http://jabber.org/protocol/pubsub#node_config</value>
761                </field>
762                <field var='pubsub#deliver_payloads'><value>0</value></field>
763                <field var='pubsub#persist_items'><value>1</value></field>
764              </x>
765            </configure>
766          </pubsub>
767        </iq>
768        """
769
770        def getConfigurationOptions():
771            return {
772                "pubsub#persist_items":
773                    {"type": "boolean",
774                     "label": "Persist items to storage"},
775                "pubsub#deliver_payloads":
776                    {"type": "boolean",
777                     "label": "Deliver payloads with event notifications"}
778                }
779
780        def setConfiguration(requestor, service, nodeIdentifier, options):
781            self.assertEqual(JID('user@example.org'), requestor)
782            self.assertEqual(JID('pubsub.example.org'), service)
783            self.assertEqual('test', nodeIdentifier)
784            self.assertEqual({'pubsub#deliver_payloads': False,
785                              'pubsub#persist_items': True}, options)
786            return defer.succeed(None)
787
788        self.service.getConfigurationOptions = getConfigurationOptions
789        self.service.setConfiguration = setConfiguration
790        return self.handleRequest(xml)
791
792
793    def test_onConfigureSetCancel(self):
794        """
795        The node configuration is cancelled, L{PubSubService.setConfiguration}
796        not called.
797        """
798
799        xml = """
800        <iq type='set' to='pubsub.example.org'
801                       from='user@example.org'>
802          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
803            <configure node='test'>
804              <x xmlns='jabber:x:data' type='cancel'>
805                <field var='FORM_TYPE' type='hidden'>
806                  <value>http://jabber.org/protocol/pubsub#node_config</value>
807                </field>
808              </x>
809            </configure>
810          </pubsub>
811        </iq>
812        """
813
814        def setConfiguration(requestor, service, nodeIdentifier, options):
815            self.fail("Unexpected call to setConfiguration")
816
817        self.service.setConfiguration = setConfiguration
818        return self.handleRequest(xml)
819
820
821    def test_onConfigureSetIgnoreUnknown(self):
822        """
823        On a node configuration set request unknown fields should be ignored.
824        """
825
826        xml = """
827        <iq type='set' to='pubsub.example.org'
828                       from='user@example.org'>
829          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
830            <configure node='test'>
831              <x xmlns='jabber:x:data' type='submit'>
832                <field var='FORM_TYPE' type='hidden'>
833                  <value>http://jabber.org/protocol/pubsub#node_config</value>
834                </field>
835                <field var='pubsub#deliver_payloads'><value>0</value></field>
836                <field var='x-myfield'><value>1</value></field>
837              </x>
838            </configure>
839          </pubsub>
840        </iq>
841        """
842
843        def getConfigurationOptions():
844            return {
845                "pubsub#persist_items":
846                    {"type": "boolean",
847                     "label": "Persist items to storage"},
848                "pubsub#deliver_payloads":
849                    {"type": "boolean",
850                     "label": "Deliver payloads with event notifications"}
851                }
852
853        def setConfiguration(requestor, service, nodeIdentifier, options):
854            self.assertEquals(['pubsub#deliver_payloads'], options.keys())
855
856        self.service.getConfigurationOptions = getConfigurationOptions
857        self.service.setConfiguration = setConfiguration
858        return self.handleRequest(xml)
859
860
861    def test_onItems(self):
862        """
863        On a items request, return all items for the given node.
864        """
865        xml = """
866        <iq type='get' to='pubsub.example.org'
867                       from='user@example.org'>
868          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
869            <items node='test'/>
870          </pubsub>
871        </iq>
872        """
873
874        def items(requestor, service, nodeIdentifier, maxItems, items):
875            self.assertEqual(JID('user@example.org'), requestor)
876            self.assertEqual(JID('pubsub.example.org'), service)
877            self.assertEqual('test', nodeIdentifier)
878            self.assertIdentical(None, maxItems)
879            self.assertEqual([], items)
880            return defer.succeed([pubsub.Item('current')])
881
882        def cb(element):
883            self.assertEqual(NS_PUBSUB, element.uri)
884            self.assertEqual(NS_PUBSUB, element.items.uri)
885            self.assertEqual(1, len(element.items.children))
886            item = element.items.children[-1]
887            self.assertTrue(domish.IElement.providedBy(item))
888            self.assertEqual('item', item.name)
889            self.assertEqual(NS_PUBSUB, item.uri)
890            self.assertEqual('current', item['id'])
891
892        self.service.items = items
893        d = self.handleRequest(xml)
894        d.addCallback(cb)
895        return d
896
897
898    def test_onRetract(self):
899        """
900        A retract request should result in L{PubSubService.retract} being
901        called.
902        """
903
904        xml = """
905        <iq type='set' to='pubsub.example.org'
906                       from='user@example.org'>
907          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
908            <retract node='test'>
909              <item id='item1'/>
910              <item id='item2'/>
911            </retract>
912          </pubsub>
913        </iq>
914        """
915
916        def retract(requestor, service, nodeIdentifier, itemIdentifiers):
917            self.assertEqual(JID('user@example.org'), requestor)
918            self.assertEqual(JID('pubsub.example.org'), service)
919            self.assertEqual('test', nodeIdentifier)
920            self.assertEqual(['item1', 'item2'], itemIdentifiers)
921            return defer.succeed(None)
922
923        self.service.retract = retract
924        return self.handleRequest(xml)
925
926
927    def test_onPurge(self):
928        """
929        A purge request should result in L{PubSubService.purge} being
930        called.
931        """
932
933        xml = """
934        <iq type='set' to='pubsub.example.org'
935                       from='user@example.org'>
936          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
937            <purge node='test'/>
938          </pubsub>
939        </iq>
940        """
941
942        def purge(requestor, service, nodeIdentifier):
943            self.assertEqual(JID('user@example.org'), requestor)
944            self.assertEqual(JID('pubsub.example.org'), service)
945            self.assertEqual('test', nodeIdentifier)
946            return defer.succeed(None)
947
948        self.service.purge = purge
949        return self.handleRequest(xml)
950
951
952    def test_onDelete(self):
953        """
954        A delete request should result in L{PubSubService.delete} being
955        called.
956        """
957
958        xml = """
959        <iq type='set' to='pubsub.example.org'
960                       from='user@example.org'>
961          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
962            <delete node='test'/>
963          </pubsub>
964        </iq>
965        """
966
967        def delete(requestor, service, nodeIdentifier):
968            self.assertEqual(JID('user@example.org'), requestor)
969            self.assertEqual(JID('pubsub.example.org'), service)
970            self.assertEqual('test', nodeIdentifier)
971            return defer.succeed(None)
972
973        self.service.delete = delete
974        return self.handleRequest(xml)
975
976
977    def test_notifyDelete(self):
978        """
979        Subscribers should be sent a delete notification.
980        """
981        subscriptions = [JID('user@example.org')]
982        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
983                                  subscriptions)
984        message = self.stub.output[-1]
985
986        self.assertEquals('message', message.name)
987        self.assertIdentical(None, message.uri)
988        self.assertEquals('user@example.org', message['to'])
989        self.assertEquals('pubsub.example.org', message['from'])
990        self.assertTrue(message.event)
991        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
992        self.assertTrue(message.event.delete)
993        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
994        self.assertTrue(message.event.delete.hasAttribute('node'))
995        self.assertEqual('test', message.event.delete['node'])
996
997
998    def test_notifyDeleteRedirect(self):
999        """
1000        Subscribers should be sent a delete notification with redirect.
1001        """
1002        redirectURI = 'xmpp:pubsub.example.org?;node=test2'
1003        subscriptions = [JID('user@example.org')]
1004        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
1005                                  subscriptions, redirectURI)
1006        message = self.stub.output[-1]
1007
1008        self.assertEquals('message', message.name)
1009        self.assertIdentical(None, message.uri)
1010        self.assertEquals('user@example.org', message['to'])
1011        self.assertEquals('pubsub.example.org', message['from'])
1012        self.assertTrue(message.event)
1013        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
1014        self.assertTrue(message.event.delete)
1015        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
1016        self.assertTrue(message.event.delete.hasAttribute('node'))
1017        self.assertEqual('test', message.event.delete['node'])
1018        self.assertTrue(message.event.delete.redirect)
1019        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri)
1020        self.assertTrue(message.event.delete.redirect.hasAttribute('uri'))
1021        self.assertEqual(redirectURI, message.event.delete.redirect['uri'])
Note: See TracBrowser for help on using the repository browser.