1
# -*- coding: utf-8 -*-
3
# Authors: Alejandro J. Cura <alecu@canonical.com>
5
# Copyright 2011 Canonical Ltd.
7
# This program is free software: you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License version 3, as published
9
# by the Free Software Foundation.
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranties of
13
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14
# PURPOSE. See the GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License along
17
# with this program. If not, see <http://www.gnu.org/licenses/>.
19
"""The test suite for the Qt UI for the control panel for Ubuntu One."""
23
from PyQt4 import QtCore
25
from ubuntuone.controlpanel import backend
26
from ubuntuone.controlpanel.tests import TestCase, EXPECTED_ACCOUNT_INFO
27
from ubuntuone.controlpanel.gui.tests import FakedObject, USER_HOME
29
# Attribute 'yyy' defined outside __init__, access to a protected member
30
# pylint: disable=W0201, W0212
33
SAMPLE_ACCOUNT_INFO = EXPECTED_ACCOUNT_INFO
34
SAMPLE_NAME = EXPECTED_ACCOUNT_INFO["name"]
35
SAMPLE_EMAIL = EXPECTED_ACCOUNT_INFO["email"]
36
SAMPLE_PLAN = EXPECTED_ACCOUNT_INFO["type"]
38
SAMPLE_COMPUTER_INFO = {
42
"configurable": False,
43
"device_id": '1258-6854',
50
"configurable": False,
51
"device_id": '987456-2321',
54
SAMPLE_DEVICES_INFO = [
57
"name": "toshiba laptop",
59
"configurable": False,
65
NO_OP = lambda *args: None
68
def set_path_on_file_dialog(folder_name=None, file_dialog=None):
69
"""Set a valid path in the file dialog to create a folder."""
70
if folder_name is None:
71
folder_name = 'Documents'
72
folder = os.path.join(USER_HOME, folder_name)
73
if file_dialog is None:
74
file_dialog = FakedFileDialog
75
file_dialog.response = QtCore.QString(folder)
79
def skip_if_abstract_class(test):
80
"""Decorator to skip a test if is an abstract class."""
83
"""Skip a test if is an abstract class."""
84
abstract = instance.class_ui is None
87
result = test(instance)
94
class FakeUi(FakedObject):
95
"""A fake Ui object."""
97
exposed_methods = ['setupUi']
100
class FakedControlPanelBackend(FakedObject):
101
"""Fake a Control Panel Backend."""
105
SHARE_TYPE = u'SHARE'
106
NAME_NOT_SET = u'ENAMENOTSET'
107
FREE_BYTES_NOT_AVAILABLE = u'EFREEBYTESNOTAVAILABLE'
108
DEFAULT_FILE_SYNC_SETTINGS = {
109
backend.AUTOCONNECT_KEY: True,
110
backend.SHOW_ALL_NOTIFICATIONS_KEY: True,
111
backend.SHARE_AUTOSUBSCRIBE_KEY: False,
112
backend.UDF_AUTOSUBSCRIBE_KEY: False,
113
backend.DOWNLOAD_KEY: -1, # no limit
114
backend.UPLOAD_KEY: -1, # no limit
117
next_result = object()
119
'account_info', # account
120
'devices_info', 'device_names_info', # devices
121
'change_device_settings', 'remove_device',
122
'volumes_info', 'change_volume_settings', # volumes
123
'create_folder', 'validate_path_for_folder',
124
'replications_info', 'change_replication_settings', # replications
125
'file_sync_status', 'enable_files', 'disable_files', # files
126
'connect_files', 'disconnect_files',
127
'restart_files', 'start_files', 'stop_files',
128
'file_sync_settings_info',
129
'change_file_sync_settings',
130
'restore_file_sync_settings',
135
class FakedConfirmDialog(object):
136
"""Fake a confirmation dialog."""
138
response = args = kwargs = None
141
def warning(cls, *a, **kw):
142
"""Simulate a warning message."""
148
class FakedFileDialog(object):
149
"""Fake a file chooser dialog."""
151
response = args = kwargs = None
153
# Invalid name "getExistingDirectory"
154
# pylint: disable=C0103
157
def getExistingDirectory(cls, *a, **kw):
158
"""Simulate a directory chooser."""
164
class BaseTestCase(TestCase):
165
"""Base Test Case."""
168
innerclass_name = None
172
@skip_if_abstract_class
174
super(BaseTestCase, self).setUp()
175
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)
181
if hasattr(self.ui, 'backend'):
182
# clean backend calls
183
self.ui.backend._called.clear()
185
def get_pixmap_data(self, pixmap):
186
"""Get the raw data of a QPixmap."""
187
byte_array = QtCore.QByteArray()
188
array_buffer = QtCore.QBuffer(byte_array)
189
pixmap.save(array_buffer, "PNG")
192
# pylint: disable=C0103
193
def assertEqualPixmaps(self, pixmap1, pixmap2):
194
"""Compare two Qt pixmaps."""
195
d1 = self.get_pixmap_data(pixmap1)
196
d2 = self.get_pixmap_data(pixmap2)
197
self.assertEqual(d1, d2)
198
# pylint: enable=C0103
200
def assert_backend_called(self, method_name, *args, **kwargs):
201
"""Check that the control panel backend 'method_name' was called."""
202
self.assertIn(method_name, self.ui.backend._called)
203
self.assertEqual(self.ui.backend._called[method_name], (args, kwargs))
205
def test_init_loads_ui(self, expected_setup_ui=None):
206
"""The __init__ method loads the ui."""
207
if self.innerclass_ui is None:
209
self.patch(self.innerclass_ui, self.innerclass_name, FakeUi)
210
if getattr(self.class_ui, '_setup', None) is not None:
211
self.patch(self.class_ui, '_setup', lambda *a: None)
212
# pylint: disable=E1102
213
self.ui = self.class_ui(**self.kwargs)
214
# pylint: disable=E1101
216
if expected_setup_ui is None:
217
expected_setup_ui = self.ui
219
expected_setup_ui = expected_setup_ui(self.ui)
220
self.assertEqual(self.ui.ui._called,
221
{'setupUi': ((expected_setup_ui,), {})})