source: wokkel/test/test_pubsub.py @ 46:4ee1f9c08b22

Last change on this file since 46:4ee1f9c08b22 was 46:4ee1f9c08b22, checked in by Ralph Meijer <ralphm@…>, 13 years ago

If provided, return NodeID in the response for Service Discovery requests.

This also renames the namespace constants to include DISCO in their name
and provides better tests and docstrings.

Author: ralphm.
Reviewer: tofu.
Fixes #7.

File size: 34.9 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_onPublishNoNode(self):
511        """
512        The root node is always a collection, publishing is a bad request.
513        """
514        xml = """
515        <iq type='set' to='pubsub.example.org'
516                       from='user@example.org'>
517          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
518            <publish/>
519          </pubsub>
520        </iq>
521        """
522
523        def cb(result):
524            self.assertEquals('bad-request', result.condition)
525
526        d = self.handleRequest(xml)
527        self.assertFailure(d, error.StanzaError)
528        d.addCallback(cb)
529        return d
530
531
532    def test_onPublish(self):
533        """
534        A publish request should result in L{PubSubService.publish} being
535        called.
536        """
537
538        xml = """
539        <iq type='set' to='pubsub.example.org'
540                       from='user@example.org'>
541          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
542            <publish node='test'/>
543          </pubsub>
544        </iq>
545        """
546
547        def publish(requestor, service, nodeIdentifier, items):
548            self.assertEqual(JID('user@example.org'), requestor)
549            self.assertEqual(JID('pubsub.example.org'), service)
550            self.assertEqual('test', nodeIdentifier)
551            self.assertEqual([], items)
552            return defer.succeed(None)
553
554        self.service.publish = publish
555        return self.handleRequest(xml)
556
557
558    def test_onOptionsGet(self):
559        """
560        Subscription options are not supported.
561        """
562
563        xml = """
564        <iq type='get' to='pubsub.example.org'
565                       from='user@example.org'>
566          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
567            <options/>
568          </pubsub>
569        </iq>
570        """
571
572        def cb(result):
573            self.assertEquals('feature-not-implemented', result.condition)
574            self.assertEquals('unsupported', result.appCondition.name)
575            self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri)
576
577        d = self.handleRequest(xml)
578        self.assertFailure(d, error.StanzaError)
579        d.addCallback(cb)
580        return d
581
582
583    def test_onSubscriptions(self):
584        """
585        A subscriptions request should result in
586        L{PubSubService.subscriptions} being called and the result prepared
587        for the response.
588        """
589
590        xml = """
591        <iq type='get' to='pubsub.example.org'
592                       from='user@example.org'>
593          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
594            <subscriptions/>
595          </pubsub>
596        </iq>
597        """
598
599        def cb(element):
600            self.assertEqual('pubsub', element.name)
601            self.assertEqual(NS_PUBSUB, element.uri)
602            self.assertEqual(NS_PUBSUB, element.subscriptions.uri)
603            children = list(element.subscriptions.elements())
604            self.assertEqual(1, len(children))
605            subscription = children[0]
606            self.assertEqual('subscription', subscription.name)
607            self.assertEqual(NS_PUBSUB, subscription.uri)
608            self.assertEqual('user@example.org', subscription['jid'])
609            self.assertEqual('test', subscription['node'])
610            self.assertEqual('subscribed', subscription['subscription'])
611
612
613        def subscriptions(requestor, service):
614            self.assertEqual(JID('user@example.org'), requestor)
615            self.assertEqual(JID('pubsub.example.org'), service)
616            subscription = pubsub.Subscription('test', JID('user@example.org'),
617                                               'subscribed')
618            return defer.succeed([subscription])
619
620        self.service.subscriptions = subscriptions
621        d = self.handleRequest(xml)
622        d.addCallback(cb)
623        return d
624
625
626    def test_onDefault(self):
627        """
628        A default request should result in
629        L{PubSubService.getDefaultConfiguration} being called.
630        """
631
632        xml = """
633        <iq type='get' to='pubsub.example.org'
634                       from='user@example.org'>
635          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
636            <default/>
637          </pubsub>
638        </iq>
639        """
640
641        def getConfigurationOptions():
642            return {
643                "pubsub#persist_items":
644                    {"type": "boolean",
645                     "label": "Persist items to storage"},
646                "pubsub#deliver_payloads":
647                    {"type": "boolean",
648                     "label": "Deliver payloads with event notifications"}
649                }
650
651        def getDefaultConfiguration(requestor, service, nodeType):
652            self.assertEqual(JID('user@example.org'), requestor)
653            self.assertEqual(JID('pubsub.example.org'), service)
654            self.assertEqual('leaf', nodeType)
655            return defer.succeed({})
656
657        def cb(element):
658            self.assertEqual('pubsub', element.name)
659            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
660            self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
661            form = data_form.Form.fromElement(element.default.x)
662            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
663
664        self.service.getConfigurationOptions = getConfigurationOptions
665        self.service.getDefaultConfiguration = getDefaultConfiguration
666        verify.verifyObject(iwokkel.IPubSubService, self.service)
667        d = self.handleRequest(xml)
668        d.addCallback(cb)
669        return d
670
671
672    def test_onConfigureGet(self):
673        """
674        On a node configuration get request L{PubSubService.getConfiguration}
675        is called and results in a data form with the configuration.
676        """
677
678        xml = """
679        <iq type='get' to='pubsub.example.org'
680                       from='user@example.org'>
681          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
682            <configure node='test'/>
683          </pubsub>
684        </iq>
685        """
686
687        def getConfigurationOptions():
688            return {
689                "pubsub#persist_items":
690                    {"type": "boolean",
691                     "label": "Persist items to storage"},
692                "pubsub#deliver_payloads":
693                    {"type": "boolean",
694                     "label": "Deliver payloads with event notifications"}
695                }
696
697        def getConfiguration(requestor, service, nodeIdentifier):
698            self.assertEqual(JID('user@example.org'), requestor)
699            self.assertEqual(JID('pubsub.example.org'), service)
700            self.assertEqual('test', nodeIdentifier)
701
702            return defer.succeed({'pubsub#deliver_payloads': '0',
703                                  'pubsub#persist_items': '1'})
704
705        def cb(element):
706            self.assertEqual('pubsub', element.name)
707            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
708            self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
709            form = data_form.Form.fromElement(element.configure.x)
710            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
711            fields = form.fields
712
713            self.assertIn('pubsub#deliver_payloads', fields)
714            field = fields['pubsub#deliver_payloads']
715            self.assertEqual('boolean', field.fieldType)
716            self.assertEqual(False, field.value)
717
718            self.assertIn('pubsub#persist_items', fields)
719            field = fields['pubsub#persist_items']
720            self.assertEqual('boolean', field.fieldType)
721            self.assertEqual(True, field.value)
722
723        self.service.getConfigurationOptions = getConfigurationOptions
724        self.service.getConfiguration = getConfiguration
725        d = self.handleRequest(xml)
726        d.addCallback(cb)
727        return d
728
729
730    def test_onConfigureSet(self):
731        """
732        On a node configuration set request the Data Form is parsed and
733        L{PubSubService.setConfiguration} is called with the passed options.
734        """
735
736        xml = """
737        <iq type='set' to='pubsub.example.org'
738                       from='user@example.org'>
739          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
740            <configure node='test'>
741              <x xmlns='jabber:x:data' type='submit'>
742                <field var='FORM_TYPE' type='hidden'>
743                  <value>http://jabber.org/protocol/pubsub#node_config</value>
744                </field>
745                <field var='pubsub#deliver_payloads'><value>0</value></field>
746                <field var='pubsub#persist_items'><value>1</value></field>
747              </x>
748            </configure>
749          </pubsub>
750        </iq>
751        """
752
753        def getConfigurationOptions():
754            return {
755                "pubsub#persist_items":
756                    {"type": "boolean",
757                     "label": "Persist items to storage"},
758                "pubsub#deliver_payloads":
759                    {"type": "boolean",
760                     "label": "Deliver payloads with event notifications"}
761                }
762
763        def setConfiguration(requestor, service, nodeIdentifier, options):
764            self.assertEqual(JID('user@example.org'), requestor)
765            self.assertEqual(JID('pubsub.example.org'), service)
766            self.assertEqual('test', nodeIdentifier)
767            self.assertEqual({'pubsub#deliver_payloads': False,
768                              'pubsub#persist_items': True}, options)
769            return defer.succeed(None)
770
771        self.service.getConfigurationOptions = getConfigurationOptions
772        self.service.setConfiguration = setConfiguration
773        return self.handleRequest(xml)
774
775
776    def test_onConfigureSetCancel(self):
777        """
778        The node configuration is cancelled, L{PubSubService.setConfiguration}
779        not called.
780        """
781
782        xml = """
783        <iq type='set' to='pubsub.example.org'
784                       from='user@example.org'>
785          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
786            <configure node='test'>
787              <x xmlns='jabber:x:data' type='cancel'>
788                <field var='FORM_TYPE' type='hidden'>
789                  <value>http://jabber.org/protocol/pubsub#node_config</value>
790                </field>
791              </x>
792            </configure>
793          </pubsub>
794        </iq>
795        """
796
797        def setConfiguration(requestor, service, nodeIdentifier, options):
798            self.fail("Unexpected call to setConfiguration")
799
800        self.service.setConfiguration = setConfiguration
801        return self.handleRequest(xml)
802
803
804    def test_onConfigureSetIgnoreUnknown(self):
805        """
806        On a node configuration set request unknown fields should be ignored.
807        """
808
809        xml = """
810        <iq type='set' to='pubsub.example.org'
811                       from='user@example.org'>
812          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
813            <configure node='test'>
814              <x xmlns='jabber:x:data' type='submit'>
815                <field var='FORM_TYPE' type='hidden'>
816                  <value>http://jabber.org/protocol/pubsub#node_config</value>
817                </field>
818                <field var='pubsub#deliver_payloads'><value>0</value></field>
819                <field var='x-myfield'><value>1</value></field>
820              </x>
821            </configure>
822          </pubsub>
823        </iq>
824        """
825
826        def getConfigurationOptions():
827            return {
828                "pubsub#persist_items":
829                    {"type": "boolean",
830                     "label": "Persist items to storage"},
831                "pubsub#deliver_payloads":
832                    {"type": "boolean",
833                     "label": "Deliver payloads with event notifications"}
834                }
835
836        def setConfiguration(requestor, service, nodeIdentifier, options):
837            self.assertEquals(['pubsub#deliver_payloads'], options.keys())
838
839        self.service.getConfigurationOptions = getConfigurationOptions
840        self.service.setConfiguration = setConfiguration
841        return self.handleRequest(xml)
842
843
844    def test_onItems(self):
845        """
846        On a items request, return all items for the given node.
847        """
848        xml = """
849        <iq type='get' to='pubsub.example.org'
850                       from='user@example.org'>
851          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
852            <items node='test'/>
853          </pubsub>
854        </iq>
855        """
856
857        def items(requestor, service, nodeIdentifier, maxItems, items):
858            self.assertEqual(JID('user@example.org'), requestor)
859            self.assertEqual(JID('pubsub.example.org'), service)
860            self.assertEqual('test', nodeIdentifier)
861            self.assertIdentical(None, maxItems)
862            self.assertEqual([], items)
863            return defer.succeed([pubsub.Item('current')])
864
865        def cb(element):
866            self.assertEqual(NS_PUBSUB, element.uri)
867            self.assertEqual(NS_PUBSUB, element.items.uri)
868            self.assertEqual(1, len(element.items.children))
869            item = element.items.children[-1]
870            self.assertTrue(domish.IElement.providedBy(item))
871            self.assertEqual('item', item.name)
872            self.assertEqual(NS_PUBSUB, item.uri)
873            self.assertEqual('current', item['id'])
874
875        self.service.items = items
876        d = self.handleRequest(xml)
877        d.addCallback(cb)
878        return d
879
880
881    def test_onRetract(self):
882        """
883        A retract request should result in L{PubSubService.retract} being
884        called.
885        """
886
887        xml = """
888        <iq type='set' to='pubsub.example.org'
889                       from='user@example.org'>
890          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
891            <retract node='test'>
892              <item id='item1'/>
893              <item id='item2'/>
894            </retract>
895          </pubsub>
896        </iq>
897        """
898
899        def retract(requestor, service, nodeIdentifier, itemIdentifiers):
900            self.assertEqual(JID('user@example.org'), requestor)
901            self.assertEqual(JID('pubsub.example.org'), service)
902            self.assertEqual('test', nodeIdentifier)
903            self.assertEqual(['item1', 'item2'], itemIdentifiers)
904            return defer.succeed(None)
905
906        self.service.retract = retract
907        return self.handleRequest(xml)
908
909
910    def test_onPurge(self):
911        """
912        A purge request should result in L{PubSubService.purge} being
913        called.
914        """
915
916        xml = """
917        <iq type='set' to='pubsub.example.org'
918                       from='user@example.org'>
919          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
920            <purge node='test'/>
921          </pubsub>
922        </iq>
923        """
924
925        def purge(requestor, service, nodeIdentifier):
926            self.assertEqual(JID('user@example.org'), requestor)
927            self.assertEqual(JID('pubsub.example.org'), service)
928            self.assertEqual('test', nodeIdentifier)
929            return defer.succeed(None)
930
931        self.service.purge = purge
932        return self.handleRequest(xml)
933
934
935    def test_onDelete(self):
936        """
937        A delete request should result in L{PubSubService.delete} being
938        called.
939        """
940
941        xml = """
942        <iq type='set' to='pubsub.example.org'
943                       from='user@example.org'>
944          <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
945            <delete node='test'/>
946          </pubsub>
947        </iq>
948        """
949
950        def delete(requestor, service, nodeIdentifier):
951            self.assertEqual(JID('user@example.org'), requestor)
952            self.assertEqual(JID('pubsub.example.org'), service)
953            self.assertEqual('test', nodeIdentifier)
954            return defer.succeed(None)
955
956        self.service.delete = delete
957        return self.handleRequest(xml)
958
959
960    def test_notifyDelete(self):
961        """
962        Subscribers should be sent a delete notification.
963        """
964        subscriptions = [JID('user@example.org')]
965        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
966                                  subscriptions)
967        message = self.stub.output[-1]
968
969        self.assertEquals('message', message.name)
970        self.assertIdentical(None, message.uri)
971        self.assertEquals('user@example.org', message['to'])
972        self.assertEquals('pubsub.example.org', message['from'])
973        self.assertTrue(message.event)
974        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
975        self.assertTrue(message.event.delete)
976        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
977        self.assertTrue(message.event.delete.hasAttribute('node'))
978        self.assertEqual('test', message.event.delete['node'])
979
980
981    def test_notifyDeleteRedirect(self):
982        """
983        Subscribers should be sent a delete notification with redirect.
984        """
985        redirectURI = 'xmpp:pubsub.example.org?;node=test2'
986        subscriptions = [JID('user@example.org')]
987        self.service.notifyDelete(JID('pubsub.example.org'), 'test',
988                                  subscriptions, redirectURI)
989        message = self.stub.output[-1]
990
991        self.assertEquals('message', message.name)
992        self.assertIdentical(None, message.uri)
993        self.assertEquals('user@example.org', message['to'])
994        self.assertEquals('pubsub.example.org', message['from'])
995        self.assertTrue(message.event)
996        self.assertEqual(NS_PUBSUB_EVENT, message.event.uri)
997        self.assertTrue(message.event.delete)
998        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.uri)
999        self.assertTrue(message.event.delete.hasAttribute('node'))
1000        self.assertEqual('test', message.event.delete['node'])
1001        self.assertTrue(message.event.delete.redirect)
1002        self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri)
1003        self.assertTrue(message.event.delete.redirect.hasAttribute('uri'))
1004        self.assertEqual(redirectURI, message.event.delete.redirect['uri'])
Note: See TracBrowser for help on using the repository browser.