9578053 Jan 22 2022 distfiles.gentoo.org/distfiles/gajim-1.3.3-2.tar.gz
This commit is contained in:
		
							parent
							
								
									a5b3822651
								
							
						
					
					
						commit
						4c1b226bff
					
				
					 1045 changed files with 753037 additions and 18 deletions
				
			
		
							
								
								
									
										0
									
								
								test/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								test/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										220
									
								
								test/broken/integration/test_gui_event_integration.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								test/broken/integration/test_gui_event_integration.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,220 @@
 | 
			
		|||
'''
 | 
			
		||||
Tests for the miscellaneous functions scattered throughout gajim/gajim.py
 | 
			
		||||
'''
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
import lib
 | 
			
		||||
lib.setup_env()
 | 
			
		||||
 | 
			
		||||
import nbxmpp
 | 
			
		||||
 | 
			
		||||
from gajim.common import gajim
 | 
			
		||||
from gajim.common import contacts as contacts_module
 | 
			
		||||
from gajim.common import caps_cache
 | 
			
		||||
from gajim.gajim import Interface
 | 
			
		||||
 | 
			
		||||
from gajim_mocks import *
 | 
			
		||||
gajim.logger = MockLogger()
 | 
			
		||||
 | 
			
		||||
Interface()
 | 
			
		||||
 | 
			
		||||
import time
 | 
			
		||||
from data import *
 | 
			
		||||
 | 
			
		||||
from gajim import roster_window
 | 
			
		||||
from gajim import plugins
 | 
			
		||||
 | 
			
		||||
class TestStatusChange(unittest.TestCase):
 | 
			
		||||
    '''tests gajim.py's incredibly complex presence handling'''
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
 | 
			
		||||
        gajim.connections = {}
 | 
			
		||||
        gajim.contacts = contacts_module.LegacyContactsAPI()
 | 
			
		||||
        gajim.interface.roster = roster_window.RosterWindow()
 | 
			
		||||
        gajim.plugin_manager = plugins.PluginManager()
 | 
			
		||||
        gajim.logger = MockLogger()
 | 
			
		||||
        caps_cache.initialize(gajim.logger)
 | 
			
		||||
 | 
			
		||||
        for acc in contacts:
 | 
			
		||||
            gajim.connections[acc] = MockConnection(acc)
 | 
			
		||||
 | 
			
		||||
            gajim.interface.roster.fill_contacts_and_groups_dicts(contacts[acc],
 | 
			
		||||
                    acc)
 | 
			
		||||
            gajim.interface.roster.add_account(acc)
 | 
			
		||||
            gajim.interface.roster.add_account_contacts(acc)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(0, len(notify.notifications))
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        notify.notifications = []
 | 
			
		||||
        for acc in contacts:
 | 
			
		||||
            gajim.connections[acc].cleanup()
 | 
			
		||||
 | 
			
		||||
    def contact_comes_online(self, account, jid, resource, prio,
 | 
			
		||||
    should_popup=True):
 | 
			
		||||
        '''a remote contact comes online'''
 | 
			
		||||
        xml = """<presence from='%s/%s' id='123'><priority>%s</priority>
 | 
			
		||||
            <c node='http://gajim.org' ver='pRCD6cgQ4SDqNMCjdhRV6TECx5o='
 | 
			
		||||
            hash='sha-1' xmlns='http://jabber.org/protocol/caps'/>
 | 
			
		||||
            <status>I'm back!</status>
 | 
			
		||||
            </presence>
 | 
			
		||||
        """ % (jid, resource, prio)
 | 
			
		||||
        msg = nbxmpp.protocol.Presence(node=nbxmpp.simplexml.XML2Node(xml))
 | 
			
		||||
        gajim.connections[account]._presenceCB(None, msg)
 | 
			
		||||
 | 
			
		||||
        contact = None
 | 
			
		||||
        for c in gajim.contacts.get_contacts(account, jid):
 | 
			
		||||
            if c.resource == resource:
 | 
			
		||||
                contact = c
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        self.assertEqual('online', contact.show)
 | 
			
		||||
        self.assertEqual("I'm back!", contact.status)
 | 
			
		||||
        self.assertEqual(prio, contact.priority)
 | 
			
		||||
 | 
			
		||||
        # the most recent notification is that the contact connected
 | 
			
		||||
        if should_popup:
 | 
			
		||||
            self.assertEqual('Contact Signed In',
 | 
			
		||||
                notify.notifications[-1].popup_event_type)
 | 
			
		||||
        else:
 | 
			
		||||
            self.assertEqual('', notify.notifications[-1].popup_event_type)
 | 
			
		||||
 | 
			
		||||
    def contact_goes_offline(self, account, jid, resource, prio,
 | 
			
		||||
    still_exists = True):
 | 
			
		||||
        '''a remote contact goes offline.'''
 | 
			
		||||
        xml = """<presence type='unavailable' from='%s/%s' id='123'>
 | 
			
		||||
            <priority>%s</priority>
 | 
			
		||||
            <c node='http://gajim.org' ver='pRCD6cgQ4SDqNMCjdhRV6TECx5o='
 | 
			
		||||
            hash='sha-1' xmlns='http://jabber.org/protocol/caps'/>
 | 
			
		||||
            <status>Goodbye!</status>
 | 
			
		||||
            </presence>
 | 
			
		||||
        """ % (jid, resource, prio)
 | 
			
		||||
        msg = nbxmpp.protocol.Presence(node=nbxmpp.simplexml.XML2Node(xml))
 | 
			
		||||
        gajim.connections[account]._presenceCB(None, msg)
 | 
			
		||||
 | 
			
		||||
        contact = None
 | 
			
		||||
        for c in gajim.contacts.get_contacts(account, jid):
 | 
			
		||||
            if c.resource == resource:
 | 
			
		||||
                contact = c
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        if not still_exists:
 | 
			
		||||
            self.assertTrue(contact is None)
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        self.assertEqual('offline', contact.show)
 | 
			
		||||
        self.assertEqual('Goodbye!', contact.status)
 | 
			
		||||
        self.assertEqual(prio, contact.priority)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual('Contact Signed Out',
 | 
			
		||||
            notify.notifications[-1].popup_event_type)
 | 
			
		||||
 | 
			
		||||
    def user_starts_chatting(self, jid, account, resource=None):
 | 
			
		||||
        '''the user opens a chat window and starts talking'''
 | 
			
		||||
        ctrl = MockChatControl(jid, account)
 | 
			
		||||
        win = MockWindow()
 | 
			
		||||
        win.new_tab(ctrl)
 | 
			
		||||
        gajim.interface.msg_win_mgr._windows['test'] = win
 | 
			
		||||
 | 
			
		||||
        if resource:
 | 
			
		||||
            jid = jid + '/' + resource
 | 
			
		||||
 | 
			
		||||
        # a basic session is started
 | 
			
		||||
        session = gajim.connections[account1].make_new_session(jid,
 | 
			
		||||
                '01234567890abcdef', cls=MockSession)
 | 
			
		||||
        ctrl.set_session(session)
 | 
			
		||||
 | 
			
		||||
        return ctrl
 | 
			
		||||
 | 
			
		||||
    def user_starts_esession(self, jid, resource, account):
 | 
			
		||||
        '''the user opens a chat window and starts an encrypted session'''
 | 
			
		||||
        ctrl = self.user_starts_chatting(jid, account, resource)
 | 
			
		||||
        ctrl.session.status = 'active'
 | 
			
		||||
        ctrl.session.enable_encryption = True
 | 
			
		||||
 | 
			
		||||
        return ctrl
 | 
			
		||||
 | 
			
		||||
    def test_contact_comes_online(self):
 | 
			
		||||
        jid = 'default1@gajim.org'
 | 
			
		||||
 | 
			
		||||
        # contact is offline initially
 | 
			
		||||
        contacts = gajim.contacts.get_contacts(account1, jid)
 | 
			
		||||
        self.assertEqual(1, len(contacts))
 | 
			
		||||
        self.assertEqual('offline', contacts[0].show)
 | 
			
		||||
        self.assertEqual('', contacts[0].status)
 | 
			
		||||
 | 
			
		||||
        self.contact_comes_online(account1, jid, 'lowprio', 1)
 | 
			
		||||
 | 
			
		||||
    def test_contact_goes_offline(self):
 | 
			
		||||
        jid = 'default1@gajim.org'
 | 
			
		||||
 | 
			
		||||
        self.contact_comes_online(account1, jid, 'lowprio', 1)
 | 
			
		||||
 | 
			
		||||
        ctrl = self.user_starts_chatting(jid, account1)
 | 
			
		||||
        orig_sess = ctrl.session
 | 
			
		||||
 | 
			
		||||
        self.contact_goes_offline(account1, jid, 'lowprio', 1)
 | 
			
		||||
 | 
			
		||||
        # session hasn't changed since we were talking to the bare jid
 | 
			
		||||
        self.assertEqual(orig_sess, ctrl.session)
 | 
			
		||||
 | 
			
		||||
    def test_two_resources_higher_comes_online(self):
 | 
			
		||||
        jid = 'default1@gajim.org'
 | 
			
		||||
 | 
			
		||||
        self.contact_comes_online(account1, jid, 'lowprio', 1)
 | 
			
		||||
 | 
			
		||||
        ctrl = self.user_starts_chatting(jid, account1)
 | 
			
		||||
 | 
			
		||||
        self.contact_comes_online(account1, jid, 'highprio', 50,
 | 
			
		||||
            should_popup=False)
 | 
			
		||||
 | 
			
		||||
        # old session was dropped
 | 
			
		||||
        self.assertEqual(None, ctrl.session)
 | 
			
		||||
 | 
			
		||||
    def test_two_resources_higher_goes_offline(self):
 | 
			
		||||
        jid = 'default1@gajim.org'
 | 
			
		||||
 | 
			
		||||
        self.contact_comes_online(account1, jid, 'lowprio', 1)
 | 
			
		||||
        self.contact_comes_online(account1, jid, 'highprio', 50,
 | 
			
		||||
            should_popup=False)
 | 
			
		||||
 | 
			
		||||
        ctrl = self.user_starts_chatting(jid, account1)
 | 
			
		||||
 | 
			
		||||
        self.contact_goes_offline(account1, jid, 'highprio', 50,
 | 
			
		||||
            still_exists=False)
 | 
			
		||||
 | 
			
		||||
        # old session was dropped
 | 
			
		||||
        self.assertEqual(None, ctrl.session)
 | 
			
		||||
 | 
			
		||||
    def test_two_resources_higher_comes_online_with_esession(self):
 | 
			
		||||
        jid = 'default1@gajim.org'
 | 
			
		||||
 | 
			
		||||
        self.contact_comes_online(account1, jid, 'lowprio', 1)
 | 
			
		||||
 | 
			
		||||
        ctrl = self.user_starts_esession(jid, 'lowprio', account1)
 | 
			
		||||
 | 
			
		||||
        self.contact_comes_online(account1, jid, 'highprio', 50,
 | 
			
		||||
            should_popup=False)
 | 
			
		||||
 | 
			
		||||
        # session was associated with the low priority full jid, so it should
 | 
			
		||||
        # have been removed from the control
 | 
			
		||||
        self.assertEqual(None, ctrl.session)
 | 
			
		||||
 | 
			
		||||
    def test_two_resources_higher_goes_offline_with_esession(self):
 | 
			
		||||
        jid = 'default1@gajim.org'
 | 
			
		||||
 | 
			
		||||
        self.contact_comes_online(account1, jid, 'lowprio', 1)
 | 
			
		||||
        self.contact_comes_online(account1, jid, 'highprio', 50)
 | 
			
		||||
 | 
			
		||||
        ctrl = self.user_starts_esession(jid, 'highprio', account1)
 | 
			
		||||
 | 
			
		||||
        self.contact_goes_offline(account1, jid, 'highprio', 50,
 | 
			
		||||
        still_exists=False)
 | 
			
		||||
 | 
			
		||||
        # session was associated with the high priority full jid, so it should
 | 
			
		||||
        # have been removed from the control
 | 
			
		||||
        self.assertEqual(None, ctrl.session)
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
							
								
								
									
										211
									
								
								test/broken/integration/test_roster.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								test/broken/integration/test_roster.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,211 @@
 | 
			
		|||
import unittest
 | 
			
		||||
 | 
			
		||||
import lib
 | 
			
		||||
lib.setup_env()
 | 
			
		||||
 | 
			
		||||
from data import *
 | 
			
		||||
 | 
			
		||||
from gajim_mocks import *
 | 
			
		||||
 | 
			
		||||
from gajim.common import app
 | 
			
		||||
from gajim.common import contacts as contacts_module
 | 
			
		||||
from gajim import roster_window
 | 
			
		||||
 | 
			
		||||
