import unittest from slixmpp import Iq from slixmpp.test import SlixTest import slixmpp.plugins.xep_0030 as xep_0030 from slixmpp.xmlstream import register_stanza_plugin class TestDisco(SlixTest): """ Test creating and manipulating the disco#info and disco#items stanzas from the XEP-0030 plugin. """ def setUp(self): register_stanza_plugin(Iq, xep_0030.DiscoInfo) register_stanza_plugin(Iq, xep_0030.DiscoItems) def testCreateInfoQueryNoNode(self): """Testing disco#info query with no node.""" iq = self.Iq() iq['disco_info']['node'] = '' self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info" /> </iq> """) def testCreateInfoQueryWithNode(self): """Testing disco#info query with a node.""" iq = self.Iq() iq['disco_info']['node'] = 'foo' self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info" node="foo" /> </iq> """) def testCreateItemsQueryNoNode(self): """Testing disco#items query with no node.""" iq = self.Iq() iq['disco_items']['node'] = '' self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#items" /> </iq> """) def testCreateItemsQueryWithNode(self): """Testing disco#items query with a node.""" iq = self.Iq() iq['disco_items']['node'] = 'foo' self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#items" node="foo" /> </iq> """) def testIdentities(self): """Testing adding identities to disco#info.""" iq = self.Iq() iq['disco_info'].add_identity('conference', 'text', name='Chatroom', lang='en') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <identity category="conference" type="text" name="Chatroom" xml:lang="en" /> </query> </iq> """) def testDuplicateIdentities(self): """ Test adding multiple copies of the same category and type combination. Only the first identity should be kept. """ iq = self.Iq() iq['disco_info'].add_identity('conference', 'text', name='Chatroom') iq['disco_info'].add_identity('conference', 'text', name='MUC') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <identity category="conference" type="text" name="Chatroom" /> </query> </iq> """) def testDuplicateIdentitiesWithLangs(self): """ Test adding multiple copies of the same category, type, and language combination. Only the first identity should be kept. """ iq = self.Iq() iq['disco_info'].add_identity('conference', 'text', name='Chatroom', lang='en') iq['disco_info'].add_identity('conference', 'text', name='MUC', lang='en') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <identity category="conference" type="text" name="Chatroom" xml:lang="en" /> </query> </iq> """) def testRemoveIdentitiesNoLang(self): """Test removing identities from a disco#info stanza.""" iq = self.Iq() iq['disco_info'].add_identity('client', 'pc') iq['disco_info'].add_identity('client', 'bot') iq['disco_info'].del_identity('client', 'pc') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <identity category="client" type="bot" /> </query> </iq> """) def testRemoveIdentitiesWithLang(self): """Test removing identities from a disco#info stanza.""" iq = self.Iq() iq['disco_info'].add_identity('client', 'pc') iq['disco_info'].add_identity('client', 'bot') iq['disco_info'].add_identity('client', 'pc', lang='no') iq['disco_info'].del_identity('client', 'pc') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <identity category="client" type="bot" /> <identity category="client" type="pc" xml:lang="no" /> </query> </iq> """) def testRemoveAllIdentitiesNoLang(self): """Test removing all identities from a disco#info stanza.""" iq = self.Iq() iq['disco_info'].add_identity('client', 'bot', name='Bot') iq['disco_info'].add_identity('client', 'bot', lang='no') iq['disco_info'].add_identity('client', 'console') del iq['disco_info']['identities'] self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info" /> </iq> """) def testRemoveAllIdentitiesWithLang(self): """Test removing all identities from a disco#info stanza.""" iq = self.Iq() iq['disco_info'].add_identity('client', 'bot', name='Bot') iq['disco_info'].add_identity('client', 'bot', lang='no') iq['disco_info'].add_identity('client', 'console') iq['disco_info'].del_identities(lang='no') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <identity category="client" type="bot" name="Bot" /> <identity category="client" type="console" /> </query> </iq> """) def testAddBatchIdentitiesNoLang(self): """Test adding multiple identities at once to a disco#info stanza.""" iq = self.Iq() identities = [('client', 'pc', 'no', 'PC Client'), ('client', 'bot', None, 'Bot'), ('client', 'console', None, None)] iq['disco_info']['identities'] = identities self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <identity category="client" type="pc" xml:lang="no" name="PC Client" /> <identity category="client" type="bot" name="Bot" /> <identity category="client" type="console" /> </query> </iq> """) def testAddBatchIdentitiesWithLang(self): """Test selectively replacing identities based on language.""" iq = self.Iq() iq['disco_info'].add_identity('client', 'pc', lang='no') iq['disco_info'].add_identity('client', 'pc', lang='en') iq['disco_info'].add_identity('client', 'pc', lang='fr') identities = [('client', 'bot', 'fr', 'Bot'), ('client', 'bot', 'en', 'Bot')] iq['disco_info'].set_identities(identities, lang='fr') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <identity category="client" type="pc" xml:lang="no" /> <identity category="client" type="pc" xml:lang="en" /> <identity category="client" type="bot" xml:lang="fr" name="Bot" /> <identity category="client" type="bot" xml:lang="en" name="Bot" /> </query> </iq> """) def testGetIdentitiesNoLang(self): """Test getting all identities from a disco#info stanza.""" iq = self.Iq() iq['disco_info'].add_identity('client', 'pc') iq['disco_info'].add_identity('client', 'pc', lang='no') iq['disco_info'].add_identity('client', 'pc', lang='en') iq['disco_info'].add_identity('client', 'pc', lang='fr') expected = {('client', 'pc', None, None), ('client', 'pc', 'no', None), ('client', 'pc', 'en', None), ('client', 'pc', 'fr', None)} self.failUnless(iq['disco_info']['identities'] == expected, "Identities do not match:\n%s\n%s" % ( expected, iq['disco_info']['identities'])) def testGetIdentitiesWithLang(self): """ Test getting all identities of a given lang from a disco#info stanza. """ iq = self.Iq() iq['disco_info'].add_identity('client', 'pc') iq['disco_info'].add_identity('client', 'pc', lang='no') iq['disco_info'].add_identity('client', 'pc', lang='en') iq['disco_info'].add_identity('client', 'pc', lang='fr') expected = {('client', 'pc', 'no', None)} result = iq['disco_info'].get_identities(lang='no') self.failUnless(result == expected, "Identities do not match:\n%s\n%s" % ( expected, result)) def testFeatures(self): """Testing adding features to disco#info.""" iq = self.Iq() iq['disco_info'].add_feature('foo') iq['disco_info'].add_feature('bar') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <feature var="foo" /> <feature var="bar" /> </query> </iq> """) def testFeaturesDuplicate(self): """Test adding duplicate features to disco#info.""" iq = self.Iq() iq['disco_info'].add_feature('foo') iq['disco_info'].add_feature('bar') iq['disco_info'].add_feature('foo') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <feature var="foo" /> <feature var="bar" /> </query> </iq> """) def testRemoveFeature(self): """Test removing a feature from disco#info.""" iq = self.Iq() iq['disco_info'].add_feature('foo') iq['disco_info'].add_feature('bar') iq['disco_info'].add_feature('baz') iq['disco_info'].del_feature('foo') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <feature var="bar" /> <feature var="baz" /> </query> </iq> """) def testGetFeatures(self): """Test getting all features from a disco#info stanza.""" iq = self.Iq() iq['disco_info'].add_feature('foo') iq['disco_info'].add_feature('bar') iq['disco_info'].add_feature('baz') expected = {'foo', 'bar', 'baz'} self.failUnless(iq['disco_info']['features'] == expected, "Features do not match:\n%s\n%s" % ( expected, iq['disco_info']['features'])) def testRemoveAllFeatures(self): """Test removing all features from a disco#info stanza.""" iq = self.Iq() iq['disco_info'].add_feature('foo') iq['disco_info'].add_feature('bar') iq['disco_info'].add_feature('baz') del iq['disco_info']['features'] self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info" /> </iq> """) def testAddBatchFeatures(self): """Test adding multiple features at once to a disco#info stanza.""" iq = self.Iq() features = ['foo', 'bar', 'baz'] iq['disco_info']['features'] = features self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#info"> <feature var="foo" /> <feature var="bar" /> <feature var="baz" /> </query> </iq> """) def testItems(self): """Testing adding features to disco#info.""" iq = self.Iq() iq['disco_items'].add_item('user@localhost') iq['disco_items'].add_item('user@localhost', 'foo') iq['disco_items'].add_item('user@localhost', 'bar', name='Testing') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#items"> <item jid="user@localhost" /> <item jid="user@localhost" node="foo" /> <item jid="user@localhost" node="bar" name="Testing" /> </query> </iq> """) def testDuplicateItems(self): """Test adding items with the same JID without any nodes.""" iq = self.Iq() iq['disco_items'].add_item('user@localhost', name='First') iq['disco_items'].add_item('user@localhost', name='Second') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#items"> <item jid="user@localhost" name="First" /> </query> </iq> """) def testDuplicateItemsWithNodes(self): """Test adding items with the same JID/node combination.""" iq = self.Iq() iq['disco_items'].add_item('user@localhost', node='foo', name='First') iq['disco_items'].add_item('user@localhost', node='foo', name='Second') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#items"> <item jid="user@localhost" node="foo" name="First" /> </query> </iq> """) def testRemoveItemsNoNode(self): """Test removing items without nodes from a disco#items stanza.""" iq = self.Iq() iq['disco_items'].add_item('user@localhost') iq['disco_items'].add_item('user@localhost', node='foo') iq['disco_items'].add_item('test@localhost') iq['disco_items'].del_item('user@localhost') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#items"> <item jid="user@localhost" node="foo" /> <item jid="test@localhost" /> </query> </iq> """) def testRemoveItemsWithNode(self): """Test removing items with nodes from a disco#items stanza.""" iq = self.Iq() iq['disco_items'].add_item('user@localhost') iq['disco_items'].add_item('user@localhost', node='foo') iq['disco_items'].add_item('test@localhost') iq['disco_items'].del_item('user@localhost', node='foo') self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#items"> <item jid="user@localhost" /> <item jid="test@localhost" /> </query> </iq> """) def testGetItems(self): """Test retrieving items from disco#items stanza.""" iq = self.Iq() iq['disco_items'].add_item('user@localhost') iq['disco_items'].add_item('user@localhost', node='foo') iq['disco_items'].add_item('test@localhost', node='bar', name='Tester') expected = {('user@localhost', None, None), ('user@localhost', 'foo', None), ('test@localhost', 'bar', 'Tester')} self.failUnless(iq['disco_items']['items'] == expected, "Items do not match:\n%s\n%s" % ( expected, iq['disco_items']['items'])) def testRemoveAllItems(self): """Test removing all items from a disco#items stanza.""" iq = self.Iq() iq['disco_items'].add_item('user@localhost') iq['disco_items'].add_item('user@localhost', node='foo') iq['disco_items'].add_item('test@localhost', node='bar', name='Tester') del iq['disco_items']['items'] self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#items" /> </iq> """) def testAddBatchItems(self): """Test adding multiple items to a disco#items stanza.""" iq = self.Iq() items = [('user@localhost', 'foo', 'Test'), ('test@localhost', None, None), ('other@localhost', None, 'Other')] iq['disco_items']['items'] = items self.check(iq, """ <iq> <query xmlns="http://jabber.org/protocol/disco#items"> <item jid="user@localhost" node="foo" name="Test" /> <item jid="test@localhost" /> <item jid="other@localhost" name="Other" /> </query> </iq> """) suite = unittest.TestLoader().loadTestsFromTestCase(TestDisco)