~ubuntu-branches/ubuntu/oneiric/ubuntuone-control-panel/oneiric

« back to all changes in this revision

Viewing changes to ubuntuone/controlpanel/gui/qt/tests/__init__.py

* New upstream release:
  [ Alejandro J. Cura <alecu@canonical.com>]
    - Do not throw a webclient error when closing
      (LP: #845105).
  [ Natalia B. Bidart <natalia.bidart@canonical.com> ]
    - Removed all code related to Bookmarks (LP: #850142).
    - Replaces references to "Evolution" by "Thunderbird" (LP: #849494).
  [ Rodney Dawes <rodney.dawes@canonical.com> ]
    - Don't install a .desktop file for control panel
      (part of LP: #838778).
    - Point the indicator/Unity API at the installer .desktop file
      (part of LP: #838778).
    - Set the WMCLASS so Unity will fall back properly
      (part of LP: #838778).
    - Fix a few grammar mistakes (LP: #835093).
    - Don't show the "Get NGB free!" label on "Join now" button at all
      (LP: #819955).
* debian/control:
  - ubuntuone-control-panel-gtk depends now on ubuntuone-installer >= 2.0.0.
  - require ubuntuone-client >= 2.0.0.
  - require ubuntu-sso-client >= 1.4.0.
  - no longer install a .desktop file (will be installed by ubuntuone-installer).

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
"""The test suite for the Qt UI for the control panel for Ubuntu One."""
20
20
 
 
21
import logging
21
22
import os
22
 
 
23
 
from PyQt4 import QtCore
24
 
 
25
 
from ubuntuone.controlpanel import backend
26
 
from ubuntuone.controlpanel.tests import TestCase, EXPECTED_ACCOUNT_INFO
 
23
import urllib
 
24
 
 
25
from PyQt4 import QtGui, QtCore
 
26
from ubuntuone.devtools.handlers import MementoHandler
 
27
 
 
28
from ubuntuone.controlpanel import backend, cache
 
29
from ubuntuone.controlpanel.tests import TestCase, EXPECTED_ACCOUNT_INFO, TOKEN
 
30
from ubuntuone.controlpanel.gui import qt, UBUNTUONE_FROM_OAUTH
27
31
from ubuntuone.controlpanel.gui.tests import FakedObject, USER_HOME
28
32
 
29
33
# Attribute 'yyy' defined outside __init__, access to a protected member
76
80
    return folder
77
81
 
78
82
 
79
 
def skip_if_abstract_class(test):
80
 
    """Decorator to skip a test if is an abstract class."""
81
 
 
82
 
    def inner(instance):
83
 
        """Skip a test if is an abstract class."""
84
 
        abstract = instance.class_ui is None
85
 
        result = None
86
 
        if not abstract:
87
 
            result = test(instance)
88
 
 
89
 
        return result
90
 
 
91
 
    return inner
92
 
 
93
 
 
94
83
class FakeUi(FakedObject):
95
84
    """A fake Ui object."""
96
85
 
114
103
        backend.UPLOAD_KEY: -1,  # no limit
115
104
    }
116
105
 
117
 
    next_result = object()
 
106
    next_result = []
118
107
    exposed_methods = [
119
108
        'account_info',  # account
120
109
        'devices_info', 'device_names_info',  # devices
128
117
        'file_sync_settings_info',
129
118
        'change_file_sync_settings',
130
119
        'restore_file_sync_settings',
131
 
        'shutdown',
 
120
        'shutdown', 'login',
132
121
    ]
133
122
 
134
 
 
135
 
class FakedConfirmDialog(object):
 
123
    def get_credentials(self):
 
124
        """Fake credentials retrieval."""
 
125
        self._called['get_credentials'] = ((), {})
 
126
        return TOKEN
 
127
 
 
128
 
 
129
class CrashyBackendException(Exception):
 
130
    """A faked backend crash."""
 
131
 
 
132
 
 
133
class CrashyBackend(FakedControlPanelBackend):
 
134
    """A faked backend that crashes."""
 
135
 
 
136
    def __init__(self, *args, **kwargs):
 
137
        super(CrashyBackend, self).__init__(*args, **kwargs)
 
138
        for i in self.exposed_methods + ['get_credentials']:
 
139
            setattr(self, i, self._fail(i))
 
140
 
 
141
    def _fail(self, f):
 
142
        """Crash boom bang."""
 
143
 
 
144
        def inner(*args, **kwargs):
 
145
            """Raise a custom exception."""
 
146
            raise CrashyBackendException(f)
 
147
 
 
148
        return inner
 
149
 
 
150
 
 
151
class FakedDialog(object):
136
152
    """Fake a confirmation dialog."""
137
153
 
 
154
    Close = 0
138
155
    response = args = kwargs = None
139
156
 
140
157
    @classmethod
149
166
    """Fake a file chooser dialog."""
150
167
 
151
168
    response = args = kwargs = None
 
169
    DontUseNativeDialog = 4
152
170
 
153
171
    # Invalid name "getExistingDirectory"
154
172
    # pylint: disable=C0103
168
186
    innerclass_name = None
169
187
    class_ui = None
170
188
    kwargs = {}
 
189
    logger = None
171
190
 
172
 
    @skip_if_abstract_class
173
191
    def setUp(self):
 
192
        cache.Cache._shared_objects = {}
174
193
        super(BaseTestCase, self).setUp()
175
194
        self.patch(backend, 'ControlBackend', FakedControlPanelBackend)
176
 
        # self.class_ui is not callable
177
 
        # pylint: disable=E1102
178
 
        self.ui = self.class_ui(**self.kwargs)
179
 
        self.addCleanup(self.ui.destroy)
180
 
 
181
 
        if hasattr(self.ui, 'backend'):
182
 
            # clean backend calls
183
 
            self.ui.backend._called.clear()
 
195
 
 
196
        self.ui = None
 
197
        if self.class_ui is not None:
 
198
            # self.class_ui is not callable
 
199
            # pylint: disable=E1102
 
200
            self.ui = self.class_ui(**self.kwargs)
 
201
            # pylint: enable=E1102
 
202
            self.addCleanup(self.ui.destroy)
 
203
 
 
204
        if getattr(self.ui, 'backend', None) is not None:
 
205
            self.addCleanup(self.ui.backend._called.clear)
 
206
 
 
207
        logger = self.logger if self.logger is not None else \
 
208
                 getattr(self.ui, 'logger', None)
 
209
        self.memento = None
 
210
        if logger is not None:
 
211
            self.memento = MementoHandler()
 
212
            self.memento.setLevel(logging.DEBUG)
 
213
            logger.addHandler(self.memento)
 
214
            self.addCleanup(logger.removeHandler, self.memento)
 
215
 
 
216
        # default response if user does nothing
 
217
        FakedFileDialog.response = QtCore.QString('')
 
218
        FakedFileDialog.args = None
 
219
        FakedFileDialog.kwargs = None
 
220
        self.patch(QtGui, 'QFileDialog', FakedFileDialog)
 
221
 
 
222
        FakedDialog.response = None
 
223
        FakedDialog.args = None
 
224
        FakedDialog.kwargs = None
 
225
        self.patch(QtGui, 'QMessageBox', FakedDialog)
184
226
 
185
227
    def get_pixmap_data(self, pixmap):
186
228
        """Get the raw data of a QPixmap."""
202
244
        self.assertIn(method_name, self.ui.backend._called)
203
245
        self.assertEqual(self.ui.backend._called[method_name], (args, kwargs))
204
246
 
 
247
    def assert_uri_hook_called(self, button, url):
 
248
        """Check that uri_hook was called with 'url' when clicking 'button'."""
 
249
        self.patch(qt, 'uri_hook', self._set_called)
 
250
        button.click()
 
251
 
 
252
        self.assertEqual(len(self._called), 2, 'uri_hook must be called.')
 
253
        self.assertEqual(len(self._called[0]), 1, 'uri_hook must be called.')
 
254
        actual_url = self._called[0][0]
 
255
        if actual_url.startswith(UBUNTUONE_FROM_OAUTH):
 
256
            self.assertIn(urllib.urlencode({'next': url}), actual_url)
 
257
        else:
 
258
            self.assertEqual(actual_url, url)
 
259
 
205
260
    def test_init_loads_ui(self, expected_setup_ui=None):
206
261
        """The __init__ method loads the ui."""
207
262
        if self.innerclass_ui is None:
219
274
            expected_setup_ui = expected_setup_ui(self.ui)
220
275
        self.assertEqual(self.ui.ui._called,
221
276
                         {'setupUi': ((expected_setup_ui,), {})})
 
277
 
 
278
    def test_backend_is_correct(self):
 
279
        """The backend instance is correct."""
 
280
        if getattr(self.ui, 'backend', None) is not None:
 
281
            self.assertIsInstance(self.ui.backend, FakedControlPanelBackend)