app.get_jid_from_account = lambda acc: 'myjid@' + acc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestRosterWindow(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        app.interface = MockInterface()
 | 
			
		||||
 | 
			
		||||
        self.C_NAME = roster_window.Column.NAME
 | 
			
		||||
        self.C_TYPE = roster_window.Column.TYPE
 | 
			
		||||
        self.C_JID = roster_window.Column.JID
 | 
			
		||||
        self.C_ACCOUNT = roster_window.Column.ACCOUNT
 | 
			
		||||
 | 
			
		||||
        # Add after creating RosterWindow
 | 
			
		||||
        # We want to test the filling explicitly
 | 
			
		||||
        app.contacts = contacts_module.LegacyContactsAPI()
 | 
			
		||||
        app.connections = {}
 | 
			
		||||
        self.roster = roster_window.RosterWindow(app.app)
 | 
			
		||||
 | 
			
		||||
        for acc in contacts:
 | 
			
		||||
            app.connections[acc] = MockConnection(acc)
 | 
			
		||||
            app.contacts.add_account(acc)
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        self.roster.window.destroy()
 | 
			
		||||
        # Clean main loop
 | 
			
		||||
        from gi.repository import GLib
 | 
			
		||||
        mc = GLib.main_context_default()
 | 
			
		||||
        while mc.pending():
 | 
			
		||||
            mc.iteration()
 | 
			
		||||
 | 
			
		||||
    ### Custom assertions
 | 
			
		||||
    def assert_all_contacts_are_in_roster(self, acc):
 | 
			
		||||
        for jid in contacts[acc]:
 | 
			
		||||
            self.assert_contact_is_in_roster(jid, acc)
 | 
			
		||||
 | 
			
		||||
    def assert_contact_is_in_roster(self, jid, account):
 | 
			
		||||
        contacts = app.contacts.get_contacts(account, jid)
 | 
			
		||||
        # check for all resources
 | 
			
		||||
        for contact in contacts:
 | 
			
		||||
            iters = self.roster._get_contact_iter(jid, account,
 | 
			
		||||
                    model=self.roster.model)
 | 
			
		||||
 | 
			
		||||
            if jid != app.get_jid_from_account(account):
 | 
			
		||||
                # We don't care for groups of SelfContact
 | 
			
		||||
                self.assertTrue(len(iters) == len(contact.get_shown_groups()),
 | 
			
		||||
                        msg='Contact is not in all his groups')
 | 
			
		||||
 | 
			
		||||
            # Are we big brother?
 | 
			
		||||
            bb_jid = None
 | 
			
		||||
            bb_account = None
 | 
			
		||||
            family = app.contacts.get_metacontacts_family(account, jid)
 | 
			
		||||
            if family:
 | 
			
		||||
                nearby_family, bb_jid, bb_account = \
 | 
			
		||||
                        self.roster._get_nearby_family_and_big_brother(family, account)
 | 
			
		||||
 | 
			
		||||
                is_in_nearby_family = (jid, account) in (
 | 
			
		||||
                        (data['jid'], data['account']) for data in nearby_family)
 | 
			
		||||
                self.assertTrue(is_in_nearby_family,
 | 
			
		||||
                        msg='Contact not in his own nearby family')
 | 
			
		||||
 | 
			
		||||
            is_big_brother = (bb_jid, bb_account) == (jid, account)
 | 
			
		||||
 | 
			
		||||
            # check for each group tag
 | 
			
		||||
            for titerC in iters:
 | 
			
		||||
                self.assertTrue(self.roster.model.iter_is_valid(titerC),
 | 
			
		||||
                        msg='Contact iter invalid')
 | 
			
		||||
 | 
			
		||||
                c_model = self.roster.model[titerC]
 | 
			
		||||
                # name can be stricked if contact or group is blocked
 | 
			
		||||
#                self.assertEqual(contact.get_shown_name(), c_model[self.C_NAME],
 | 
			
		||||
#                        msg='Contact name missmatch')
 | 
			
		||||
                self.assertEqual(contact.jid, c_model[self.C_JID],
 | 
			
		||||
                        msg='Jid missmatch')
 | 
			
		||||
 | 
			
		||||
                if not self.roster.regroup:
 | 
			
		||||
                    self.assertEqual(account, c_model[self.C_ACCOUNT],
 | 
			
		||||
                            msg='Account missmatch')
 | 
			
		||||
 | 
			
		||||
                # Check for correct nesting
 | 
			
		||||
                parent_iter = self.roster.model.iter_parent(titerC)
 | 
			
		||||
                p_model = self.roster.model[parent_iter]
 | 
			
		||||
                if family:
 | 
			
		||||
                    if is_big_brother:
 | 
			
		||||
                        self.assertTrue(p_model[self.C_TYPE] == 'group',
 | 
			
		||||
                                msg='Big Brother is not on top')
 | 
			
		||||
                    else:
 | 
			
		||||
                        self.assertTrue(p_model[self.C_TYPE] == 'contact',
 | 
			
		||||
                                msg='Little Brother brother has no BigB')
 | 
			
		||||
                else:
 | 
			
		||||
                    if jid == app.get_jid_from_account(account):
 | 
			
		||||
                        self.assertTrue(p_model[self.C_TYPE] == 'account',
 | 
			
		||||
                                msg='SelfContact is not on top')
 | 
			
		||||
                    else:
 | 
			
		||||
                        self.assertTrue(p_model[self.C_TYPE] == 'group',
 | 
			
		||||
                                msg='Contact not found in a group')
 | 
			
		||||
 | 
			
		||||
    def assert_group_is_in_roster(self, group, account):
 | 
			
		||||
        #TODO
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def assert_account_is_in_roster(self, acc):
 | 
			
		||||
        titerA = self.roster._get_account_iter(acc, model=self.roster.model)
 | 
			
		||||
        self.assertTrue(self.roster.model.iter_is_valid(titerA),
 | 
			
		||||
                msg='Account iter is invalid')
 | 
			
		||||
 | 
			
		||||
        acc_model = self.roster.model[titerA]
 | 
			
		||||
        self.assertEqual(acc_model[self.C_TYPE], 'account',
 | 
			
		||||
                msg='No account found')
 | 
			
		||||
 | 
			
		||||
        if not self.roster.regroup:
 | 
			
		||||
            self.assertEqual(acc_model[self.C_ACCOUNT], acc,
 | 
			
		||||
                    msg='Account not found')
 | 
			
		||||
 | 
			
		||||
            self_jid = app.get_jid_from_account(acc)
 | 
			
		||||
            self.assertEqual(acc_model[self.C_JID], self_jid,
 | 
			
		||||
                    msg='Account JID not found in account row')
 | 
			
		||||
 | 
			
		||||
    def assert_model_is_in_sync(self):
 | 
			
		||||
        #TODO: check that iter_n_children returns the correct numbers
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    # tests
 | 
			
		||||
    def test_fill_contacts_and_groups_dicts(self):
 | 
			
		||||
        for acc in contacts:
 | 
			
		||||
            self.roster.fill_contacts_and_groups_dicts(contacts[acc], acc)
 | 
			
		||||
 | 
			
		||||
            for jid in contacts[acc]:
 | 
			
		||||
                instances = app.contacts.get_contacts(acc, jid)
 | 
			
		||||
 | 
			
		||||
                # Created a contact for each single jid?
 | 
			
		||||
                self.assertTrue(len(instances) == 1)
 | 
			
		||||
 | 
			
		||||
                # Contacts kept their info
 | 
			
		||||
                contact = instances[0]
 | 
			
		||||
                self.assertEqual(sorted(contact.groups), sorted(contacts[acc][jid]['groups']),
 | 
			
		||||
                        msg='Group Missmatch')
 | 
			
		||||
 | 
			
		||||
                groups = contacts[acc][jid]['groups'] or ['General',]
 | 
			
		||||
 | 
			
		||||
    def test_fill_roster_model(self):
 | 
			
		||||
        for acc in contacts:
 | 
			
		||||
            self.roster.fill_contacts_and_groups_dicts(contacts[acc], acc)
 | 
			
		||||
 | 
			
		||||
            self.roster.add_account(acc)
 | 
			
		||||
            self.assert_account_is_in_roster(acc)
 | 
			
		||||
 | 
			
		||||
            self.roster.add_account_contacts(acc)
 | 
			
		||||
            self.assert_all_contacts_are_in_roster(acc)
 | 
			
		||||
 | 
			
		||||
        self.assert_model_is_in_sync()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestRosterWindowRegrouped(TestRosterWindow):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        app.settings.set('mergeaccounts', True)
 | 
			
		||||
        TestRosterWindow.setUp(self)
 | 
			
		||||
 | 
			
		||||
    def test_toggle_regroup(self):
 | 
			
		||||
        self.roster.regroup = not self.roster.regroup
 | 
			
		||||
        self.roster.setup_and_draw_roster()
 | 
			
		||||
        self.roster.regroup = not self.roster.regroup
 | 
			
		||||
        self.roster.setup_and_draw_roster()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestRosterWindowMetaContacts(TestRosterWindowRegrouped):
 | 
			
		||||
 | 
			
		||||
    def test_receive_metacontact_data(self):
 | 
			
		||||
        for complete_data in metacontact_data:
 | 
			
		||||
            t_acc = complete_data[0]['account']
 | 
			
		||||
            t_jid = complete_data[0]['jid']
 | 
			
		||||
            data = complete_data[1:]
 | 
			
		||||
            for brother in data:
 | 
			
		||||
                acc = brother['account']
 | 
			
		||||
                jid = brother['jid']
 | 
			
		||||
                app.contacts.add_metacontact(t_acc, t_jid, acc, jid)
 | 
			
		||||
        self.roster.setup_and_draw_roster()
 | 
			
		||||
 | 
			
		||||
    def test_connect_new_metacontact(self):
 | 
			
		||||
        self.test_fill_roster_model()
 | 
			
		||||
 | 
			
		||||
        jid = 'coolstuff@gajim.org'
 | 
			
		||||
        contact = app.contacts.create_contact(jid, account1)
 | 
			
		||||
        app.contacts.add_contact(account1, contact)
 | 
			
		||||
        self.roster.add_contact(jid, account1)
 | 
			
		||||
        self.roster.chg_contact_status(contact, 'offline', '', account1)
 | 
			
		||||
 | 
			
		||||
        app.contacts.add_metacontact(account1, 'samejid@gajim.org',
 | 
			
		||||
                account1, jid)
 | 
			
		||||
        self.roster.chg_contact_status(contact, 'online', '', account1)
 | 
			
		||||
 | 
			
		||||
        self.assert_model_is_in_sync()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
							
								
								
									
										89
									
								
								test/broken/test_pluginmanager.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								test/broken/test_pluginmanager.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
## This file is part of Gajim.
 | 
			
		||||
##
 | 
			
		||||
## Gajim is free software; you can redistribute it and/or modify
 | 
			
		||||
## it under the terms of the GNU General Public License as published
 | 
			
		||||
## by the Free Software Foundation; version 3 only.
 | 
			
		||||
##
 | 
			
		||||
## Gajim is distributed in the hope that it will be useful,
 | 
			
		||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
## GNU General Public License for more details.
 | 
			
		||||
##
 | 
			
		||||
## You should have received a copy of the GNU General Public License
 | 
			
		||||
## along with Gajim.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
##
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
Testing PluginManager class.
 | 
			
		||||
 | 
			
		||||
:author: Mateusz Biliński <mateusz@bilinski.it>
 | 
			
		||||
:since: 05/30/2008
 | 
			
		||||
:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
 | 
			
		||||
:license: GPL
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import os
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
gajim_root = os.path.join(os.path.abspath(os.path.dirname(__file__)), '..')
 | 
			
		||||
sys.path.append(gajim_root + '/gajim')
 | 
			
		||||
 | 
			
		||||
# a temporary version of ~/.gajim for testing
 | 
			
		||||
configdir = gajim_root + '/test/tmp'
 | 
			
		||||
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
# define _ for i18n
 | 
			
		||||
import builtins
 | 
			
		||||
builtins._ = lambda x: x
 | 
			
		||||
 | 
			
		||||
# wipe config directory
 | 
			
		||||
import os
 | 
			
		||||
if os.path.isdir(configdir):
 | 
			
		||||
    import shutil
 | 
			
		||||
    shutil.rmtree(configdir)
 | 
			
		||||
 | 
			
		||||
os.mkdir(configdir)
 | 
			
		||||
 | 
			
		||||
from gajim.common import configpaths
 | 
			
		||||
configpaths.set_config_root(configdir)
 | 
			
		||||
configpaths.init()
 | 
			
		||||
 | 
			
		||||
# for some reason common.app needs to be imported before xmpppy?
 | 
			
		||||
 | 
			
		||||
configpaths.override_path('DATA', gajim_root + '/gajim/data')
 | 
			
		||||
 | 
			
		||||
# name to use for the test account
 | 
			
		||||
account_name = 'test'
 | 
			
		||||
 | 
			
		||||
from plugins import PluginManager
 | 
			
		||||
 | 
			
		||||
class PluginManagerTestCase(unittest.TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.pluginmanager = PluginManager()
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def test_01_Singleton(self):
 | 
			
		||||
        """ 1. Checking whether PluginManger class is singleton. """
 | 
			
		||||
        self.pluginmanager.test_arg = 1
 | 
			
		||||
        secondPluginManager = PluginManager()
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(id(secondPluginManager), id(self.pluginmanager),
 | 
			
		||||
                         'Different IDs in references to PluginManager objects (not a singleton)')
 | 
			
		||||
        self.assertEqual(secondPluginManager.test_arg, 1,
 | 
			
		||||
                         'References point to different PluginManager objects (not a singleton')
 | 
			
		||||
 | 
			
		||||
def suite():
 | 
			
		||||
    suite = unittest.TestLoader().loadTestsFromTestCase(PluginManagerTestCase)
 | 
			
		||||
    return suite
 | 
			
		||||
 | 
			
		||||
if __name__=='__main__':
 | 
			
		||||
    runner = unittest.TextTestRunner()
 | 
			
		||||
    test_suite = suite()
 | 
			
		||||
    runner.run(test_suite)
 | 
			
		||||
							
								
								
									
										156
									
								
								test/broken/unit/test_jingle.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								test/broken/unit/test_jingle.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,156 @@
 | 
			
		|||
'''
 | 
			
		||||
Tests for dispatcher.py
 | 
			
		||||
'''
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
import lib
 | 
			
		||||
lib.setup_env()
 | 
			
		||||
 | 
			
		||||
from mock import Mock
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from nbxmpp import dispatcher
 | 
			
		||||
from nbxmpp.namespaces import Namespace
 | 
			
		||||
 | 
			
		||||
from gajim.common.protocol.bytestream import ConnectionIBBytestream
 | 
			
		||||
from gajim.common.protocol.bytestream import ConnectionSocks5Bytestream
 | 
			
		||||
from gajim.common.jingle import ConnectionJingle
 | 
			
		||||
from gajim.common import app
 | 
			
		||||
from gajim.common.socks5 import SocksQueue
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
session_init = '''
 | 
			
		||||
<iq xmlns="jabber:client" to="jingleft@thiessen.im/Gajim" type="set" id="43">
 | 
			
		||||
<jingle xmlns="urn:xmpp:jingle:1" action="session-initiate" initiator="jtest@thiessen.im/Gajim" sid="38">
 | 
			
		||||
<content name="fileWL1Y2JIPTM5RAD68" creator="initiator">
 | 
			
		||||
<security xmlns="urn:xmpp:jingle:security:xtls:0">
 | 
			
		||||
<method name="x509" />
 | 
			
		||||
</security>
 | 
			
		||||
<description xmlns="urn:xmpp:jingle:apps:file-transfer:1">
 | 
			
		||||
<offer>
 | 
			
		||||
<file xmlns="http://jabber.org/protocol/si/profile/file-transfer" name="to" size="2273">
 | 
			
		||||
<desc />
 | 
			
		||||
</file>
 | 
			
		||||
</offer>
 | 
			
		||||
</description>
 | 
			
		||||
<transport xmlns="urn:xmpp:jingle:transports:s5b:1" sid="39">
 | 
			
		||||
<candidate jid="jtest@thiessen.im/Gajim" cid="40" priority="8257536" host="192.168.2.100" type="direct" port="28011" />
 | 
			
		||||
<candidate jid="proxy.thiessen.im" cid="41" priority="655360" host="192.168.2.100" type="proxy" port="5000" />
 | 
			
		||||
<candidate jid="proxy.jabbim.cz" cid="42" priority="655360" host="192.168.2.100" type="proxy" port="7777" />
 | 
			
		||||
</transport>
 | 
			
		||||
</content>
 | 
			
		||||
</jingle>
 | 
			
		||||
</iq>
 | 
			
		||||
        '''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
transport_info = '''
 | 
			
		||||
<iq from='jtest@thiessen.im/Gajim'
 | 
			
		||||
    id='hjdi8'
 | 
			
		||||
    to='jingleft@thiessen.im/Gajim'
 | 
			
		||||
    type='set'>
 | 
			
		||||
  <jingle xmlns='urn:xmpp:jingle:1'
 | 
			
		||||
          action='transport-info'
 | 
			
		||||
          initiator='jtest@thiessen.im/Gajim'
 | 
			
		||||
          sid='38'>
 | 
			
		||||
    <content creator='initiator' name='fileWL1Y2JIPTM5RAD68'>
 | 
			
		||||
      <transport xmlns='urn:xmpp:jingle:transports:s5b:1'
 | 
			
		||||
                 sid='vj3hs98y'>
 | 
			
		||||
        <candidate-used cid='hr65dqyd'/>
 | 
			
		||||
      </transport>
 | 
			
		||||
    </content>
 | 
			
		||||
  </jingle>
 | 
			
		||||
</iq>
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
class Connection(Mock, ConnectionJingle, ConnectionSocks5Bytestream,
 | 
			
		||||
                 ConnectionIBBytestream):
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        Mock.__init__(self)
 | 
			
		||||
        ConnectionJingle.__init__(self)
 | 
			
		||||
        ConnectionSocks5Bytestream.__init__(self)
 | 
			
		||||
        ConnectionIBBytestream.__init__(self)
 | 
			
		||||
        self.connected = 2 # This tells gajim we are connected
 | 
			
		||||
 | 
			
		||||
    def send(self, stanza=None, when=None):
 | 
			
		||||
        # Called when gajim wants to send something
 | 
			
		||||
        print(str(stanza))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestJingle(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.dispatcher = dispatcher.XMPPDispatcher()
 | 
			
		||||
        app.nec = Mock()
 | 
			
		||||
        app.socks5queue = SocksQueue(Mock())
 | 
			
		||||
        # Setup mock client
 | 
			
		||||
        self.client = Connection()
 | 
			
		||||
        self.client.__str__ = lambda: 'Mock' # FIXME: why do I need this one?
 | 
			
		||||
        self.client._caller = Connection()
 | 
			
		||||
        self.client.defaultNamespace = Namespace.CLIENT
 | 
			
		||||
        self.client.Connection = Connection() # mock transport
 | 
			
		||||
        self.con = self.client.Connection
 | 
			
		||||
        self.con.server_resource = None
 | 
			
		||||
        self.con.connection = Connection()
 | 
			
		||||
 | 
			
		||||
        '''
 | 
			
		||||
        Fake file_props when we receive a file. Gajim creates a file_props
 | 
			
		||||
        out of a FileRequestReceive event and from then on it changes in
 | 
			
		||||
        a lot of places. It is easier to just copy it in here.
 | 
			
		||||
        If the session_initiate stanza changes, this also must change.
 | 
			
		||||
        '''
 | 
			
		||||
        self.receive_file = {'stream-methods':
 | 
			
		||||
                             'http://jabber.org/protocol/bytestreams',
 | 
			
		||||
                             'sender': 'jtest@thiessen.im/Gajim',
 | 
			
		||||
                             'file-name': 'test_received_file',
 | 
			
		||||
                             'request-id': '43', 'sid': '39',
 | 
			
		||||
                             'session-sid': '38', 'session-type': 'jingle',
 | 
			
		||||
                             'transfered_size': [], 'receiver':
 | 
			
		||||
                             'jingleft@thiessen.im/Gajim', 'desc': '',
 | 
			
		||||
                              'size': '2273', 'type': 'r',
 | 
			
		||||
                              'streamhosts': [{'initiator':
 | 
			
		||||
                            'jtest@thiessen.im/Gajim',
 | 
			
		||||
                            'target': 'jingleft@thiessen.im/Gajim',
 | 
			
		||||
                            'cid': '41', 'state': 0, 'host': '192.168.2.100',
 | 
			
		||||
                             'type': 'direct', 'port': '28011'},
 | 
			
		||||
                            {'initiator': 'jtest@thiessen.im/Gajim',
 | 
			
		||||
                              'target': 'jingleft@thiessen.im/Gajim',
 | 
			
		||||
                              'cid': '42', 'state': 0, 'host': '192.168.2.100',
 | 
			
		||||
                              'type': 'proxy', 'port': '5000'}],
 | 
			
		||||
                             'name': 'to'}
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        # Unplug if needed
 | 
			
		||||
        if hasattr(self.dispatcher, '_owner'):
 | 
			
		||||
            self.dispatcher.PlugOut()
 | 
			
		||||
 | 
			
		||||
    def _simulate_connect(self):
 | 
			
		||||
        self.dispatcher.PlugIn(self.client) # client is owner
 | 
			
		||||
        # Simulate that we have established a connection
 | 
			
		||||
        self.dispatcher.StreamInit()
 | 
			
		||||
        self.dispatcher.ProcessNonBlocking("<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'>")
 | 
			
		||||
 | 
			
		||||
    def _simulate_jingle_session(self):
 | 
			
		||||
 | 
			
		||||
        self.dispatcher.RegisterHandler('iq', self.con._JingleCB, 'set',
 | 
			
		||||
                                        Namespace.JINGLE)
 | 
			
		||||
        self.dispatcher.ProcessNonBlocking(session_init)
 | 
			
		||||
        session = list(self.con._sessions.values())[0] # The only session we have
 | 
			
		||||
        jft = list(session.contents.values())[0] # jingleFT object
 | 
			
		||||
        jft.file_props = self.receive_file # We plug file_props manually
 | 
			
		||||
        # The user accepts to receive the file
 | 
			
		||||
        # we have to manually simulate this behavior
 | 
			
		||||
        session.approve_session()
 | 
			
		||||
        self.con.send_file_approval(self.receive_file)
 | 
			
		||||
 | 
			
		||||
        self.dispatcher.ProcessNonBlocking(transport_info)
 | 
			
		||||
 | 
			
		||||
    def test_jingle_session(self):
 | 
			
		||||
        self._simulate_connect()
 | 
			
		||||
        self._simulate_jingle_session()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
							
								
								
									
										167
									
								
								test/broken/unit/test_sessions.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								test/broken/unit/test_sessions.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,167 @@
 | 
			
		|||
import unittest
 | 
			
		||||
 | 
			
		||||
import lib
 | 
			
		||||
lib.setup_env()
 | 
			
		||||
 | 
			
		||||
import notify
 | 
			
		||||
import nbxmpp
 | 
			
		||||
 | 
			
		||||
from gajim.common import app
 | 
			
		||||
from gajim.common import nec
 | 
			
		||||
from gajim.common import ged
 | 
			
		||||
from gajim.common.nec import NetworkEvent
 | 
			
		||||
 | 
			
		||||
from gajim.session import ChatControlSession
 | 
			
		||||
from gajim.roster_window import RosterWindow
 | 
			
		||||
 | 
			
		||||
from gajim_mocks import *
 | 
			
		||||
from data import account1
 | 
			
		||||
 | 
			
		||||
app.interface = MockInterface()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# name to use for the test account
 | 
			
		||||
account_name = account1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestChatControlSession(unittest.TestCase):
 | 
			
		||||
    ''' Testclass for session.py '''
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def setUpClass(cls):
 | 
			
		||||
        app.nec = nec.NetworkEventsController()
 | 
			
		||||
        cls.conn = MockConnection(account_name, {'send_stanza': None})
 | 
			
		||||
        app.logger = MockLogger()
 | 
			
		||||
        app.default_session_type = ChatControlSession
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        app.notification = notify.Notification()
 | 
			
		||||
 | 
			
		||||
        # no notifications have been sent
 | 
			
		||||
        self.assertEqual(0, len(notify.notifications))
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        app.notification.clean()
 | 
			
		||||
 | 
			
		||||
    def receive_chat_msg(self, jid, msgtxt):
 | 
			
		||||
        '''simulate receiving a chat message from jid'''
 | 
			
		||||
        msg = nbxmpp.Message()
 | 
			
		||||
        msg.setBody(msgtxt)
 | 
			
		||||
        msg.setType('chat')
 | 
			
		||||
 | 
			
		||||
        xml = """<message from='%s' id='1' type='chat'><body>%s</body>
 | 
			
		||||
            <thread>123</thread></message>""" % (jid, msgtxt)
 | 
			
		||||
        stanza = nbxmpp.protocol.Message(node=nbxmpp.simplexml.XML2Node(xml))
 | 
			
		||||
        self.conn._messageCB(None, stanza)
 | 
			
		||||
 | 
			
		||||
    # ----- custom assertions -----
 | 
			
		||||
    def assert_new_message_notification(self):
 | 
			
		||||
        '''a new_message notification has been sent'''
 | 
			
		||||
        self.assertEqual(1, len(notify.notifications))
 | 
			
		||||
        notif = notify.notifications[-1]
 | 
			
		||||
        self.assertEqual('New Message', notif.popup_event_type)
 | 
			
		||||
 | 
			
		||||
    def assert_first_message_notification(self):
 | 
			
		||||
        '''this message was treated as a first message'''
 | 
			
		||||
        self.assert_new_message_notification()
 | 
			
		||||
        notif = notify.notifications[-1]
 | 
			
		||||
        first = notif.first_unread
 | 
			
		||||
        self.assertTrue(first,
 | 
			
		||||
            'message should have been treated as a first message')
 | 
			
		||||
 | 
			
		||||
    def assert_not_first_message_notification(self):
 | 
			
		||||
        '''this message was not treated as a first message'''
 | 
			
		||||
        self.assert_new_message_notification()
 | 
			
		||||
        notif = notify.notifications[-1]
 | 
			
		||||
        first = notif.first_unread
 | 
			
		||||
        self.assertTrue(not first,
 | 
			
		||||
            'message was unexpectedly treated as a first message')
 | 
			
		||||
 | 
			
		||||
    # ----- tests -----
 | 
			
		||||
    def test_receive_1nocontrol(self):
 | 
			
		||||
        '''test receiving a message in a blank state'''
 | 
			
		||||
        jid = 'bct@necronomicorp.com'
 | 
			
		||||
        fjid = 'bct@necronomicorp.com/Gajim'
 | 
			
		||||
        msgtxt = 'testing one'
 | 
			
		||||
 | 
			
		||||
        self.receive_chat_msg(fjid, msgtxt)
 | 
			
		||||
 | 
			
		||||
        # session is created
 | 
			
		||||
        self.assertTrue((jid in self.conn.sessions) and (
 | 
			
		||||
            '123' in self.conn.sessions[jid]), 'session is not created')
 | 
			
		||||
        sess = self.conn.sessions[jid]['123']
 | 
			
		||||
 | 
			
		||||
        # message was logged
 | 
			
		||||
        calls = app.storage.archive.mockGetNamedCalls('insert_into_logs')
 | 
			
		||||
        self.assertEqual(1, len(calls))
 | 
			
		||||
 | 
			
		||||
        # no ChatControl was open and autopopup was off
 | 
			
		||||
        # so the message goes into the event queue
 | 
			
		||||
        self.assertEqual(1, len(app.events.get_events(account_name)))
 | 
			
		||||
 | 
			
		||||
        self.assert_first_message_notification()
 | 
			
		||||
 | 
			
		||||
        # no control is attached to the session
 | 
			
		||||
        self.assertEqual(None, sess.control)
 | 
			
		||||
 | 
			
		||||
    def test_receive_2already_has_control(self):
 | 
			
		||||
        '''test receiving a message with a session already attached to a
 | 
			
		||||
        control'''
 | 
			
		||||
        jid = 'bct@necronomicorp.com'
 | 
			
		||||
        fjid = 'bct@necronomicorp.com/Gajim'
 | 
			
		||||
        msgtxt = 'testing two'
 | 
			
		||||
        app.interface.roster = RosterWindow(app.app)
 | 
			
		||||
 | 
			
		||||
        sess = self.conn.sessions[jid]['123']
 | 
			
		||||
        sess.control = MockChatControl(fjid, account_name)
 | 
			
		||||
 | 
			
		||||
        self.receive_chat_msg(fjid, msgtxt)
 | 
			
		||||
 | 
			
		||||
        # message was logged
 | 
			
		||||
        calls = app.storage.archive.mockGetNamedCalls('insert_into_logs')
 | 
			
		||||
        self.assertEqual(2, len(calls))
 | 
			
		||||
 | 
			
		||||
        # the message does not go into the event queue
 | 
			
		||||
        self.assertEqual(1, len(app.events.get_events(account_name)))
 | 
			
		||||
 | 
			
		||||
        self.assert_not_first_message_notification()
 | 
			
		||||
 | 
			
		||||
        # message was printed to the control
 | 
			
		||||
        calls = sess.control.mockGetNamedCalls('print_conversation')
 | 
			
		||||
        self.assertEqual(1, len(calls))
 | 
			
		||||
        app.interface.roster.window.destroy()
 | 
			
		||||
 | 
			
		||||
    #def test_received_3orphaned_control(self):
 | 
			
		||||
        #'''test receiving a message when a control that doesn't have a session
 | 
			
		||||
        #attached exists'''
 | 
			
		||||
 | 
			
		||||
        #jid = 'bct@necronomicorp.com'
 | 
			
		||||
        #fjid = jid + '/Gajim'
 | 
			
		||||
        #msgtxt = 'testing three'
 | 
			
		||||
 | 
			
		||||
        #ctrl = MockChatControl(jid, account_name)
 | 
			
		||||
        #gajim.interface.msg_win_mgr = Mock({'get_control': ctrl})
 | 
			
		||||
        #gajim.interface.msg_win_mgr.mockSetExpectation('get_control',
 | 
			
		||||
                #expectParams(jid, account_name))
 | 
			
		||||
 | 
			
		||||
        #self.receive_chat_msg(fjid, msgtxt)
 | 
			
		||||
 | 
			
		||||
        ## message was logged
 | 
			
		||||
        #calls = gajim.logger.mockGetNamedCalls('insert_into_logs')
 | 
			
		||||
        #self.assertEqual(1, len(calls))
 | 
			
		||||
 | 
			
		||||
        ## the message does not go into the event queue
 | 
			
		||||
        #self.assertEqual(0, len(gajim.events.get_events(account_name)))
 | 
			
		||||
 | 
			
		||||
        #self.assert_not_first_message_notification()
 | 
			
		||||
 | 
			
		||||
        ## this session is now attached to that control
 | 
			
		||||
        #self.assertEqual(self.sess, ctrl.session)
 | 
			
		||||
        #self.assertEqual(ctrl, self.sess.control, 'foo')
 | 
			
		||||
 | 
			
		||||
        ## message was printed to the control
 | 
			
		||||
        #calls = ctrl.mockGetNamedCalls('print_conversation')
 | 
			
		||||
        #self.assertEqual(1, len(calls))
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
							
								
								
									
										172
									
								
								test/broken/unit/test_socks5.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								test/broken/unit/test_socks5.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,172 @@
 | 
			
		|||
'''
 | 
			
		||||
Tests for dispatcher.py
 | 
			
		||||
'''
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
import lib
 | 
			
		||||
lib.setup_env()
 | 
			
		||||
 | 
			
		||||
from mock import Mock
 | 
			
		||||
import sys
 | 
			
		||||
import socket
 | 
			
		||||
 | 
			
		||||
from gajim.common.socks5 import *
 | 
			
		||||
from gajim.common import jingle_xtls
 | 
			
		||||
 | 
			
		||||
class fake_sock(Mock):
 | 
			
		||||
    def __init__(self, sockobj):
 | 
			
		||||
        Mock.__init__(self)
 | 
			
		||||
 | 
			
		||||
        self.sockobj = sockobj
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def setup_stream(self):
 | 
			
		||||
        sha1 = self.sockobj._get_sha1_auth()
 | 
			
		||||
 | 
			
		||||
        self.incoming = []
 | 
			
		||||
        self.incoming.append(self.sockobj._get_auth_response())
 | 
			
		||||
        self.incoming.append(self.sockobj._get_request_buff(sha1, 0x00))
 | 
			
		||||
        self.outgoing = []
 | 
			
		||||
        self.outgoing.append(self.sockobj._get_auth_buff())
 | 
			
		||||
        self.outgoing.append(self.sockobj._get_request_buff(sha1))
 | 
			
		||||
 | 
			
		||||
    def switch_stream(self):
 | 
			
		||||
        # Roles are reversed, client will be expecting server stream
 | 
			
		||||
        # and server will be expecting client stream
 | 
			
		||||
 | 
			
		||||
        temp = self.incoming
 | 
			
		||||
        self.incoming = self.outgoing
 | 
			
		||||
        self.outgoing = temp
 | 
			
		||||
 | 
			
		||||
    def _recv(self, foo):
 | 
			
		||||
        return self.incoming.pop(0)
 | 
			
		||||
 | 
			
		||||
    def _send(self, data):
 | 
			
		||||
        # This method is surrounded by a try block,
 | 
			
		||||
        # we can't use assert here
 | 
			
		||||
 | 
			
		||||
        if data != self.outgoing[0]:
 | 
			
		||||
            print('FAILED SENDING TEST')
 | 
			
		||||
        self.outgoing.pop(0)
 | 
			
		||||
 | 
			
		||||
class fake_idlequeue(Mock):
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        Mock.__init__(self)
 | 
			
		||||
 | 
			
		||||
    def plug_idle(self, obj, writable=True, readable=True):
 | 
			
		||||
 | 
			
		||||
        if readable:
 | 
			
		||||
            obj.pollin()
 | 
			
		||||
        if writable:
 | 
			
		||||
            obj.pollout()
 | 
			
		||||
 | 
			
		||||
class TestSocks5(unittest.TestCase):
 | 
			
		||||
    '''
 | 
			
		||||
    Test class for Socks5
 | 
			
		||||
    '''
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        streamhost = { 'host': None,
 | 
			
		||||
                       'port': 1,
 | 
			
		||||
                       'initiator' : None,
 | 
			
		||||
                       'target' : None}
 | 
			
		||||
        queue = Mock()
 | 
			
		||||
        queue.file_props = {}
 | 
			
		||||
        #self.sockobj = Socks5Receiver(fake_idlequeue(), streamhost, None)
 | 
			
		||||
        self.sockobj = Socks5Sender(fake_idlequeue(), None, 'server', Mock() ,
 | 
			
		||||
                                    None, None, True, file_props={})
 | 
			
		||||
        sock = fake_sock(self.sockobj)
 | 
			
		||||
        self.sockobj._sock = sock
 | 
			
		||||
        self.sockobj._recv = sock._recv
 | 
			
		||||
        self.sockobj._send = sock._send
 | 
			
		||||
        self.sockobj.state = 1
 | 
			
		||||
        self.sockobj.connected = True
 | 
			
		||||
        self.sockobj.pollend = self._pollend
 | 
			
		||||
 | 
			
		||||
        # Something that the receiver needs
 | 
			
		||||
        #self.sockobj.file_props['type'] = 'r'
 | 
			
		||||
 | 
			
		||||
        # Something that the sender needs
 | 
			
		||||
        self.sockobj.file_props = {}
 | 
			
		||||
        self.sockobj.file_props['type'] = 'r'
 | 
			
		||||
        self.sockobj.file_props['paused'] = ''
 | 
			
		||||
        self.sockobj.queue = Mock()
 | 
			
		||||
        self.sockobj.queue.process_result = self._pollend
 | 
			
		||||
 | 
			
		||||
    def _pollend(self, foo = None, duu = None):
 | 
			
		||||
        # This is a disconnect function
 | 
			
		||||
        sys.exit("end of the road")
 | 
			
		||||
 | 
			
		||||
    def _check_inout(self):
 | 
			
		||||
        # Check if there isn't anything else to receive or send
 | 
			
		||||
        sock = self.sockobj._sock
 | 
			
		||||
        assert(sock.incoming == [])
 | 
			
		||||
        assert(sock.outgoing == [])
 | 
			
		||||
 | 
			
		||||
    def test_connection_server(self):
 | 
			
		||||
        return
 | 
			
		||||
        mocksock = self.sockobj._sock
 | 
			
		||||
        mocksock.setup_stream()
 | 
			
		||||
        #self.sockobj._sock.switch_stream()
 | 
			
		||||
        s = socket.socket(2, 1, 6)
 | 
			
		||||
        server = ('127.0.0.1', 28000)
 | 
			
		||||
 | 
			
		||||
        s.connect(server)
 | 
			
		||||
 | 
			
		||||
        s.send(mocksock.outgoing.pop(0))
 | 
			
		||||
        self.assertEqual(s.recv(64), mocksock.incoming.pop(0))
 | 
			
		||||
 | 
			
		||||
        s.send(mocksock.outgoing.pop(0))
 | 
			
		||||
        self.assertEqual(s.recv(64), mocksock.incoming.pop(0))
 | 
			
		||||
 | 
			
		||||
    def test_connection_client(self):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        mocksock = self.sockobj._sock
 | 
			
		||||
        mocksock.setup_stream()
 | 
			
		||||
        mocksock.switch_stream()
 | 
			
		||||
        s = socket.socket(10, 1, 6)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 | 
			
		||||
        s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
 | 
			
		||||
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
 | 
			
		||||
 | 
			
		||||
        netadd = ('::', 28000, 0, 0)
 | 
			
		||||
        s.bind(netadd)
 | 
			
		||||
        s.listen(socket.SOMAXCONN)
 | 
			
		||||
        (s, address) = s.accept()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(s.recv(64), mocksock.incoming.pop(0))
 | 
			
		||||
        s.send(mocksock.outgoing.pop(0))
 | 
			
		||||
 | 
			
		||||
        buff = s.recv(64)
 | 
			
		||||
        inco = mocksock.incoming.pop(0)
 | 
			
		||||
        #self.assertEqual(s.recv(64), mocksock.incoming.pop(0))
 | 
			
		||||
        s.send(mocksock.outgoing.pop(0))
 | 
			
		||||
 | 
			
		||||
    def test_client_negoc(self):
 | 
			
		||||
        return
 | 
			
		||||
        self.sockobj._sock.setup_stream()
 | 
			
		||||
        try:
 | 
			
		||||
            self.sockobj.pollout()
 | 
			
		||||
        except SystemExit:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        self._check_inout()
 | 
			
		||||
 | 
			
		||||
    def test_server_negoc(self):
 | 
			
		||||
        return
 | 
			
		||||
        self.sockobj._sock.setup_stream()
 | 
			
		||||
        self.sockobj._sock.switch_stream()
 | 
			
		||||
        try:
 | 
			
		||||
            self.sockobj.idlequeue.plug_idle(self.sockobj, False, True)
 | 
			
		||||
        except SystemExit:
 | 
			
		||||
            pass
 | 
			
		||||
        self._check_inout()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    unittest.main()
 | 
			
		||||
							
								
								
									
										137
									
								
								test/gtk/assistant.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								test/gtk/assistant.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,137 @@
 | 
			
		|||
import gi
 | 
			
		||||
gi.require_version('Gtk', '3.0')
 | 
			
		||||
from gi.repository import Gtk
 | 
			
		||||
 | 
			
		||||
from gajim.common.const import CSSPriority
 | 
			
		||||
 | 
			
		||||
from gajim import gui
 | 
			
		||||
gui.init('gtk')
 | 
			
		||||
 | 
			
		||||
from gajim.gui.assistant import Assistant
 | 
			
		||||
from gajim.gui.assistant import Page
 | 
			
		||||
 | 
			
		||||
from test.gtk import util
 | 
			
		||||
util.load_style('gajim.css', CSSPriority.APPLICATION)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestAssistant(Assistant):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        Assistant.__init__(self)
 | 
			
		||||
 | 
			
		||||
        self.add_pages({'start': Start()})
 | 
			
		||||
 | 
			
		||||
        progress = self.add_default_page('progress')
 | 
			
		||||
        progress.set_title('Executing...')
 | 
			
		||||
        progress.set_text('Something is in progress...')
 | 
			
		||||
 | 
			
		||||
        error = self.add_default_page('error')
 | 
			
		||||
        error.set_title('Error')
 | 
			
		||||
        error.set_heading('Error Heading')
 | 
			
		||||
        error.set_text('This is the error text')
 | 
			
		||||
 | 
			
		||||
        success = self.add_default_page('success')
 | 
			
		||||
        success.set_title('Success')
 | 
			
		||||
        success.set_heading('Success Heading')
 | 
			
		||||
        success.set_text('This is the success text')
 | 
			
		||||
 | 
			
		||||
        self.add_button('forward', 'Forward', 'suggested-action', complete=True)
 | 
			
		||||
        self.add_button('close', 'Close', 'destructive-action')
 | 
			
		||||
        self.add_button('back', 'Back')
 | 
			
		||||
 | 
			
		||||
        self.set_button_visible_func(self._visible_func)
 | 
			
		||||
 | 
			
		||||
        self.connect('button-clicked', self._on_button_clicked)
 | 
			
		||||
        self.connect('page-changed', self._on_page_changed)
 | 
			
		||||
 | 
			
		||||
        self.show_all()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _visible_func(_assistant, page_name):
 | 
			
		||||
        if page_name == 'start':
 | 
			
		||||
            return ['forward']
 | 
			
		||||
 | 
			
		||||
        if page_name == 'progress':
 | 
			
		||||
            return ['forward', 'back']
 | 
			
		||||
 | 
			
		||||
        if page_name == 'success':
 | 
			
		||||
            return ['forward', 'back']
 | 
			
		||||
 | 
			
		||||
        if page_name == 'error':
 | 
			
		||||
            return ['back', 'close']
 | 
			
		||||
        raise ValueError('page %s unknown' % page_name)
 | 
			
		||||
 | 
			
		||||
    def _on_button_clicked(self, _assistant, button_name):
 | 
			
		||||
        page = self.get_current_page()
 | 
			
		||||
        if button_name == 'forward':
 | 
			
		||||
            if page == 'start':
 | 
			
		||||
                self.show_page('progress', Gtk.StackTransitionType.SLIDE_LEFT)
 | 
			
		||||
            elif page == 'progress':
 | 
			
		||||
                self.show_page('success', Gtk.StackTransitionType.SLIDE_LEFT)
 | 
			
		||||
            elif page == 'success':
 | 
			
		||||
                self.show_page('error', Gtk.StackTransitionType.SLIDE_LEFT)
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if button_name == 'back':
 | 
			
		||||
            if page == 'progress':
 | 
			
		||||
                self.show_page('start')
 | 
			
		||||
            if page == 'success':
 | 
			
		||||
                self.show_page('progress')
 | 
			
		||||
            if page == 'error':
 | 
			
		||||
                self.show_page('success')
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if button_name == 'close':
 | 
			
		||||
            self.destroy()
 | 
			
		||||
 | 
			
		||||
    def _on_page_changed(self, _assistant, page_name):
 | 
			
		||||
        if page_name == 'start':
 | 
			
		||||
            self.set_default_button('forward')
 | 
			
		||||
 | 
			
		||||
        elif page_name == 'progress':
 | 
			
		||||
            self.set_default_button('forward')
 | 
			
		||||
 | 
			
		||||
        elif page_name == 'success':
 | 
			
		||||
            self.set_default_button('forward')
 | 
			
		||||
 | 
			
		||||
        elif page_name == 'error':
 | 
			
		||||
            self.set_default_button('back')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Start(Page):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        Page.__init__(self)
 | 
			
		||||
 | 
			
		||||
        self.title = 'Start'
 | 
			
		||||
        self.complete = False
 | 
			
		||||
 | 
			
		||||
        heading = Gtk.Label(label='Test Assistant')
 | 
			
		||||
        heading.get_style_context().add_class('large-header')
 | 
			
		||||
 | 
			
		||||
        label1 = Gtk.Label(label='This is label 1 with some text')
 | 
			
		||||
        label1.set_max_width_chars(50)
 | 
			
		||||
        label1.set_line_wrap(True)
 | 
			
		||||
        label1.set_halign(Gtk.Align.CENTER)
 | 
			
		||||
        label1.set_justify(Gtk.Justification.CENTER)
 | 
			
		||||
        label1.set_margin_bottom(24)
 | 
			
		||||
 | 
			
		||||
        entry = Gtk.Entry(activates_default=True)
 | 
			
		||||
        entry.connect('changed', self._on_changed)
 | 
			
		||||
 | 
			
		||||
        self._server = Gtk.CheckButton.new_with_mnemonic('A fancy checkbox')
 | 
			
		||||
        self._server.set_halign(Gtk.Align.CENTER)
 | 
			
		||||
 | 
			
		||||
        self.pack_start(heading, False, True, 0)
 | 
			
		||||
        self.pack_start(label1, False, True, 0)
 | 
			
		||||
        self.pack_start(entry, False, True, 0)
 | 
			
		||||
        self.pack_start(self._server, False, True, 0)
 | 
			
		||||
        self.show_all()
 | 
			
		||||
 | 
			
		||||
    def _on_changed(self, entry):
 | 
			
		||||
        self.complete = bool(entry.get_text())
 | 
			
		||||
        self.update_page_complete()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
win = TestAssistant()
 | 
			
		||||
win.connect('destroy', Gtk.main_quit)
 | 
			
		||||
win.show_all()
 | 
			
		||||
Gtk.main()
 | 
			
		||||
							
								
								
									
										54
									
								
								test/gtk/certificate_dialog.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								test/gtk/certificate_dialog.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
import gi
 | 
			
		||||
gi.require_version('Gtk', '3.0')
 | 
			
		||||
from gi.repository import Gtk
 | 
			
		||||
 | 
			
		||||
import OpenSSL
 | 
			
		||||
 | 
			
		||||
from gajim import gui
 | 
			
		||||
gui.init('gtk')
 | 
			
		||||
 | 
			
		||||
from test.gtk import util
 | 
			
		||||
from gajim.common.const import CSSPriority
 | 
			
		||||
from gajim.gui.dialogs import CertificateDialog
 | 
			
		||||
 | 
			
		||||
util.load_style('gajim.css', CSSPriority.APPLICATION)
 | 
			
		||||
 | 
			
		||||
cert = '''
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIFhDCCBGygAwIBAgISA4oUEifTr7Y+mcdiwu6KWpcVMA0GCSqGSIb3DQEBCwUA
 | 
			
		||||
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
 | 
			
		||||
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTA0MDMxODE3NDVaFw0x
 | 
			
		||||
OTA3MDIxODE3NDVaMBsxGTAXBgNVBAMMECoubGlnaHR3aXRjaC5vcmcwggEiMA0G
 | 
			
		||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/3mcevikse7QwDYwPcGAD9zHw3UWE
 | 
			
		||||
7J8SJR349/rFTF2tBFDvEa62OUKTCg5vPKVKaXHlzruk/A7blgqsEdugycORwPD1
 | 
			
		||||
7YNJ27EldrRtotjclurzKL6D/MgcaQ4cTkPOD3cWbf/L+HClGrpFt7su6Z6cTutC
 | 
			
		||||
wiAYAdlfmVgSSv15F1xOTyFyfGJKQnW628Xs8xUvZh5H/SsEEum4MwVVGW06Z/A/
 | 
			
		||||
mwX2jmJUb2M25S1Ma025nZpGYyAAqecTmPb3fStnXm4sdytfZhm4+nj9mH9GQIU1
 | 
			
		||||
t/jO/7X7IFpc9DvVRSumSVqvNaVgiWmTLP4VxlCVJO6mibOXXUUDA5RfAgMBAAGj
 | 
			
		||||
ggKRMIICjTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
 | 
			
		||||
AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFC4/ZRurw2wVFsgJBTb9Fh/3
 | 
			
		||||
0aV9MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUFBwEB
 | 
			
		||||
BGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0
 | 
			
		||||
Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNyeXB0
 | 
			
		||||
Lm9yZy8wSQYDVR0RBEIwQIIQKi5saWdodHdpdGNoLm9yZ4IOKi5tZXRyb25vbWUu
 | 
			
		||||
aW2CDmxpZ2h0d2l0Y2gub3JnggxtZXRyb25vbWUuaW0wTAYDVR0gBEUwQzAIBgZn
 | 
			
		||||
gQwBAgEwNwYLKwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5s
 | 
			
		||||
ZXRzZW5jcnlwdC5vcmcwggECBgorBgEEAdZ5AgQCBIHzBIHwAO4AdQB0ftqDMa0z
 | 
			
		||||
EJEhnM4lT0Jwwr/9XkIgCMY3NXnmEHvMVgAAAWnkosBAAAAEAwBGMEQCICEfmTBk
 | 
			
		||||
OxS95eiYsfTH5HdL7kfp68BSin5LqeGyyxk9AiA3qeDZNKklJTdWqYjto7kUqJNd
 | 
			
		||||
YiL99SrqwzR6w+AqSwB1ACk8UZZUyDlluqpQ/FgH1Ldvv1h6KXLcpMMM9OVFR/R4
 | 
			
		||||
AAABaeSiwEUAAAQDAEYwRAIgFxouOkJeqkQUe6zNI5w/6YBIQFrsrIZdPcX+r6JI
 | 
			
		||||
is8CIEEETzlEyj9lWR/BSSruSp0FT5CuoNNeEG7HxrJ+gVhZMA0GCSqGSIb3DQEB
 | 
			
		||||
CwUAA4IBAQAQtfs1NPNMmBQRcKsZyGLZsvpp2hIhdYi72RYnHnIl4MXbhyNj9xtI
 | 
			
		||||
cJr9PQ+3FsSnxy7LDjZMpbmBuXhawOyPBPw2M0f0Tv6Eo6miwvP/X1kLE3VjTzCo
 | 
			
		||||
6JPh6bEB5wa+kH/pUcGlV6uyT7IuXOiArx0VmIpTA3uwlVdfynOnR3CF20Ds4FLc
 | 
			
		||||
JxbGMqRuw/sGiTLKlXc1xVil8WZjL3hokzrgI7K6np2skUjWuMZvhJgwi5QiE7/C
 | 
			
		||||
ejsJoYkpvcaiaLAyVymTY/n/oM2oQpv5Mqjit+18RB9c2P+ifH5iDKC/jTKn4NNz
 | 
			
		||||
8xSTlUlCBTCozjzscZVeVDIojmejWclT
 | 
			
		||||
-----END CERTIFICATE-----'''
 | 
			
		||||
 | 
			
		||||
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
 | 
			
		||||
win = CertificateDialog(None, 'testacc', cert)
 | 
			
		||||
win.connect("destroy", Gtk.main_quit)
 | 
			
		||||
win.show_all()
 | 
			
		||||
Gtk.main()
 | 
			
		||||
							
								
								
									
										40
									
								
								test/gtk/change_password.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								test/gtk/change_password.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
from functools import partial
 | 
			
		||||
 | 
			
		||||
import gi
 | 
			
		||||
gi.require_version('Gtk', '3.0')
 | 
			
		||||
from gi.repository import Gtk
 | 
			
		||||
 | 
			
		||||
from nbxmpp.modules.dataforms import create_field
 | 
			
		||||
from nbxmpp.modules.dataforms import SimpleDataForm
 | 
			
		||||
 | 
			
		||||
from gajim.common.const import CSSPriority
 | 
			
		||||
 | 
			
		||||
from gajim import gui
 | 
			
		||||
gui.init('gtk')
 | 
			
		||||
 | 
			
		||||
from gajim.gui.change_password import ChangePassword
 | 
			
		||||
 | 
			
		||||
from test.gtk import util
 | 
			
		||||
util.load_style('gajim.css', CSSPriority.APPLICATION)
 | 
			
		||||
 | 
			
		||||
fields = [
 | 
			
		||||
    create_field(typ='text-single', label='Username', var='username'),
 | 
			
		||||
    create_field(typ='text-single', label='Old Password', var='old_password'),
 | 
			
		||||
    create_field(typ='text-single', label='Mothers name', var='mother', required=True),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
form = SimpleDataForm(type_='form', fields=fields)
 | 
			
		||||
 | 
			
		||||
def _apply(self, next_stage=False):
 | 
			
		||||
    if next_stage:
 | 
			
		||||
        print(self.get_page('next_stage').get_submit_form())
 | 
			
		||||
    else:
 | 
			
		||||
        self.get_page('next_stage').set_form(form)
 | 
			
		||||
        self.show_page('next_stage', Gtk.StackTransitionType.SLIDE_LEFT)
 | 
			
		||||
 | 
			
		||||
win = ChangePassword(None)
 | 
			
		||||
win._on_apply = partial(_apply, win)
 | 
			
		||||
 | 
			
		||||
win.connect('destroy', Gtk.main_quit)
 | 
			
		||||
win.show_all()
 | 
			
		||||
Gtk.main()
 | 
			
		||||
							
								
								
									
										133
									
								
								test/gtk/dataform.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								test/gtk/dataform.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,133 @@
 | 
			
		|||
from base64 import b64decode
 | 
			
		||||
 | 
			
		||||
from gi.repository import Gtk
 | 
			
		||||
import nbxmpp
 | 
			
		||||
from nbxmpp.modules.dataforms import extend_form
 | 
			
		||||
 | 
			
		||||
from gajim import gui
 | 
			
		||||
gui.init('gtk')
 | 
			
		||||
 | 
			
		||||
from gajim.gui.dataform import DataFormWidget
 | 
			
		||||
from gajim.common.const import CSSPriority
 | 
			
		||||
from gajim.common import app
 | 
			
		||||
 | 
			
		||||
from test.gtk import util
 | 
			
		||||
util.load_style('gajim.css', CSSPriority.APPLICATION)
 | 
			
		||||
 | 
			
		||||
image = '''iVBORw0KGgoAAAANSUhEUgAAAIwAAAA8CAAAAACRYQ2XAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfiCwQXMiypK
 | 
			
		||||
zsIAAAM4ElEQVRo3u1ZeVxUR7b+moZmE1AWFVDQNoIiEBFFxUHEXaJGQX0TnWhi0DhjYlQwbviEbOKOE9eIOjFGR8e44C4qcYkIssmiIMiO7Es3vXffe94ftxsaaUh0Zt689/ul/ulb59a5/VXVWb5TxSP832lG+B3M/wMwxr9plFpjWlFtZm9n+p8Gwxrll2vuXXDyf
 | 
			
		||||
F5erZw5yde1G+/fBYb3K97UoErf3U/8y/xRrNREaFqVnFDuPmKm/38AjIaflVF32mKWzYCxSp4ZwJIRT1GRefflkNnuFv+LYIiHUsWLWNPelWs8BD3a20/Dkx+q5v/J9N8OhshI09SgMOled6nW5orZ+y5CD9aQv52Py4hY3ckkdJhN/jkwz1NLNeVHrUcNKsnkBziqZ
 | 
			
		||||
gyFdWdqqow9Rit921kym/pUxhbJl/pwvVtPhMNd3xyMbCtrIjwU5lNcZTTaVt7Lqks9pvBk9WJv8zZ0zx9W8potnMXx7vssATQ6fWotsQ8Y9XpoqLUF7X1B9NFhIiK2TfqSOmtHBeFMa+d2+NIrxURUVf6+cTMRZbqJM09ti1yXQK/R2sA02xIRhR1u91pxLyLmfme6z
 | 
			
		||||
AbEcU8VMwKv6aTKFb4qovMTiaguYdfmVdd/Oxh+lG6JEhUhAC71Gaa/bvHzhqvLkkydDW+xf0h8el9bQLln/I63dFL+tJ/Uw/CT+TTAQuhrJi28iAG819wmZkxZh5VRxAeubWQT1m+o72wuqQs+KlaLAqOU+kKNjZhmn9B22KRd/73yREaxiDGkr2hKZwxsU/p4ehWMJ
 | 
			
		||||
n5gtIKI6IIp0xka9Wbe6u3fERGRiEQVnHDCNerzgoNCJWmPPuo7dqyvh8PITTfK24EmWf3ZyWPTO4BRJY982AFM/FvbtU8uDZ1vtGyB1TdFRKTaE+T6eSYREZ2areITEYlF18PWjHP89Lu1c0P+69vvFnR3mbQps9W2xDX7/ec/+sPVV8Fori3Io1fAaB4HhTfpwJS2K
 | 
			
		||||
rAallTiekmrQDQsIXx9qniL6fo7mVPncv9j2WDNUP6Vg2+P+jL6oqKphSj7+PgnZRWpcR+Fxb1QapTS5trLy51W5xFNv9QGxhgA6rfnrXV/1ZieTl0Z2cHCFKUCgUrDmFFlvZOVnRkA/PjZxL7HhvszN72s+QcGAwAE0rweP+/uVS8eeYcfCZgC8PSs3H3Bx9dtQvm+4
 | 
			
		||||
3PGVD7PTPKeHWtsMOgpzHT9JSPDtOE4vM9Xdjqp630XAFCJzLsBGhjBCKRUSR34PKiHplgCrHCo0SC/t+1tc3mmNhX3o6ecGxRiP9T3A3fpsdURACtvqjp9YVBzBWPEMAqV2m/8iEBtdJ+8YZw+nxF9fMy8I3XYItjWFoNNuQQlcIBKoKVACpM6Jc+BD8UxSwBXxm7Jv
 | 
			
		||||
hnWwOfHOBSns1ONcwLiTOyBF3PHfXqwV8SK3OuPCow1Qg9zSVn6rYmj1Olw131c4tPOtUu/1zPHJZzNMMuC9Q3/4xadxeib7pOvTqt1AxKJiORxYw9s3puSG+fzwQEiInK9+5gk2UHGth/+Le1gj3y1VNQslp8JmbRywZaXTMcPgqiFISJqriMiougfuFDvn/wbIqbG5
 | 
			
		||||
zvFBO5RSkQkmnKPiNXQrFi3LCIiWhEYtfzDgYvObBKuyvnSNl+n11JYKu0kHdwtIKKCE1F60mehadxDdVqrTCpWdNBOnvPMmwsNRESSoG84sWWJmZx7Klw3adrGVJWkdn+A04QH+qqSB5HniOL36ct4hL2Jm4sCexjkJaya41DPe1vjZOouMCqpREZWfEY2SDtQeTkUQ
 | 
			
		||||
JlfFQ+AlvtMDVrmJAUAaf61wpHdr7qst4Rcni8+Eu5qLeDzQIys/kUhuh1cEPJOgm37dHA7ZNwdooYcA+G1TlpFRET9y6hJuCrUwRgWfb2dHIVvBZ/htjxPLSGqS1z3I5HiciOntdOzpdiZiDT1RzyXPiOiA2YnGSIimUgpKc1Nunxk+5boDT2Jrvv5r2tnM8ZAYG8PA
 | 
			
		||||
HVzngFArY0pSGnKA4DaS3JBwXYAYKoLH6t4Yxb2t+cnz19kIzZNmP/JV2TJw/WSsMFGtt39J6Nw2FfBAIDGockWVWMA5k604JA/ACxbdlTUA4A5qirLihpYEys7xx1bgSljeiUxaxwMJMo8d87kfqT6YdrAO9vrxY5wImJETgt8FnbPaVSxxL59iojy7wZ48VbmlFKCX
 | 
			
		||||
eitPCKi6r885pRu3GOI1JeKs7aHJ7PPOjP9bB8VEf2wsyF82j9qOiZKLZiww3T8fc67Z3Y/xewIJ2JuBfNXPNeOVAk4l0/0rtos+ODsbeOdX+QSEb3gck72nIgWIqLGZkX73Pp1pX5PNf82EVEOQ0QamZrVTwev8FvOaJX7Lh7a59obN79UfZYT7qKLUcYCLiY39t4QG
 | 
			
		||||
RMxo5fNagBN9yYLAbB3jk6d1Q3igkye0KWbpSXL8GpSHEcBgNdnf+e3/UW+33gAGAIAfPOuam0tKzZ3Xnp1l3Xzwo1Lr8wDAM7f+Fr0MkcIjCOLRxtlCNeWKfaZmANA3b3xoRbVj49/n1nUyLcqTXwGvvPMmxMBYIbDfj3ujo8BYGuj1iNvHr1dLGO6LPx5JubO3krPu
 | 
			
		||||
FB7YwB4/ywAWPuqAQBDkgAA77ksOcgb4XWtf25euazSIWJeXtyq0OujE/Fkd2Smr4cJD/x1k2MAYP+xsrbpmpkBSCjQurVpwB8qVzl4SrustSW5CVXBE3XWPmfnHAD4VlsQaRf9ATB69gW51whfmxLrSZO7jeo26GthReMf5dVVxaeXAIDg8+DPjQB88tcdOizHRgPA5
 | 
			
		||||
pO6PzJ3c1vIii1hwIBzbHYdPHE1rbzy8LjlWnfoFy4iNZetZNdqGEVx9FGtmpyI1cgZNvdUcNDW809FLGlkTc3diUiW65PNjbkZSkQk9lRpde7OICKq3trBx3ikJRD57+ZpKQSbdopnbMx/nmwVFaKFLo07v2SuzNoIAJKXl1Cfpct1k5LTz172AKrr+1NNUna112hPi
 | 
			
		||||
+wnM+wBnEk8wHmEtQIAyrROQHmuFgAgtTREyCNLKxV6K0PESH4Os/WYt2nriWwdXWeJZVLkHeZSM5gy5hARtZSQSq5KTvilQi+D9ZZxvz0NhZqHmg4iYwDyfgunOKh0jqQSl2fEZwXfHKzJevyk+P6ftU7Hxs5NOnD01amkj0DUNgCY6828O9TMT8sHv/cdDgAV5f0AA
 | 
			
		||||
DXtdA6PGwjg+MvRBstbBS/2iE/3xGl9vFytI9w8Smrh6ie04wN4ud9ulW7kjBUBQYExr6hHOQRsuAxgz7mlC/RcN97Wrbd+LcxZe6HQCMCTPz4DgEGXBnZaN92PGhL9J38XCxgNWByXKmpl222canq8RDb3Cx0zl64hIqKpyUG5RERZhqM+2yImlpoecyHWRkJE7Lw9R
 | 
			
		||||
EQVFmwX5W3tvMrC4irRkrj27znKteuBkqaP3P0kKXJjloghVe2DaE8iInKscDaAQbWGLSrhirQz04+c/XASJ7ZuJqIacyIi2vStAb3WOONwGoCm3qL9Tl7MWwsAsR+mDJJY1C+yc796/O0+/RtqG5s8AUDSWBioN1pZVlUnkmt4txx5TjMHxwIwnRsSc+hdrakpTAGcn
 | 
			
		||||
wAAOHm/qyMRUY2bgdexFTsAwHVnGv9cv6vIepTWtLikqJe796plkwD8lCaZNV5nKLn55XKlSsMQBk93gmytRXjPdt8q8JbwoR5w1RNA+bhCXhdgSqctdrG2d3ZoH5JPpu/QlirJ7MICABhy2hNAw5AiCwABf5vwlDvda8jIkUjh3t/JrpuA44ctsWZr2n3ri6yzwPOAG
 | 
			
		||||
gDY1fB1V4W/YtvmfxR22MUSxxRdRakRqImItqxjiZTbNhIRka9SQERElRe2Ra4+XdBet2HtsHP6/aHniGjHAiIi8kvv+nxGYtAfEqJik7Tl7Z+5k5aeKSS9MqqZiGjxiZYeRFR+NmZ9TJIB5cfLF91urQi+8WsiUg9JISJiuxmsDtp2xdJgsgxS3mp+5AEA+HTJFAA4M
 | 
			
		||||
uulhdcJGwA53+9ttkLFo0KR4wwPQ8q+tkl30we/A0AjPb9nT3egrnwEAJS7WrzJCTn/neAbN2orrAAMNK/tCWB6pS6URT4yr2APNYmcQwd2QkKEfZMuSQ4GvHfF4XLGlukAUrwBAEff+7Uzvc5bYpWGiOihTzvpjU9YEo3fuLegS1025eIm89W2X9xvISJatI2IiMb+8
 | 
			
		||||
itner+hRS7W65wJLCJi6kp+XU1MORru7EvVkztO6ln3z4Nh123WLUNDjFUxvXaTcc6nMFcbfP1a9028z9gj2WIWqpqHu9QF/V7/CNxkeFYjA/llf+M3ulV5pdUduNZjoEtZtdLtL65vctPzc0SjmDE3uzL4XwEGaE59Wir0GODyhncVCiWBZ2GCfw2Y3y9MfwfzO5hO2
 | 
			
		||||
v8AIg7mWYx8/rwAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTgtMTEtMDRUMjM6NTA6NDQrMDE6MDBAxMf7AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE4LTExLTA0VDIzOjUwOjQ0KzAxOjAwMZl/RwAAAABJRU5ErkJggolQTkcNChoKAAAADUlIRFIAAAAoAAAAPAEAAAAAP
 | 
			
		||||
MLFTQAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAJiS0dEAAHdihOkAAAAB3RJTUUH4gsEFzIsqSs7CAAAABBJREFUGNNj+A8CDKMkjUkAKsYq5D2hXoMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTgtM
 | 
			
		||||
TEtMDRUMjM6NTA6NDQrMDE6MDBAxMf7AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE4LTExLTA0VDIzOjUwOjQ0KzAxOjAwMZl/RwAAAABJRU5ErkJggg=='''
 | 
			
		||||
 | 
			
		||||
app.bob_cache['sha1+8f35fef110ffc5df08d579a50083ff9308fb6242'] = b64decode(image)
 | 
			
		||||
 | 
			
		||||
FORM = '''
 | 
			
		||||
<x xmlns='jabber:x:data' type='form'>
 | 
			
		||||
  <title>Bot Configuration</title>
 | 
			
		||||
  <instructions>Fill out this form to configure your new bot!</instructions>
 | 
			
		||||
  <field type='hidden'
 | 
			
		||||
         var='FORM_TYPE'>
 | 
			
		||||
    <value>jabber:bot</value>
 | 
			
		||||
  </field>
 | 
			
		||||
  <field type='fixed'><value>Section 1: Bot Info</value></field>
 | 
			
		||||
  <field type='text-single'
 | 
			
		||||
         label='The name of your bot'
 | 
			
		||||
         var='botname'>
 | 
			
		||||
    <required/>
 | 
			
		||||
  </field>
 | 
			
		||||
  <field type='text-multi'
 | 
			
		||||
         label='Helpful description of your bot'
 | 
			
		||||
         var='description'>
 | 
			
		||||
    <required/>
 | 
			
		||||
  </field>
 | 
			
		||||
  <field type='boolean'
 | 
			
		||||
         label='Public bot?'
 | 
			
		||||
         var='public'/>
 | 
			
		||||
  <field type='text-private'
 | 
			
		||||
         label='Password for special access'
 | 
			
		||||
         var='password'>
 | 
			
		||||
    <required/>
 | 
			
		||||
  </field>
 | 
			
		||||
  <field type='fixed'><value>Section 2: Features</value></field>
 | 
			
		||||
  <field type='list-multi'
 | 
			
		||||
         label='What features will the bot support?'
 | 
			
		||||
         var='features'>
 | 
			
		||||
    <option label='Contests'><value>contests</value></option>
 | 
			
		||||
    <option label='News'><value>news</value></option>
 | 
			
		||||
    <option label='Polls'><value>polls</value></option>
 | 
			
		||||
    <option label='Reminders'><value>reminders</value></option>
 | 
			
		||||
    <option label='Search'><value>search</value></option>
 | 
			
		||||
    <option label='Search1'><value>search1</value></option>
 | 
			
		||||
    <option label='Really long long long long long long long long entry'><value>longentry</value></option>
 | 
			
		||||
    <option label='Search3'><value>search3</value></option>
 | 
			
		||||
    <value>news</value>
 | 
			
		||||
    <value>search</value>
 | 
			
		||||
  </field>
 | 
			
		||||
  <field type='fixed'><value>Section 3: Subscriber List</value></field>
 | 
			
		||||
  <field type='list-single'
 | 
			
		||||
         label='Maximum number of subscribers'
 | 
			
		||||
         var='maxsubs'>
 | 
			
		||||
    <value>20</value>
 | 
			
		||||
    <option label='10'><value>10</value></option>
 | 
			
		||||
    <option label='20'><value>20</value></option>
 | 
			
		||||
    <option label='30'><value>30</value></option>
 | 
			
		||||
    <option label='50'><value>50</value></option>
 | 
			
		||||
    <option label='100'><value>100</value></option>
 | 
			
		||||
    <option label='None'><value>none</value></option>
 | 
			
		||||
  </field>
 | 
			
		||||
  <field type='fixed'><value>Section 4: Invitations</value></field>
 | 
			
		||||
  <field type='jid-multi'
 | 
			
		||||
         label='People to invite'
 | 
			
		||||
         var='invitelist'>
 | 
			
		||||
    <desc>Tell all your friends about your new bot!</desc>
 | 
			
		||||
    <required/>
 | 
			
		||||
  </field>
 | 
			
		||||
  <field var='ocr' type='text-single' label='Fill in what you see'>
 | 
			
		||||
    <media xmlns='urn:xmpp:media-element'>
 | 
			
		||||
      <uri type='image/png'>cid:sha1+8f35fef110ffc5df08d579a50083ff9308fb6242@bob.xmpp.org</uri>
 | 
			
		||||
    </media>
 | 
			
		||||
    <required/>
 | 
			
		||||
  </field>
 | 
			
		||||
</x>
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DataFormWindow(Gtk.Window):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        Gtk.Window.__init__(self, title="Data Form Test")
 | 
			
		||||
        self.set_default_size(600, 600)
 | 
			
		||||
        options = {
 | 
			
		||||
            'left-width': 100,
 | 
			
		||||
            'form-width': 435,
 | 
			
		||||
        }
 | 
			
		||||
        self._widget = DataFormWidget(
 | 
			
		||||
            extend_form(node=nbxmpp.Node(node=FORM)), options)
 | 
			
		||||
        self.add(self._widget)
 | 
			
		||||
        self.show()
 | 
			
		||||
 | 
			
		||||
win = DataFormWindow()
 | 
			
		||||
win.connect("destroy", Gtk.main_quit)
 | 
			
		||||
win.show_all()
 | 
			
		||||
Gtk.main()
 | 
			
		||||
							
								
								
									
										50
									
								
								test/gtk/fake_dataform.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								test/gtk/fake_dataform.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
from gi.repository import Gtk
 | 
			
		||||
 | 
			
		||||
from gajim import gui
 | 
			
		||||
gui.init('gtk')
 | 
			
		||||
 | 
			
		||||
from gajim.gui.dataform import FakeDataFormWidget
 | 
			
		||||
from gajim.common.const import CSSPriority
 | 
			
		||||
 | 
			
		||||
from test.gtk import util
 | 
			
		||||
util.load_style('gajim.css', CSSPriority.APPLICATION)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fake_form = {
 | 
			
		||||
    'instructions': 'This is the a long long long long long long test instruction',
 | 
			
		||||
    'username': '',
 | 
			
		||||
    'nick': '',
 | 
			
		||||
    'password': '',
 | 
			
		||||
    'name': '',
 | 
			
		||||
    'first': '',
 | 
			
		||||
    'last': '',
 | 
			
		||||
    'email': '',
 | 
			
		||||
    'address': '',
 | 
			
		||||
    'city': '',
 | 
			
		||||
    'state': '',
 | 
			
		||||
    'zip': '',
 | 
			
		||||
    'phone': '',
 | 
			
		||||
    'url': '',
 | 
			
		||||
    'date': '',
 | 
			
		||||
    'misc': '',
 | 
			
		||||
    'text': '',
 | 
			
		||||
    'key': '',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fake_form2 = {
 | 
			
		||||
    'instructions': 'To register, visit https://jabber.at/account/register/',
 | 
			
		||||
    'redirect-url': 'https://jabber.at/account/register/'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class DataFormWindow(Gtk.Window):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        Gtk.Window.__init__(self, title="Data Form Test")
 | 
			
		||||
        self.set_default_size(600, 600)
 | 
			
		||||
        self._widget = FakeDataFormWidget(fake_form2)
 | 
			
		||||
        self.add(self._widget)
 | 
			
		||||
        self.show()
 | 
			
		||||
 | 
			
		||||
win = DataFormWindow()
 | 
			
		||||
win.connect("destroy", Gtk.main_quit)
 | 
			
		||||
win.show_all()
 | 
			
		||||
Gtk.main()
 | 
			
		||||
							
								
								
									
										120
									
								
								test/gtk/groupchat_info.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								test/gtk/groupchat_info.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,120 @@
 | 
			
		|||
import time
 | 
			
		||||
 | 
			
		||||
import gi
 | 
			
		||||
gi.require_version('Gtk', '3.0')
 | 
			
		||||
from gi.repository import Gtk
 | 
			
		||||
 | 
			
		||||
from nbxmpp.protocol import Iq
 | 
			
		||||
from nbxmpp.modules.discovery import parse_disco_info
 | 
			
		||||
 | 
			
		||||
from gajim.common.const import CSSPriority
 | 
			
		||||
 | 
			
		||||
from gajim import gui
 | 
			
		||||
gui.init('gtk')
 | 
			
		||||
 | 
			
		||||
from test.gtk import util
 | 
			
		||||
from gajim.gui.groupchat_info import GroupChatInfoScrolled
 | 
			
		||||
 | 
			
		||||
util.load_style('gajim.css', CSSPriority.APPLICATION)
 | 
			
		||||
 | 
			
		||||
stanza = Iq(node='''
 | 
			
		||||
<iq xmlns="jabber:client" xml:lang="de-DE" to="user@user.us" from="asd@conference.temptatio.dev" type="result" id="67284933-e526-41f3-8309-9d9475cf9c74">
 | 
			
		||||
<query xmlns="http://jabber.org/protocol/disco#info">
 | 
			
		||||
<identity name="ipsum dolor sit amet, consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt" type="text" category="conference" />
 | 
			
		||||
<feature var="vcard-temp" />
 | 
			
		||||
<feature var="http://jabber.org/protocol/muc" />
 | 
			
		||||
<feature var="http://jabber.org/protocol/disco#info" />
 | 
			
		||||
<feature var="http://jabber.org/protocol/disco#items" />
 | 
			
		||||
<feature var="muc_temporary" />
 | 
			
		||||
<feature var="muc_moderated" />
 | 
			
		||||
<feature var="muc_open" />
 | 
			
		||||
<feature var="muc_hidden" />
 | 
			
		||||
<feature var="muc_nonanonymous" />
 | 
			
		||||
<feature var="muc_passwordprotected" />
 | 
			
		||||
<feature var="urn:xmpp:mam:2" />
 | 
			
		||||
<feature var="muc_public" />
 | 
			
		||||
<feature var="muc_persistent" />
 | 
			
		||||
<feature var="muc_membersonly" />
 | 
			
		||||
<feature var="muc_semianonymous" />
 | 
			
		||||
<feature var="muc_unmoderated" />
 | 
			
		||||
<feature var="muc_unsecured" />
 | 
			
		||||
<x type="result" xmlns="jabber:x:data">
 | 
			
		||||
<field var="FORM_TYPE" type="hidden">
 | 
			
		||||
<value>http://jabber.org/protocol/muc#roominfo</value>
 | 
			
		||||
</field>
 | 
			
		||||
<field var="muc#roominfo_occupants" type="text-single" label="Number of occupants">
 | 
			
		||||
<value>1</value>
 | 
			
		||||
</field>
 | 
			
		||||
<field var="muc#roomconfig_roomname" type="text-single" label="Natural-Language Room Name">
 | 
			
		||||
<value>ipsum dolor sit amet, consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt</value>
 | 
			
		||||
</field>
 | 
			
		||||
<field var="muc#roominfo_description" type="text-single" label="Raum Beschreibung">
 | 
			
		||||
<value>Lorem ipsum dolor sit amet, consetetur sadipscing elitr sed diam nonumy eirmod tempor invidunt ut labore et dolore magna</value>
 | 
			
		||||
</field>
 | 
			
		||||
<field var="muc#roominfo_contactjid" type="jid-multi" label="Contact Addresses (normally, room owner or owners)">
 | 
			
		||||
<value>userA@user.us</value>
 | 
			
		||||
<value>userB@user.us</value>
 | 
			
		||||
</field>
 | 
			
		||||
<field var="muc#roominfo_changesubject" type="boolean" label="Occupants May Change the Subject">
 | 
			
		||||
<value>1</value>
 | 
			
		||||
</field>
 | 
			
		||||
<field var="muc#roomconfig_allowinvites" type="boolean" label="Occupants are allowed to invite others">
 | 
			
		||||
<value>1</value>
 | 
			
		||||
</field>
 | 
			
		||||
<field var="muc#roomconfig_allowpm" type="list-single" label="Roles that May Send Private Messages">
 | 
			
		||||
<value>anyone</value>
 | 
			
		||||
<option label="Anyone">
 | 
			
		||||
<value>anyone</value>
 | 
			
		||||
</option>
 | 
			
		||||
<option label="Anyone with Voice">
 | 
			
		||||
<value>participants</value>
 | 
			
		||||
</option>
 | 
			
		||||
<option label="Moderators Only">
 | 
			
		||||
<value>moderators</value>
 | 
			
		||||
</option>
 | 
			
		||||
<option label="Nobody">
 | 
			
		||||
<value>none</value>
 | 
			
		||||
</option>
 | 
			
		||||
</field>
 | 
			
		||||
<field var="muc#roominfo_lang" type="text-single" label="Natural Language for Room Discussions">
 | 
			
		||||
<value>de</value>
 | 
			
		||||
</field>
 | 
			
		||||
<field type="text-single" var="muc#roominfo_logs">
 | 
			
		||||
<value>https://logs.xmpp.org/xsf/</value>
 | 
			
		||||
</field>
 | 
			
		||||
</x>
 | 
			
		||||
</query>
 | 
			
		||||
</iq>''')
 | 
			
		||||
 | 
			
		||||
disco_info = parse_disco_info(stanza)
 | 
			
		||||
 | 
			
		||||
class GroupchatInfo(Gtk.ApplicationWindow):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        Gtk.ApplicationWindow.__init__(self)
 | 
			
		||||
        self.set_name('GroupchatJoin')
 | 
			
		||||
        self.set_position(Gtk.WindowPosition.CENTER)
 | 
			
		||||
        self.set_show_menubar(False)
 | 
			
		||||
        self.set_title('Test Group chat info')
 | 
			
		||||
 | 
			
		||||
        self._main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL,
 | 
			
		||||
                                 spacing=18)
 | 
			
		||||
        self._main_box.set_valign(Gtk.Align.FILL)
 | 
			
		||||
 | 
			
		||||
        self._muc_info_box = GroupChatInfoScrolled(None)
 | 
			
		||||
        self._muc_info_box.set_vexpand(True)
 | 
			
		||||
 | 
			
		||||
        self._main_box.add(self._muc_info_box)
 | 
			
		||||
 | 
			
		||||
        self.add(self._main_box)
 | 
			
		||||
        self._muc_info_box.set_from_disco_info(disco_info)
 | 
			
		||||
        self._muc_info_box.set_subject(
 | 
			
		||||
            'Lorem ipsum dolor sit amet, consetetur sadipscing elitr sed '
 | 
			
		||||
            'diam nonumy eirmod tempor invidunt ut labore et dolore magna')
 | 
			
		||||
        self._muc_info_box.set_author('userX', None)
 | 
			
		||||
        self.show_all()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
win = GroupchatInfo()
 | 
			
		||||
win.connect('destroy', Gtk.main_quit)
 | 
			
		||||
win.show_all()
 | 
			
		||||
Gtk.main()
 | 
			
		||||
							
								
								
									
										214
									
								
								test/gtk/htmltextview.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								test/gtk/htmltextview.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,214 @@
 | 
			
		|||
from unittest.mock import MagicMock
 | 
			
		||||
 | 
			
		||||
import gi
 | 
			
		||||
gi.require_version('Gtk', '3.0')
 | 
			
		||||
from gi.repository import Gtk
 | 
			
		||||
 | 
			
		||||
from gajim.common import app
 | 
			
		||||
from gajim.common import configpaths
 | 
			
		||||
configpaths.init()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from gajim import gui
 | 
			
		||||
gui.init('gtk')
 | 
			
		||||
 | 
			
		||||
from gajim.common.helpers import AdditionalDataDict
 | 
			
		||||
 | 
			
		||||
from gajim.conversation_textview import ConversationTextview
 | 
			
		||||
from gajim.gui_interface import Interface
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
app.settings = MagicMock()
 | 
			
		||||
app.plugin_manager = MagicMock()
 | 
			
		||||
app.logger = MagicMock()
 | 
			
		||||
app.cert_store = MagicMock()
 | 
			
		||||
app.storage = MagicMock()
 | 
			
		||||
app.interface = Interface()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
XHTML = [
 | 
			
		||||
    '''
 | 
			
		||||
    <div>
 | 
			
		||||
        <span style="color: red; text-decoration:underline">Hello</span>
 | 
			
		||||
        <br/>\n
 | 
			
		||||
        <img src="http://images.slashdot.org/topics/topicsoftware.gif"/>
 | 
			
		||||
        <br/>\n
 | 
			
		||||
        <span style="font-size: 500%; font-family: serif">World</span>\n
 | 
			
		||||
    </div>
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <hr />
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <body xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
        <p xmlns='http://www.w3.org/1999/xhtml'>Look here 
 | 
			
		||||
            <a href='http://google.com/'>Google</a>
 | 
			
		||||
        </p>
 | 
			
		||||
        <br/>
 | 
			
		||||
    </body>
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <hr />
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <body xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
        <p style='font-size:large'>
 | 
			
		||||
            <span style='font-style: italic'>O
 | 
			
		||||
            <span style='font-size:larger'>M</span>G
 | 
			
		||||
            </span>, I'm <span style='color:green'>green</span> with 
 | 
			
		||||
            <span style='font-weight: bold'>envy</span>!
 | 
			
		||||
        </p>
 | 
			
		||||
    </body>
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <hr />
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <body xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
        <p>
 | 
			
		||||
            As Emerson said in his essay 
 | 
			
		||||
            <span style='font-style: italic; background-color:cyan'>
 | 
			
		||||
            Self-Reliance</span>:
 | 
			
		||||
        </p>
 | 
			
		||||
        <p style='margin-left: 5px; margin-right: 2%'>
 | 
			
		||||
            "A foolish consistency is the hobgoblin of little minds."
 | 
			
		||||
        </p>
 | 
			
		||||
    </body>
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <hr />
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <body xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
        <p style='text-align:center'>
 | 
			
		||||
            Hey, are you licensed to <a href='http://www.jabber.org/'>Jabber</a>?
 | 
			
		||||
        </p>
 | 
			
		||||
        <p style='text-align:right'>
 | 
			
		||||
            <img src='http://www.xmpp.org/images/psa-license.jpg'
 | 
			
		||||
                alt='A License to Jabber' width='50%' height='50%'/>
 | 
			
		||||
        </p>
 | 
			
		||||
    </body>
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <hr />
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <body xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
        <ul style='background-color:rgb(120,140,100)'>
 | 
			
		||||
            <li> One </li>
 | 
			
		||||
            <li> Two </li>
 | 
			
		||||
            <li> Three </li>
 | 
			
		||||
        </ul>
 | 
			
		||||
        <hr />
 | 
			
		||||
        <pre style="background-color:rgb(120,120,120)">def fac(n):
 | 
			
		||||
        def faciter(n,acc):
 | 
			
		||||
        if n==0: return acc
 | 
			
		||||
        return faciter(n-1, acc*n)
 | 
			
		||||
        if n<0: raise ValueError('Must be non-negative')
 | 
			
		||||
        return faciter(n,1)</pre>
 | 
			
		||||
    </body>
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <hr />
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <body xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
        <ol style='background-color:rgb(120,140,100)'>
 | 
			
		||||
            <li> One </li>
 | 
			
		||||
            <li>
 | 
			
		||||
                Two is nested: 
 | 
			
		||||
                <ul style='background-color:rgb(200,200,100)'>
 | 
			
		||||
                    <li> One </li>
 | 
			
		||||
                    <li style='font-size:50%'> Two </li>
 | 
			
		||||
                    <li style='font-size:200%'> Three </li>
 | 
			
		||||
                    <li style='font-size:9999pt'> Four </li>
 | 
			
		||||
                </ul>
 | 
			
		||||
            </li>
 | 
			
		||||
            <li> Three </li>
 | 
			
		||||
        </ol>
 | 
			
		||||
    </body>
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <hr />
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <body xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
        <p>
 | 
			
		||||
            <strong>
 | 
			
		||||
            <a href='xmpp:example@example.org'>xmpp link</a>
 | 
			
		||||
            </strong>: 
 | 
			
		||||
        </p>
 | 
			
		||||
        <div xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
            <cite style='margin: 7px;' title='xmpp:examples@example.org'>
 | 
			
		||||
                <p>
 | 
			
		||||
                    <strong>examples@example.org wrote:</strong>
 | 
			
		||||
                </p>
 | 
			
		||||
                <p>this cite - bla bla bla, smile- :-)  …</p>
 | 
			
		||||
            </cite>
 | 
			
		||||
            <div>
 | 
			
		||||
                <p>some text</p>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <p/>
 | 
			
		||||
        <p>#232/1</p>
 | 
			
		||||
    </body>
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <hr />
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
    '''
 | 
			
		||||
    <body xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
        <img src='data:image/png;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAw\
 | 
			
		||||
            AAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFz\
 | 
			
		||||
            ByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSp\
 | 
			
		||||
            a/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJl\
 | 
			
		||||
            ZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uis\
 | 
			
		||||
            F81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PH\
 | 
			
		||||
            hhx4dbgYKAAA7' alt='Larry'/>
 | 
			
		||||
    </body>
 | 
			
		||||
    ''',
 | 
			
		||||
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TextviewWindow(Gtk.Window):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        Gtk.Window.__init__(self, title="Textview Test")
 | 
			
		||||
        self.set_default_size(600, 600)
 | 
			
		||||
 | 
			
		||||
        self._textview = ConversationTextview(None)
 | 
			
		||||
 | 
			
		||||
        scrolled = Gtk.ScrolledWindow()
 | 
			
		||||
        scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
 | 
			
		||||
        scrolled.add(self._textview.tv)
 | 
			
		||||
        self.add(scrolled)
 | 
			
		||||
        self.show()
 | 
			
		||||
        self._print_xhtml()
 | 
			
		||||
 | 
			
		||||
    def _print_xhtml(self):
 | 
			
		||||
        for xhtml in XHTML:
 | 
			
		||||
            additional_data = AdditionalDataDict()
 | 
			
		||||
            additional_data.set_value('gajim', 'xhtml', xhtml)
 | 
			
		||||
            self._textview.print_real_text(None, additional_data=additional_data)
 | 
			
		||||
            self._textview.print_real_text('\n')
 | 
			
		||||
 | 
			
		||||
win = TextviewWindow()
 | 
			
		||||
win.connect("destroy", Gtk.main_quit)
 | 
			
		||||
win.show_all()
 | 
			
		||||
Gtk.main()
 | 
			
		||||
							
								
								
									
										55
									
								
								test/gtk/ssl_error_dialog.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								test/gtk/ssl_error_dialog.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
import gi
 | 
			
		||||
gi.require_version('Gtk', '3.0')
 | 
			
		||||
from gi.repository import Gtk
 | 
			
		||||
 | 
			
		||||
import OpenSSL
 | 
			
		||||
 | 
			
		||||
from gajim import gui
 | 
			
		||||
gui.init('gtk')
 | 
			
		||||
 | 
			
		||||
from test.gtk import util
 | 
			
		||||
from gajim.common.const import CSSPriority
 | 
			
		||||
from gajim.gui.ssl_error_dialog import SSLErrorDialog
 | 
			
		||||
 | 
			
		||||
util.load_style('gajim.css', CSSPriority.APPLICATION)
 | 
			
		||||
 | 
			
		||||
cert = '''
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIFhDCCBGygAwIBAgISA4oUEifTr7Y+mcdiwu6KWpcVMA0GCSqGSIb3DQEBCwUA
 | 
			
		||||
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
 | 
			
		||||
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTA0MDMxODE3NDVaFw0x
 | 
			
		||||
OTA3MDIxODE3NDVaMBsxGTAXBgNVBAMMECoubGlnaHR3aXRjaC5vcmcwggEiMA0G
 | 
			
		||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/3mcevikse7QwDYwPcGAD9zHw3UWE
 | 
			
		||||
7J8SJR349/rFTF2tBFDvEa62OUKTCg5vPKVKaXHlzruk/A7blgqsEdugycORwPD1
 | 
			
		||||
7YNJ27EldrRtotjclurzKL6D/MgcaQ4cTkPOD3cWbf/L+HClGrpFt7su6Z6cTutC
 | 
			
		||||
wiAYAdlfmVgSSv15F1xOTyFyfGJKQnW628Xs8xUvZh5H/SsEEum4MwVVGW06Z/A/
 | 
			
		||||
mwX2jmJUb2M25S1Ma025nZpGYyAAqecTmPb3fStnXm4sdytfZhm4+nj9mH9GQIU1
 | 
			
		||||
t/jO/7X7IFpc9DvVRSumSVqvNaVgiWmTLP4VxlCVJO6mibOXXUUDA5RfAgMBAAGj
 | 
			
		||||
ggKRMIICjTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
 | 
			
		||||
AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFC4/ZRurw2wVFsgJBTb9Fh/3
 | 
			
		||||
0aV9MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUFBwEB
 | 
			
		||||
BGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0
 | 
			
		||||
Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNyeXB0
 | 
			
		||||
Lm9yZy8wSQYDVR0RBEIwQIIQKi5saWdodHdpdGNoLm9yZ4IOKi5tZXRyb25vbWUu
 | 
			
		||||
aW2CDmxpZ2h0d2l0Y2gub3JnggxtZXRyb25vbWUuaW0wTAYDVR0gBEUwQzAIBgZn
 | 
			
		||||
gQwBAgEwNwYLKwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5s
 | 
			
		||||
ZXRzZW5jcnlwdC5vcmcwggECBgorBgEEAdZ5AgQCBIHzBIHwAO4AdQB0ftqDMa0z
 | 
			
		||||
EJEhnM4lT0Jwwr/9XkIgCMY3NXnmEHvMVgAAAWnkosBAAAAEAwBGMEQCICEfmTBk
 | 
			
		||||
OxS95eiYsfTH5HdL7kfp68BSin5LqeGyyxk9AiA3qeDZNKklJTdWqYjto7kUqJNd
 | 
			
		||||
YiL99SrqwzR6w+AqSwB1ACk8UZZUyDlluqpQ/FgH1Ldvv1h6KXLcpMMM9OVFR/R4
 | 
			
		||||
AAABaeSiwEUAAAQDAEYwRAIgFxouOkJeqkQUe6zNI5w/6YBIQFrsrIZdPcX+r6JI
 | 
			
		||||
is8CIEEETzlEyj9lWR/BSSruSp0FT5CuoNNeEG7HxrJ+gVhZMA0GCSqGSIb3DQEB
 | 
			
		||||
CwUAA4IBAQAQtfs1NPNMmBQRcKsZyGLZsvpp2hIhdYi72RYnHnIl4MXbhyNj9xtI
 | 
			
		||||
cJr9PQ+3FsSnxy7LDjZMpbmBuXhawOyPBPw2M0f0Tv6Eo6miwvP/X1kLE3VjTzCo
 | 
			
		||||
6JPh6bEB5wa+kH/pUcGlV6uyT7IuXOiArx0VmIpTA3uwlVdfynOnR3CF20Ds4FLc
 | 
			
		||||
JxbGMqRuw/sGiTLKlXc1xVil8WZjL3hokzrgI7K6np2skUjWuMZvhJgwi5QiE7/C
 | 
			
		||||
ejsJoYkpvcaiaLAyVymTY/n/oM2oQpv5Mqjit+18RB9c2P+ifH5iDKC/jTKn4NNz
 | 
			
		||||
8xSTlUlCBTCozjzscZVeVDIojmejWclT
 | 
			
		||||
-----END CERTIFICATE-----'''
 | 
			
		||||
 | 
			
		||||
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
 | 
			
		||||
ssl_error_num = 10
 | 
			
		||||
win = SSLErrorDialog('testacc', None, cert, ssl_error_num)
 | 
			
		||||
win.connect('destroy', Gtk.main_quit)
 | 
			
		||||
win.show_all()
 | 
			
		||||
Gtk.main()
 | 
			
		||||
							
								
								
									
										23
									
								
								test/gtk/util.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								test/gtk/util.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
from gi.repository import Gdk
 | 
			
		||||
from gi.repository import Gtk
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_gajim_dir():
 | 
			
		||||
    gajim_path = Path(__file__) / '..' / '..' / '..' / 'gajim'
 | 
			
		||||
    return gajim_path.resolve()
 | 
			
		||||
 | 
			
		||||
def load_style(filename, priority):
 | 
			
		||||
    path = get_gajim_dir() / 'data' / 'style' / filename
 | 
			
		||||
    try:
 | 
			
		||||
        with open(str(path), "r") as file:
 | 
			
		||||
            css = file.read()
 | 
			
		||||
    except Exception as exc:
 | 
			
		||||
        print(exc)
 | 
			
		||||
        return
 | 
			
		||||
    provider = Gtk.CssProvider()
 | 
			
		||||
    provider.load_from_data(bytes(css.encode('utf-8')))
 | 
			
		||||
    Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
 | 
			
		||||
                                             provider,
 | 
			
		||||
                                             priority)
 | 
			
		||||
							
								
								
									
										46
									
								
								test/lib/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								test/lib/__init__.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
import os
 | 
			
		||||
 | 
			
		||||
from tempfile import gettempdir
 | 
			
		||||
 | 
			
		||||
# a temporary version of ~/.gajim for testing
 | 
			
		||||
configdir = os.path.join(gettempdir(), 'gajim')
 | 
			
		||||
os.makedirs(configdir, exist_ok=True)
 | 
			
		||||
 | 
			
		||||
# plugins config dir
 | 
			
		||||
pluginsconfigdir = configdir + '/pluginsconfig'
 | 
			
		||||
# theme config directory
 | 
			
		||||
themedir = configdir + '/theme'
 | 
			
		||||
 | 
			
		||||
# define _ for i18n
 | 
			
		||||
import builtins
 | 
			
		||||
builtins._ = lambda x: x
 | 
			
		||||
 | 
			
		||||
from gajim.common.contacts import LegacyContactsAPI
 | 
			
		||||
 | 
			
		||||
def setup_env(use_x=True):
 | 
			
		||||
    # wipe config directory
 | 
			
		||||
    if os.path.isdir(configdir):
 | 
			
		||||
        import shutil
 | 
			
		||||
        shutil.rmtree(configdir)
 | 
			
		||||
 | 
			
		||||
    os.mkdir(configdir)
 | 
			
		||||
    os.mkdir(pluginsconfigdir)
 | 
			
		||||
    os.mkdir(themedir)
 | 
			
		||||
 | 
			
		||||
    from gajim.common import configpaths
 | 
			
		||||
    configpaths.set_config_root(configdir)
 | 
			
		||||
    configpaths.init()
 | 
			
		||||
 | 
			
		||||
    # for some reason gajim.common.app needs to be imported before xmpppy?
 | 
			
		||||
    from gajim.common import app
 | 
			
		||||
 | 
			
		||||
    import logging
 | 
			
		||||
    logging.basicConfig()
 | 
			
		||||
 | 
			
		||||
    app.use_x = use_x
 | 
			
		||||
    app.contacts = LegacyContactsAPI()
 | 
			
		||||
    app.connections = {}
 | 
			
		||||
 | 
			
		||||
    if use_x:
 | 
			
		||||
        from gajim.application import GajimApplication
 | 
			
		||||
        app.app = GajimApplication()
 | 
			
		||||
							
								
								
									
										77
									
								
								test/lib/data.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										77
									
								
								test/lib/data.py
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,77 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
account1 = 'acc1'
 | 
			
		||||
account2 = 'Cool"chârßéµö'
 | 
			
		||||
account3 = 'dingdong.org'
 | 
			
		||||
 | 
			
		||||
contacts = {}
 | 
			
		||||
contacts[account1] = {
 | 
			
		||||
        'myjid@'+account1: {
 | 
			
		||||
                          'ask': None, 'groups': [], 'name': None, 'resources': {},
 | 
			
		||||
                          'subscription': 'both'},
 | 
			
		||||
        'default1@gajim.org': {
 | 
			
		||||
                          'ask': None, 'groups': [], 'name': None, 'resources': {},
 | 
			
		||||
                          'subscription': 'both'},
 | 
			
		||||
        'default2@gajim.org': {
 | 
			
		||||
                          'ask': None, 'groups': ['GroupA',], 'name': None, 'resources': {},
 | 
			
		||||
                          'subscription': 'both'},
 | 
			
		||||
        'Cool"chârßéµö@gajim.org': {
 | 
			
		||||
                          'ask': None, 'groups': ['<Cool"chârßéµö', 'GroupB'],
 | 
			
		||||
                          'name': None, 'resources': {}, 'subscription': 'both'},
 | 
			
		||||
        'samejid@gajim.org': {
 | 
			
		||||
                          'ask': None, 'groups': ['GroupA',], 'name': None, 'resources': {},
 | 
			
		||||
                          'subscription': 'both'}
 | 
			
		||||
}
 | 
			
		||||
contacts[account2] = {
 | 
			
		||||
        'myjid@'+account2: {
 | 
			
		||||
                          'ask': None, 'groups': [], 'name': None, 'resources': {},
 | 
			
		||||
                          'subscription': 'both'},
 | 
			
		||||
        'default3@gajim.org': {
 | 
			
		||||
                          'ask': None, 'groups': ['GroupC',], 'name': None, 'resources': {},
 | 
			
		||||
                          'subscription': 'both'},
 | 
			
		||||
        'asksubfrom@gajim.org': {
 | 
			
		||||
                          'ask': 'subscribe', 'groups': ['GroupA',], 'name': None,
 | 
			
		||||
                          'resources': {}, 'subscription': 'from'},
 | 
			
		||||
        'subto@gajim.org': {
 | 
			
		||||
                          'ask': None, 'groups': ['GroupB'], 'name': None, 'resources': {},
 | 
			
		||||
                          'subscription': 'to'},
 | 
			
		||||
        'samejid@gajim.org': {
 | 
			
		||||
                          'ask': None, 'groups': ['GroupA', 'GroupB'], 'name': None,
 | 
			
		||||
                          'resources': {}, 'subscription': 'both'}
 | 
			
		||||
}
 | 
			
		||||
contacts[account3] = {
 | 
			
		||||
        #'guypsych0\\40h.com@msn.dingdong.org': {
 | 
			
		||||
        #                 'ask': None, 'groups': [], 'name': None, 'resources': {},
 | 
			
		||||
        #                 'subscription': 'both'},
 | 
			
		||||
        'guypsych0%h.com@msn.delx.cjb.net': {
 | 
			
		||||
                          'ask': 'subscribe', 'groups': [], 'name': None,
 | 
			
		||||
                          'resources': {}, 'subscription': 'from'},
 | 
			
		||||
        #'guypsych0%h.com@msn.jabber.wiretrip.org': {
 | 
			
		||||
        #                 'ask': None, 'groups': [], 'name': None, 'resources': {},
 | 
			
		||||
        #                 'subscription': 'to'},
 | 
			
		||||
        #'guypsycho\\40g.com@gtalk.dingdong.org': {
 | 
			
		||||
        #                 'ask': None, 'groups': [], 'name': None,
 | 
			
		||||
        #                 'resources': {}, 'subscription': 'both'}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# We have contacts that are not in roster but only specified in the metadata
 | 
			
		||||
metacontact_data = [
 | 
			
		||||
        [{'account': account3,
 | 
			
		||||
          'jid': 'guypsych0\\40h.com@msn.dingdong.org',
 | 
			
		||||
          'order': 0},
 | 
			
		||||
         {'account': account3,
 | 
			
		||||
          'jid': 'guypsych0%h.com@msn.delx.cjb.net',
 | 
			
		||||
          'order': 0},
 | 
			
		||||
         {'account': account3,
 | 
			
		||||
          'jid': 'guypsych0%h.com@msn.jabber.wiretrip.org',
 | 
			
		||||
          'order': 0},
 | 
			
		||||
         {'account': account3,
 | 
			
		||||
          'jid': 'guypsycho\\40g.com@gtalk.dingdong.org',
 | 
			
		||||
          'order': 0}],
 | 
			
		||||
 | 
			
		||||
        [{'account': account1,
 | 
			
		||||
          'jid': 'samejid@gajim.org',
 | 
			
		||||
          'order': 0},
 | 
			
		||||
         {'account': account2,
 | 
			
		||||
          'jid': 'samejid@gajim.org',
 | 
			
		||||
          'order': 0}]
 | 
			
		||||
        ]
 | 
			
		||||
							
								
								
									
										139
									
								
								test/lib/gajim_mocks.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								test/lib/gajim_mocks.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,139 @@
 | 
			
		|||
'''
 | 
			
		||||
Module with dummy classes for Gajim specific unit testing
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
from .mock import Mock
 | 
			
		||||
from gajim.common import app
 | 
			
		||||
from gajim.common import ged
 | 
			
		||||
 | 
			
		||||
from gajim.common.connection_handlers import ConnectionHandlers
 | 
			
		||||
 | 
			
		||||
class MockConnection(Mock, ConnectionHandlers):
 | 
			
		||||
    def __init__(self, account, *args):
 | 
			
		||||
        Mock.__init__(self, *args)
 | 
			
		||||
 | 
			
		||||
        self.connection = Mock()
 | 
			
		||||
 | 
			
		||||
        self.name = account
 | 
			
		||||
 | 
			
		||||
        ConnectionHandlers.__init__(self)
 | 
			
		||||
 | 
			
		||||
        self.connected = 2
 | 
			
		||||
        self.pep = {}
 | 
			
		||||
        self.sessions = {}
 | 
			
		||||
        self.server_resource = 'Gajim'
 | 
			
		||||
 | 
			
		||||
        app.interface.instances[account] = {'infos': {}, 'disco': {},
 | 
			
		||||
                'gc_config': {}, 'search': {}, 'sub_request': {}}
 | 
			
		||||
        app.interface.minimized_controls[account] = {}
 | 
			
		||||
        app.contacts.add_account(account)
 | 
			
		||||
        app.groups[account] = {}
 | 
			
		||||
        app.gc_connected[account] = {}
 | 
			
		||||
        app.automatic_rooms[account] = {}
 | 
			
		||||
        app.newly_added[account] = []
 | 
			
		||||
        app.to_be_removed[account] = []
 | 
			
		||||
        app.nicks[account] = app.settings.get_account_setting(account, 'name')
 | 
			
		||||
        app.block_signed_in_notifications[account] = True
 | 
			
		||||
        app.last_message_time[account] = {}
 | 
			
		||||
 | 
			
		||||
        app.connections[account] = self
 | 
			
		||||
 | 
			
		||||
class MockWindow(Mock):
 | 
			
		||||
    def __init__(self, *args):
 | 
			
		||||
        Mock.__init__(self, *args)
 | 
			
		||||
        self.window = Mock()
 | 
			
		||||
        self._controls = {}
 | 
			
		||||
 | 
			
		||||
    def get_control(self, jid, account):
 | 
			
		||||
        try:
 | 
			
		||||
            return self._controls[account][jid]
 | 
			
		||||
        except KeyError:
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
    def has_control(self, jid, acct):
 | 
			
		||||
        return self.get_control(jid, acct) is not None
 | 
			
		||||
 | 
			
		||||
    def new_tab(self, ctrl):
 | 
			
		||||
        account = ctrl.account
 | 
			
		||||
        jid = ctrl.jid
 | 
			
		||||
 | 
			
		||||
        if account not in self._controls:
 | 
			
		||||
            self._controls[account] = {}
 | 
			
		||||
 | 
			
		||||
        if jid not in self._controls[account]:
 | 
			
		||||
            self._controls[account][jid] = {}
 | 
			
		||||
 | 
			
		||||
        self._controls[account][jid] = ctrl
 | 
			
		||||
 | 
			
		||||
    def __nonzero__(self):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
class MockChatControl(Mock):
 | 
			
		||||
    def __init__(self, jid, account, *args):
 | 
			
		||||
        Mock.__init__(self, *args)
 | 
			
		||||
 | 
			
		||||
        self.jid = jid
 | 
			
		||||
        self.account = account
 | 
			
		||||
 | 
			
		||||
        self.parent_win = MockWindow({'get_active_control': self})
 | 
			
		||||
        self.session = None
 | 
			
		||||
 | 
			
		||||
    def set_session(self, sess):
 | 
			
		||||
        self.session = sess
 | 
			
		||||
 | 
			
		||||
    def __nonzero__(self):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        return self is other
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MockInterface(Mock):
 | 
			
		||||
    def __init__(self, *args):
 | 
			
		||||
        Mock.__init__(self, *args)
 | 
			
		||||
        app.interface = self
 | 
			
		||||
        self.msg_win_mgr = Mock()
 | 
			
		||||
        self.roster = Mock()
 | 
			
		||||
        app.ged = ged.GlobalEventsDispatcher()
 | 
			
		||||
        from gajim import plugins
 | 
			
		||||
        app.plugin_manager = plugins.PluginManager()
 | 
			
		||||
 | 
			
		||||
        self.instances = {}
 | 
			
		||||
        self.minimized_controls = {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MockLogger(Mock):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        Mock.__init__(self, {'insert_into_logs': None,
 | 
			
		||||
            'get_transports_type': {}})
 | 
			
		||||
        self.cur = Mock()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MockContact(Mock):
 | 
			
		||||
    def __nonzero__(self):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import random
 | 
			
		||||
 | 
			
		||||
class MockSession(Mock):
 | 
			
		||||
    def __init__(self, conn, jid, thread_id, type_):
 | 
			
		||||
        Mock.__init__(self)
 | 
			
		||||
 | 
			
		||||
        self.conn = conn
 | 
			
		||||
        self.jid = jid
 | 
			
		||||
        self.type_ = type_
 | 
			
		||||
        self.thread_id = thread_id
 | 
			
		||||
        self.resource = ''
 | 
			
		||||
 | 
			
		||||
        if not self.thread_id:
 | 
			
		||||
            self.thread_id = '%0x' % random.randint(0, 10000)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return '<MockSession %s>' % self.thread_id
 | 
			
		||||
 | 
			
		||||
    def __nonzero__(self):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        return self is other
 | 
			
		||||
							
								
								
									
										466
									
								
								test/lib/mock.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								test/lib/mock.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,466 @@
 | 
			
		|||
#
 | 
			
		||||
# (c) Dave Kirby 2001 - 2005
 | 
			
		||||
#     mock@thedeveloperscoach.com
 | 
			
		||||
#
 | 
			
		||||
# Original call interceptor and call assertion code by Phil Dawes (pdawes@users.sourceforge.net)
 | 
			
		||||
# Call interceptor code enhanced by Bruce Cropley (cropleyb@yahoo.com.au)
 | 
			
		||||
#
 | 
			
		||||
# This Python  module and associated files are released under the FreeBSD
 | 
			
		||||
# license. Essentially, you can do what you like with it except pretend you wrote
 | 
			
		||||
# it yourself.
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
#     Copyright (c) 2005, Dave Kirby
 | 
			
		||||
#     Copyright (c) 2009, Yann Leboulanger
 | 
			
		||||
#
 | 
			
		||||
#     All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
#     Redistribution and use in source and binary forms, with or without
 | 
			
		||||
#     modification, are permitted provided that the following conditions are met:
 | 
			
		||||
#
 | 
			
		||||
#         * Redistributions of source code must retain the above copyright
 | 
			
		||||
#           notice, this list of conditions and the following disclaimer.
 | 
			
		||||
#
 | 
			
		||||
#         * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
#           notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
#           documentation and/or other materials provided with the distribution.
 | 
			
		||||
#
 | 
			
		||||
#         * Neither the name of this library nor the names of its
 | 
			
		||||
#           contributors may be used to endorse or promote products derived from
 | 
			
		||||
#           this software without specific prior written permission.
 | 
			
		||||
#
 | 
			
		||||
#     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 | 
			
		||||
#     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
#     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
#     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 | 
			
		||||
#     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
#     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
#     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 | 
			
		||||
#     ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
#     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
#     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
#
 | 
			
		||||
#         mock@thedeveloperscoach.com
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Mock object library for Python. Mock objects can be used when unit testing
 | 
			
		||||
to remove a dependency on another production class. They are typically used
 | 
			
		||||
when the dependency would either pull in lots of other classes, or
 | 
			
		||||
significantly slow down the execution of the test.
 | 
			
		||||
They are also used to create exceptional conditions that cannot otherwise
 | 
			
		||||
be easily triggered in the class under test.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
__version__ = "0.1.0"
 | 
			
		||||
 | 
			
		||||
# Added in Python 2.1
 | 
			
		||||
import inspect
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
class MockInterfaceError(Exception):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
class Mock(object):
 | 
			
		||||
    """
 | 
			
		||||
    The Mock class emulates any other class for testing purposes.
 | 
			
		||||
    All method calls are stored for later examination.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, returnValues=None, realClass=None):
 | 
			
		||||
        """
 | 
			
		||||
        The Mock class constructor takes a dictionary of method names and
 | 
			
		||||
        the values they return.  Methods that are not in the returnValues
 | 
			
		||||
        dictionary will return None.
 | 
			
		||||
        You may also supply a class whose interface is being mocked.
 | 
			
		||||
        All calls will be checked to see if they appear in the original
 | 
			
		||||
        interface. Any calls to methods not appearing in the real class
 | 
			
		||||
        will raise a MockInterfaceError.  Any calls that would fail due to
 | 
			
		||||
        non-matching parameter lists will also raise a MockInterfaceError.
 | 
			
		||||
        Both of these help to prevent the Mock class getting out of sync
 | 
			
		||||
        with the class it is Mocking.
 | 
			
		||||
        """
 | 
			
		||||
        self.mockCalledMethods = {}
 | 
			
		||||
        self.mockAllCalledMethods = []
 | 
			
		||||
        self.mockReturnValues = returnValues or {}
 | 
			
		||||
        self.mockExpectations = {}
 | 
			
		||||
        self.realClass = realClass
 | 
			
		||||
        self.realClassMethods = None
 | 
			
		||||
        if realClass:
 | 
			
		||||
            self.realClassMethods = dict(inspect.getmembers(realClass, inspect.isroutine))
 | 
			
		||||
            for retMethod in self.mockReturnValues.keys():
 | 
			
		||||
                if retMethod not in self.realClassMethods:
 | 
			
		||||
                    raise MockInterfaceError("Return value supplied for method '%s' that was not in the original class" % retMethod)
 | 
			
		||||
        self._setupSubclassMethodInterceptors()
 | 
			
		||||
 | 
			
		||||
    def _setupSubclassMethodInterceptors(self):
 | 
			
		||||
        methods = inspect.getmembers(self.realClass, inspect.isroutine)
 | 
			
		||||
        baseMethods = dict(inspect.getmembers(Mock, inspect.ismethod))
 | 
			
		||||
        for m in methods:
 | 
			
		||||
            name = m[0]
 | 
			
		||||
            # Don't record calls to methods of Mock base class.
 | 
			
		||||
            if not name in baseMethods:
 | 
			
		||||
                self.__dict__[name] = MockCallable(name, self, handcrafted=True)
 | 
			
		||||
 | 
			
		||||
    def get_module(self, name):
 | 
			
		||||
        return Mock()
 | 
			
		||||
 | 
			
		||||
    def __getattr__(self, name):
 | 
			
		||||
        return MockCallable(name, self)
 | 
			
		||||
 | 
			
		||||
    def mockAddReturnValues(self, **methodReturnValues ):
 | 
			
		||||
        self.mockReturnValues.update(methodReturnValues)
 | 
			
		||||
 | 
			
		||||
    def mockSetExpectation(self, name, testFn, after=0, until=0):
 | 
			
		||||
        self.mockExpectations.setdefault(name, []).append((testFn, after, until))
 | 
			
		||||
 | 
			
		||||
    def _checkInterfaceCall(self, name, callParams, callKwParams):
 | 
			
		||||
        """
 | 
			
		||||
        Check that a call to a method of the given name to the original
 | 
			
		||||
        class with the given parameters would not fail. If it would fail,
 | 
			
		||||
        raise a MockInterfaceError.
 | 
			
		||||
        Based on the Python 2.3.3 Reference Manual section 5.3.4: Calls.
 | 
			
		||||
        """
 | 
			
		||||
        if self.realClassMethods is None:
 | 
			
		||||
            return
 | 
			
		||||
        if name not in self.realClassMethods:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        func = self.realClassMethods[name]
 | 
			
		||||
        try:
 | 
			
		||||
            args, varargs, varkw, defaults = inspect.getargspec(func)
 | 
			
		||||
        except TypeError:
 | 
			
		||||
            # func is not a Python function. It is probably a builtin,
 | 
			
		||||
            # such as __repr__ or __coerce__. TODO: Checking?
 | 
			
		||||
            # For now assume params are OK.
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        # callParams doesn't include self; args does include self.
 | 
			
		||||
        numPosCallParams = 1 + len(callParams)
 | 
			
		||||
 | 
			
		||||
        if numPosCallParams > len(args) and not varargs:
 | 
			
		||||
            raise MockInterfaceError("Original %s() takes at most %s arguments (%s given)" %
 | 
			
		||||
                (name, len(args), numPosCallParams))
 | 
			
		||||
 | 
			
		||||
        # Get the number of positional arguments that appear in the call,
 | 
			
		||||
        # also check for duplicate parameters and unknown parameters
 | 
			
		||||
        numPosSeen = _getNumPosSeenAndCheck(numPosCallParams, callKwParams, args, varkw)
 | 
			
		||||
 | 
			
		||||
        lenArgsNoDefaults = len(args) - len(defaults or [])
 | 
			
		||||
        if numPosSeen < lenArgsNoDefaults:
 | 
			
		||||
            raise MockInterfaceError("Original %s() takes at least %s arguments (%s given)" % (name, lenArgsNoDefaults, numPosSeen))
 | 
			
		||||
 | 
			
		||||
    def mockGetAllCalls(self):
 | 
			
		||||
        """
 | 
			
		||||
        Return a list of MockCall objects,
 | 
			
		||||
        representing all the methods in the order they were called.
 | 
			
		||||
        """
 | 
			
		||||
        return self.mockAllCalledMethods
 | 
			
		||||
    getAllCalls = mockGetAllCalls  # deprecated - kept for backward compatibility
 | 
			
		||||
 | 
			
		||||
    def mockGetNamedCalls(self, methodName):
 | 
			
		||||
        """
 | 
			
		||||
        Return a list of MockCall objects,
 | 
			
		||||
        representing all the calls to the named method in the order they were called.
 | 
			
		||||
        """
 | 
			
		||||
        return self.mockCalledMethods.get(methodName, [])
 | 
			
		||||
    getNamedCalls = mockGetNamedCalls  # deprecated - kept for backward compatibility
 | 
			
		||||
 | 
			
		||||
    def mockCheckCall(self, index, name, *args, **kwargs):
 | 
			
		||||
        '''test that the index-th call had the specified name and parameters'''
 | 
			
		||||
        call = self.mockAllCalledMethods[index]
 | 
			
		||||
        assert name == call.getName(), "%r != %r" % (name, call.getName())
 | 
			
		||||
        call.checkArgs(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _getNumPosSeenAndCheck(numPosCallParams, callKwParams, args, varkw):
 | 
			
		||||
    """
 | 
			
		||||
    Positional arguments can appear as call parameters either named as
 | 
			
		||||
    a named (keyword) parameter, or just as a value to be matched by
 | 
			
		||||
    position. Count the positional arguments that are given by either
 | 
			
		||||
    keyword or position, and check for duplicate specifications.
 | 
			
		||||
    Also check for arguments specified by keyword that do not appear
 | 
			
		||||
    in the method's parameter list.
 | 
			
		||||
    """
 | 
			
		||||
    posSeen = {}
 | 
			
		||||
    for arg in args[:numPosCallParams]:
 | 
			
		||||
        posSeen[arg] = True
 | 
			
		||||
    for kwp in callKwParams:
 | 
			
		||||
        if kwp in posSeen:
 | 
			
		||||
            raise MockInterfaceError("%s appears as both a positional and named parameter." % kwp)
 | 
			
		||||
        if kwp in args:
 | 
			
		||||
            posSeen[kwp] = True
 | 
			
		||||
        elif not varkw:
 | 
			
		||||
            raise MockInterfaceError("Original method does not have a parameter '%s'" % kwp)
 | 
			
		||||
    return len(posSeen)
 | 
			
		||||
 | 
			
		||||
class MockCall:
 | 
			
		||||
    """
 | 
			
		||||
    MockCall records the name and parameters of a call to an instance
 | 
			
		||||
    of a Mock class. Instances of MockCall are created by the Mock class,
 | 
			
		||||
    but can be inspected later as part of the test.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, name, params, kwparams ):
 | 
			
		||||
        self.name = name
 | 
			
		||||
        self.params = params
 | 
			
		||||
        self.kwparams = kwparams
 | 
			
		||||
 | 
			
		||||
    def checkArgs(self, *args, **kwargs):
 | 
			
		||||
        assert args == self.params, "%r != %r" % (args, self.params)
 | 
			
		||||
        assert kwargs == self.kwparams, "%r != %r" % (kwargs, self.kwparams)
 | 
			
		||||
 | 
			
		||||
    def getParam( self, n ):
 | 
			
		||||
        if isinstance(n, int):
 | 
			
		||||
            return self.params[n]
 | 
			
		||||
        elif isinstance(n, str):
 | 
			
		||||
            return self.kwparams[n]
 | 
			
		||||
        else:
 | 
			
		||||
            raise IndexError('illegal index type for getParam')
 | 
			
		||||
 | 
			
		||||
    def getNumParams(self):
 | 
			
		||||
        return len(self.params)
 | 
			
		||||
 | 
			
		||||
    def getNumKwParams(self):
 | 
			
		||||
        return len(self.kwparams)
 | 
			
		||||
 | 
			
		||||
    def getName(self):
 | 
			
		||||
        return self.name
 | 
			
		||||
 | 
			
		||||
    #pretty-print the method call
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        s = self.name + "("
 | 
			
		||||
        sep = ''
 | 
			
		||||
        for p in self.params:
 | 
			
		||||
            s = s + sep + repr(p)
 | 
			
		||||
            sep = ', '
 | 
			
		||||
        items = sorted(self.kwparams.items())
 | 
			
		||||
        for k, v in items:
 | 
			
		||||
            s = s + sep + k + '=' + repr(v)
 | 
			
		||||
            sep = ', '
 | 
			
		||||
        s = s + ')'
 | 
			
		||||
        return s
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return self.__str__()
 | 
			
		||||
 | 
			
		||||
class MockCallable:
 | 
			
		||||
    """
 | 
			
		||||
    Intercepts the call and records it, then delegates to either the mock's
 | 
			
		||||
    dictionary of mock return values that was passed in to the constructor,
 | 
			
		||||
    or a handcrafted method of a Mock subclass.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, name, mock, handcrafted=False):
 | 
			
		||||
        self.name = name
 | 
			
		||||
        self.mock = mock
 | 
			
		||||
        self.handcrafted = handcrafted
 | 
			
		||||
 | 
			
		||||
    def __call__(self,  *params, **kwparams):
 | 
			
		||||
        self.mock._checkInterfaceCall(self.name, params, kwparams)
 | 
			
		||||
        thisCall = self.recordCall(params, kwparams)
 | 
			
		||||
        self.checkExpectations(thisCall, params, kwparams)
 | 
			
		||||
        return self.makeCall(params, kwparams)
 | 
			
		||||
 | 
			
		||||
    def recordCall(self, params, kwparams):
 | 
			
		||||
        """
 | 
			
		||||
        Record the MockCall in an ordered list of all calls, and an ordered
 | 
			
		||||
        list of calls for that method name.
 | 
			
		||||
        """
 | 
			
		||||
        thisCall = MockCall(self.name, params, kwparams)
 | 
			
		||||
        calls = self.mock.mockCalledMethods.setdefault(self.name, [])
 | 
			
		||||
        calls.append(thisCall)
 | 
			
		||||
        self.mock.mockAllCalledMethods.append(thisCall)
 | 
			
		||||
        return thisCall
 | 
			
		||||
 | 
			
		||||
    def makeCall(self, params, kwparams):
 | 
			
		||||
        if self.handcrafted:
 | 
			
		||||
            allPosParams = (self.mock,) + params
 | 
			
		||||
            func = _findFunc(self.mock.realClass, self.name)
 | 
			
		||||
            if not func:
 | 
			
		||||
                raise NotImplementedError
 | 
			
		||||
            return func(*allPosParams, **kwparams)
 | 
			
		||||
        else:
 | 
			
		||||
            returnVal = self.mock.mockReturnValues.get(self.name)
 | 
			
		||||
            if isinstance(returnVal, ReturnValuesBase):
 | 
			
		||||
                returnVal = returnVal.next()
 | 
			
		||||
            return returnVal
 | 
			
		||||
 | 
			
		||||
    def checkExpectations(self, thisCall, params, kwparams):
 | 
			
		||||
        if self.name in self.mock.mockExpectations:
 | 
			
		||||
            callsMade = len(self.mock.mockCalledMethods[self.name])
 | 
			
		||||
            for (expectation, after, until) in self.mock.mockExpectations[self.name]:
 | 
			
		||||
                if callsMade > after and (until==0 or callsMade < until):
 | 
			
		||||
                    assert expectation(self.mock, thisCall, len(self.mock.mockAllCalledMethods)-1), 'Expectation failed: '+str(thisCall)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _findFunc(cl, name):
 | 
			
		||||
    """ Depth first search for a method with a given name. """
 | 
			
		||||
    if name in cl.__dict__:
 | 
			
		||||
        return cl.__dict__[name]
 | 
			
		||||
    for base in cl.__bases__:
 | 
			
		||||
        func = _findFunc(base, name)
 | 
			
		||||
        if func:
 | 
			
		||||
            return func
 | 
			
		||||
    return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ReturnValuesBase:
 | 
			
		||||
    def next(self):
 | 
			
		||||
        try:
 | 
			
		||||
            return self.iter.next()
 | 
			
		||||
        except StopIteration:
 | 
			
		||||
            raise AssertionError("No more return values")
 | 
			
		||||
    def __iter__(self):
 | 
			
		||||
        return self
 | 
			
		||||
 | 
			
		||||
class ReturnValues(ReturnValuesBase):
 | 
			
		||||
    def __init__(self, *values):
 | 
			
		||||
        self.iter = iter(values)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ReturnIterator(ReturnValuesBase):
 | 
			
		||||
    def __init__(self, iterator):
 | 
			
		||||
        self.iter = iter(iterator)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def expectParams(*params, **keywords):
 | 
			
		||||
    '''check that the callObj is called with specified params and keywords
 | 
			
		||||
    '''
 | 
			
		||||
    def fn(mockObj, callObj, idx):
 | 
			
		||||
        return callObj.params == params and callObj.kwparams == keywords
 | 
			
		||||
    return fn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def expectAfter(*methods):
 | 
			
		||||
    '''check that the function is only called after all the functions in 'methods'
 | 
			
		||||
    '''
 | 
			
		||||
    def fn(mockObj, callObj, idx):
 | 
			
		||||
        calledMethods = [method.getName() for method in mockObj.mockGetAllCalls()]
 | 
			
		||||
        #skip last entry, since that is the current call
 | 
			
		||||
        calledMethods = calledMethods[:-1]
 | 
			
		||||
        for method in methods:
 | 
			
		||||
            if method not in calledMethods:
 | 
			
		||||
                return False
 | 
			
		||||
        return True
 | 
			
		||||
    return fn
 | 
			
		||||
 | 
			
		||||
def expectException(exception, *args, **kwargs):
 | 
			
		||||
    ''' raise an exception when the method is called
 | 
			
		||||
    '''
 | 
			
		||||
    def fn(mockObj, callObj, idx):
 | 
			
		||||
        raise exception(*args, **kwargs)
 | 
			
		||||
    return fn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def expectParam(paramIdx, cond):
 | 
			
		||||
    '''check that the callObj is called with parameter specified by paramIdx (a position index or keyword)
 | 
			
		||||
    fulfills the condition specified by cond.
 | 
			
		||||
    cond is a function that takes a single argument, the value to test.
 | 
			
		||||
    '''
 | 
			
		||||
    def fn(mockObj, callObj, idx):
 | 
			
		||||
        param = callObj.getParam(paramIdx)
 | 
			
		||||
        return cond(param)
 | 
			
		||||
    return fn
 | 
			
		||||
 | 
			
		||||
def EQ(value):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return param == value
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def NE(value):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return param != value
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def GT(value):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return param > value
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def LT(value):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return param < value
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def GE(value):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return param >= value
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def LE(value):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return param <= value
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def AND(*condlist):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        for cond in condlist:
 | 
			
		||||
            if not cond(param):
 | 
			
		||||
                return False
 | 
			
		||||
        return True
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def OR(*condlist):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        for cond in condlist:
 | 
			
		||||
            if cond(param):
 | 
			
		||||
                return True
 | 
			
		||||
        return False
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def NOT(cond):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return not cond(param)
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def MATCHES(regex, *args, **kwargs):
 | 
			
		||||
    compiled_regex = re.compile(regex, *args, **kwargs)
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return compiled_regex.match(param) is not None
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def SEQ(*sequence):
 | 
			
		||||
    iterator = iter(sequence)
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        try:
 | 
			
		||||
            cond = iterator.next()
 | 
			
		||||
        except StopIteration:
 | 
			
		||||
            raise AssertionError('SEQ exhausted')
 | 
			
		||||
        return cond(param)
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def IS(instance):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return param is instance
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def ISINSTANCE(class_):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return isinstance(param, class_)
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def ISSUBCLASS(class_):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return issubclass(param, class_)
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def CONTAINS(val):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return val in param
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def IN(container):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return param in container
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def HASATTR(attr):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return hasattr(param, attr)
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
def HASMETHOD(method):
 | 
			
		||||
    def testFn(param):
 | 
			
		||||
        return hasattr(param, method) and callable(getattr(param, method))
 | 
			
		||||
    return testFn
 | 
			
		||||
 | 
			
		||||
CALLABLE = callable
 | 
			
		||||
							
								
								
									
										28
									
								
								test/lib/notify.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								test/lib/notify.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
# mock notify module
 | 
			
		||||
 | 
			
		||||
from gajim.common import app
 | 
			
		||||
from gajim.common import ged
 | 
			
		||||
 | 
			
		||||
notifications = []
 | 
			
		||||
 | 
			
		||||
class Notification:
 | 
			
		||||
    def _nec_notification(self, obj):
 | 
			
		||||
        global notifications
 | 
			
		||||
        notifications.append(obj)
 | 
			
		||||
 | 
			
		||||
    def clean(self):
 | 
			
		||||
        global notifications
 | 
			
		||||
        notifications = []
 | 
			
		||||
        app.ged.remove_event_handler('notification', ged.GUI2,
 | 
			
		||||
            self._nec_notification)
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        app.ged.register_event_handler('notification', ged.GUI2,
 | 
			
		||||
            self._nec_notification)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def notify(event, jid, account, parameters, advanced_notif_num = None):
 | 
			
		||||
    notifications.append((event, jid, account, parameters, advanced_notif_num))
 | 
			
		||||
 | 
			
		||||
def get_advanced_notification(event, account, contact):
 | 
			
		||||
    return None
 | 
			
		||||
							
								
								
									
										0
									
								
								test/no_gui/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								test/no_gui/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										36
									
								
								test/no_gui/test_regex.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								test/no_gui/test_regex.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
import unittest
 | 
			
		||||
 | 
			
		||||
from gajim import gui
 | 
			
		||||
gui.init('gtk')
 | 
			
		||||
import gajim.common.regex as regex
 | 
			
		||||
 | 
			
		||||
class Test(unittest.TestCase):
 | 
			
		||||
    def test_links_regexp_entire(self):
 | 
			
		||||
        def assert_matches_all(str_):
 | 
			
		||||
            m = regex.BASIC_REGEX.match(str_)
 | 
			
		||||
 | 
			
		||||
            # the match should equal the string
 | 
			
		||||
            str_span = (0, len(str_))
 | 
			
		||||
            self.assertEqual(m.span(), str_span)
 | 
			
		||||
 | 
			
		||||
        # these entire strings should be parsed as links
 | 
			
		||||
        assert_matches_all('http://google.com/')
 | 
			
		||||
        assert_matches_all('http://google.com')
 | 
			
		||||
        assert_matches_all('http://www.google.ca/search?q=xmpp')
 | 
			
		||||
 | 
			
		||||
        assert_matches_all('http://tools.ietf.org/html/draft-saintandre-rfc3920bis-05#section-12.3')
 | 
			
		||||
 | 
			
		||||
        assert_matches_all('http://en.wikipedia.org/wiki/Protocol_(computing)')
 | 
			
		||||
        assert_matches_all(
 | 
			
		||||
                'http://en.wikipedia.org/wiki/Protocol_%28computing%29')
 | 
			
		||||
 | 
			
		||||
        assert_matches_all('mailto:test@example.org')
 | 
			
		||||
 | 
			
		||||
        assert_matches_all('xmpp:example-node@example.com')
 | 
			
		||||
        assert_matches_all('xmpp:example-node@example.com/some-resource')
 | 
			
		||||
        assert_matches_all('xmpp:example-node@example.com?message')
 | 
			
		||||
        assert_matches_all('xmpp://guest@example.com/support@example.com?message')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    unittest.main()
 | 
			
		||||
							
								
								
									
										5
									
								
								test/no_gui/unit/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								test/no_gui/unit/__init__.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
'''
 | 
			
		||||
 | 
			
		||||
This package just contains plain unit tests
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
							
								
								
									
										50
									
								
								test/no_gui/unit/test_nick_completion.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								test/no_gui/unit/test_nick_completion.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
import unittest
 | 
			
		||||
 | 
			
		||||
from gajim import gui
 | 
			
		||||
gui.init('gtk')
 | 
			
		||||
from gajim.gui.util import NickCompletionGenerator
 | 
			
		||||
 | 
			
		||||
class Test(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_generate_suggestions(self):
 | 
			
		||||
        gen = NickCompletionGenerator('meeeee')
 | 
			
		||||
 | 
			
		||||
        l = ['aaaa', 'meeeee', 'fooo', 'xxxxz', 'xaaaz']
 | 
			
		||||
        for n in l:
 | 
			
		||||
            gen.record_message(n, False)
 | 
			
		||||
        l2 = ['xxx'] + l
 | 
			
		||||
        r = gen.generate_suggestions(nicks=l2, beginning='x')
 | 
			
		||||
        self.assertEqual(r, ['xaaaz', 'xxxxz', 'xxx'])
 | 
			
		||||
 | 
			
		||||
        r = gen.generate_suggestions(
 | 
			
		||||
            nicks=l2,
 | 
			
		||||
            beginning='m'
 | 
			
		||||
            )
 | 
			
		||||
        self.assertEqual(r, [])
 | 
			
		||||
 | 
			
		||||
        for n in ['xaaaz', 'xxxxz']:
 | 
			
		||||
            gen.record_message(n, True)
 | 
			
		||||
 | 
			
		||||
        r = gen.generate_suggestions(
 | 
			
		||||
            nicks=l2,
 | 
			
		||||
            beginning='x'
 | 
			
		||||
            )
 | 
			
		||||
        self.assertEqual(r, ['xxxxz', 'xaaaz', 'xxx'])
 | 
			
		||||
        r = gen.generate_suggestions(
 | 
			
		||||
            nicks=l2,
 | 
			
		||||
            beginning=''
 | 
			
		||||
            )
 | 
			
		||||
        self.assertEqual(r, ['xxxxz', 'xaaaz', 'aaaa', 'fooo', 'xxx'])
 | 
			
		||||
 | 
			
		||||
        l2[1] = 'bbbb'
 | 
			
		||||
        gen.contact_renamed('aaaa', 'bbbb')
 | 
			
		||||
        r = gen.generate_suggestions(
 | 
			
		||||
            nicks=l2,
 | 
			
		||||
            beginning=''
 | 
			
		||||
            )
 | 
			
		||||
        self.assertEqual(r, ['xxxxz', 'xaaaz', 'bbbb', 'fooo', 'xxx'])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    unittest.main()
 | 
			
		||||
							
								
								
									
										5
									
								
								test/unit/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								test/unit/__init__.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
'''
 | 
			
		||||
 | 
			
		||||
This package just contains plain unit tests
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
							
								
								
									
										32
									
								
								test/unit/test_gui_interface.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								test/unit/test_gui_interface.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
'''
 | 
			
		||||
Some diverse tests covering functionality in the GUI Interface class.
 | 
			
		||||
'''
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
import gajim.gui
 | 
			
		||||
gajim.gui.init('gtk')
 | 
			
		||||
 | 
			
		||||
from test import lib
 | 
			
		||||
lib.setup_env()
 | 
			
		||||
 | 
			
		||||
from gajim.common import logging_helpers
 | 
			
		||||
logging_helpers.set_quiet()
 | 
			
		||||
 | 
			
		||||
from gajim.common import app
 | 
			
		||||
 | 
			
		||||
from gajim.gui_interface import Interface
 | 
			
		||||
 | 
			
		||||
from gi.repository import GLib
 | 
			
		||||
 | 
			
		||||
class TestInterface(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def test_instantiation(self):
 | 
			
		||||
        ''' Test that we can proper initialize and do not fail on globals '''
 | 
			
		||||
        def close_app():
 | 
			
		||||
            app.app.quit()
 | 
			
		||||
        GLib.idle_add(close_app)
 | 
			
		||||
        app.app.run()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    unittest.main()
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue