896
928
"""The creation with only a volume_id."""
897
929
item = gui.FolderItem(path=self.path, queue=self.queue)
899
self.assertEqual(item.text(gui.LOCAL_SUBSCRIPTION_COL), '')
900
self.assertEqual(item.text(gui.LOCAL_SPACE_COL), '')
931
self.assertEqual(unicode(item.text(gui.LOCAL_SUBSCRIPTION_COL)), '')
932
self.assertEqual(unicode(item.text(gui.LOCAL_SPACE_COL)), '')
901
933
self.assertEqual(item.path, self.path)
902
934
self.assertEqual(item.volume_id, None)
903
self.assertEqual(item.thread, self.calculator)
935
self.assertIsInstance(item.thread, gui.CalculateSize)
904
936
self.assertEqual(item.size, None)
905
937
self.assertEqual(item.checkState(gui.LOCAL_SUBSCRIPTION_COL),
908
self.assertTrue(self.calculator.started)
911
class LocalFoldersPanelTestCase(UbuntuOneBinTestCase):
939
# pylint: disable=E1101
940
self.assertTrue(item.thread.started)
943
class BaseLocalFoldersPanelTestCase(UbuntuOneBinTestCase,
944
BaseLocalFoldersTestCase):
945
"""Base test suite for the LocalFoldersPanel widget."""
947
class_ui = gui.LocalFoldersPanel
949
@defer.inlineCallbacks
951
self.patch(FakedControlPanelBackend, 'exposed_results',
953
'account_info': ACCOUNT_INFO})
954
self.patch(gui, 'default_folders', self.default_folders)
956
self.timer = FakedTimer()
957
self.kwargs['timer'] = self.timer
958
self.addCleanup(self.kwargs.pop, 'timer')
960
yield super(BaseLocalFoldersPanelTestCase, self).setUp()
962
self.patch(self.ui.backend, 'validate_path_for_folder',
965
def default_folders(self, user_home):
966
"""A fixed default folders list."""
967
return [os.path.join(user_home, f) for f in DEFAULT_FOLDERS]
969
def validate_path(self, folder):
970
"""A fixed path validator."""
971
return defer.succeed(u'invalid' not in folder.lower())
973
def assert_space_header_correct(self, total):
974
"""Check that the 'used space' header is correct."""
975
total = '(%s)' % gui.humanize(total)
976
expected = gui.LOCAL_FOLDERS_SPACE_HEADER.format(space_total=total)
977
actual = self.ui.ui.folders.headerItem().text(gui.LOCAL_SPACE_COL)
978
self.assertEqual(expected, unicode(actual))
980
def assert_folder_added(self, path, volume_id=None, item=None):
981
"""A entry for 'path' was added to the folder list."""
982
folders = self.ui.ui.folders
984
if path == MUSIC_PATH:
985
display_name = gui.MUSIC_DISPLAY_NAME
987
display_name = path.replace(USER_HOME + os.path.sep, '')
988
if item is None: # search for it
989
items = folders.findItems(display_name,
990
QtCore.Qt.MatchFixedString | QtCore.Qt.MatchCaseSensitive,
992
self.assertEqual(len(items), 1)
994
self.assertEqual(display_name,
995
unicode(item.text(gui.LOCAL_SUBSCRIPTION_COL)))
997
self.assertEqual(item.path, path)
998
self.assertEqual(item.volume_id, volume_id)
999
# should be checked if the volume_id is not None
1000
subscribed = item.checkState(gui.LOCAL_SUBSCRIPTION_COL) == gui.CHECKED
1001
self.assertEqual(subscribed, volume_id != None)
1003
self.timer.timeout.emit() # update sizes will be called
1005
# if volume_id is not None, no 'space' is expected since is a cloud
1006
# folder, and its size is accounted for in the quota used amount
1007
size = gui.humanize(size_for_path(path)) if volume_id is None else ''
1008
self.assertEqual(unicode(item.text(gui.LOCAL_SPACE_COL)), size)
1011
class LocalFoldersPanelTestCase(BaseLocalFoldersPanelTestCase):
912
1012
"""Test suite for the LocalFoldersPanel widget."""
914
class_ui = gui.LocalFoldersPanel
916
# TODO: add the test suite (LP: #959690).
1014
def test_initial_state(self):
1015
"""Initial state is correct."""
1016
self.assertIsInstance(self.ui.timer, gui.QtCore.QTimer)
1017
self.assertFalse(self.ui.timer.isActive())
1019
self.assertEqual(self.ui.ui.folders.topLevelItemCount(), 0)
1020
self.assertFalse(self.ui.ui.offer_frame.isVisible())
1022
headers = self.ui.ui.folders.header()
1023
self.assertEqual(headers.resizeMode(gui.LOCAL_SUBSCRIPTION_COL),
1025
self.assertEqual(headers.resizeMode(gui.LOCAL_SPACE_COL),
1026
headers.ResizeToContents)
1028
header = self.ui.ui.folders.headerItem()
1029
self.assertEqual(unicode(header.text(gui.LOCAL_SUBSCRIPTION_COL)),
1030
gui.LOCAL_FOLDERS_FOLDER_HEADER)
1032
self.assertEqual(unicode(self.ui.ui.add_folder_button.text()),
1033
gui.FOLDERS_BUTTON_ADD_FOLDER)
1034
self.assertEqual(self.ui.ui.add_folder_button.add_folder_func,
1036
self.assertEqual(unicode(self.ui.ui.add_storage_button.text()),
1037
gui.GET_MORE_STORAGE)
1039
@defer.inlineCallbacks
1040
def test_is_processing_while_asking_info(self):
1041
"""The ui is processing while the contents are loaded."""
1043
def check_account():
1044
"""The ui must be is_processing."""
1045
self.assertTrue(self.ui.is_processing, 'ui must be processing')
1048
def check_volumes(with_storage_info):
1049
"""The ui must be is_processing."""
1050
self.assertFalse(with_storage_info)
1051
self.assertTrue(self.ui.is_processing, 'ui must be processing')
1052
return FAKE_VOLUMES_ONLY_ROOT_INFO
1054
self.patch(self.ui.backend, 'account_info', check_account)
1055
self.patch(self.ui.backend, 'volumes_info', check_volumes)
1057
yield self.ui.load() # trigger the info request
1059
self.assertEqual(self.ui.account_info, ACCOUNT_INFO)
1060
self.assert_space_header_correct(ACCOUNT_INFO['quota_used'])
1062
def test_is_not_processing_after_info_ready(self):
1063
"""The ui is not processing when contents are load."""
1064
self.ui.process_info(FAKE_VOLUMES_ONLY_ROOT_INFO)
1066
self.assertFalse(self.ui.is_processing)
1068
@defer.inlineCallbacks
1069
def test_info_is_requested_on_load(self):
1070
"""The volumes info is requested to the backend."""
1071
yield self.ui.load()
1072
self.assert_backend_called('account_info')
1073
self.assert_backend_called('volumes_info', with_storage_info=False)
1075
@defer.inlineCallbacks
1076
def test_process_info(self):
1077
"""The volumes info is processed when ready."""
1078
volumes_info = FAKE_VOLUMES_INFO
1079
yield self.ui.process_info(volumes_info)
1081
self.assertTrue(self.ui.timer.isActive())
1083
# the following will execute update_sizes once
1084
# will fill in all the path sizes for the already added folders
1085
self.timer.timeout.emit()
1087
for _, _, vols in volumes_info:
1088
volumes.extend(vols)
1089
volumes = sorted(volumes, key=operator.itemgetter('path'))
1091
for volume in volumes:
1092
if (volume['type'] != self.ui.backend.FOLDER_TYPE or
1093
not bool(volume['subscribed'])):
1094
# non-folders or unsubscribed should not appear in the tree
1096
self.assert_folder_added(volume['path'],
1097
volume_id=volume['volume_id'])
1098
for folder in gui.default_folders(USER_HOME):
1099
valid = yield self.validate_path(folder)
1101
continue # invalid folders should not appear in the tree
1102
self.assert_folder_added(folder, volume_id=None, item=None)
1104
self.assert_space_header_correct(ACCOUNT_INFO['quota_used'])
1106
@defer.inlineCallbacks
1107
def test_process_info_twice(self):
1108
"""The volumes info can be processed twice."""
1109
yield self.test_process_info()
1110
yield self.test_process_info()
1112
@defer.inlineCallbacks
1113
def test_timer_is_not_started_if_no_volumes(self):
1114
"""If not volumes to show, timer is not started."""
1115
self.patch(gui, 'default_folders', lambda *a, **kw: [])
1116
yield self.ui.process_info([])
1117
self.assertFalse(self.ui.timer.isActive())
1119
@defer.inlineCallbacks
1120
def test_on_folders_item_changed_subscription_column(self):
1121
"""If a new folder is subscribed, update header size."""
1122
# processing only a root folder will force showing only default,
1123
# unsubscribed folders
1124
yield self.ui.process_info(FAKE_VOLUMES_ONLY_ROOT_INFO)
1126
new_size = ACCOUNT_INFO['quota_used']
1127
for i in xrange(self.ui.ui.folders.topLevelItemCount()):
1128
item = self.ui.ui.folders.topLevelItem(i)
1129
item.setCheckState(gui.LOCAL_SUBSCRIPTION_COL, gui.CHECKED)
1130
new_size += size_for_path(item.path)
1131
self.assert_space_header_correct(new_size)
1133
# quota was not filled, so "get more storage" is not shown
1134
available = ACCOUNT_INFO['quota_total'] - ACCOUNT_INFO['quota_used']
1135
assert new_size <= available
1136
self.assertFalse(self.ui.ui.offer_frame.isVisible())
1138
# now, deselect each folder and confirm space column is correct
1139
for i in xrange(self.ui.ui.folders.topLevelItemCount()):
1140
item = self.ui.ui.folders.topLevelItem(i)
1141
item.setCheckState(gui.LOCAL_SUBSCRIPTION_COL, gui.UNCHECKED)
1142
new_size -= size_for_path(item.path)
1143
self.assert_space_header_correct(new_size)
1145
self.assert_space_header_correct(ACCOUNT_INFO['quota_used'])
1147
@defer.inlineCallbacks
1148
def test_on_folders_item_changed_unsubscribing(self):
1149
"""If a cloud folder was unsubscribed, do not update header."""
1150
# patch update_sizes with sel.fail to ensure is not called
1151
self.patch(self.ui, 'update_sizes', self.fail)
1153
# process only root and a subscribed music folder
1154
yield self.ui.process_info(FAKE_VOLUMES_MINIMAL_INFO)
1156
item = self.ui.ui.folders.topLevelItem(0)
1157
item.setCheckState(gui.LOCAL_SUBSCRIPTION_COL, gui.UNCHECKED)
1159
@defer.inlineCallbacks
1160
def test_on_folders_item_changed_space_column(self):
1161
"""If user clicked the 'space' column, don't update sizes."""
1162
# patch update_sizes with sel.fail to ensure is not called
1163
self.patch(self.ui, 'update_sizes', self.fail)
1165
yield self.ui.process_info(FAKE_VOLUMES_INFO)
1167
for i in xrange(self.ui.ui.folders.topLevelItemCount()):
1168
item = self.ui.ui.folders.topLevelItem(i)
1169
self.ui.on_folders_itemChanged(item, gui.LOCAL_SPACE_COL)
1170
# size does not change
1171
self.assert_space_header_correct(ACCOUNT_INFO['quota_used'])
1173
@defer.inlineCallbacks
1174
def test_going_over_quota(self):
1175
"""When subscribing a folder, alert the user if quota was exceeded."""
1176
yield self.ui.process_info(FAKE_VOLUMES_INFO)
1178
available = ACCOUNT_INFO['quota_total'] - ACCOUNT_INFO['quota_used']
1179
self.patch(FakedCalculateSize, 'next_size', available + 1)
1181
self.ui.add_folder(self.path)
1182
self.ui.on_folder_created(self.path)
1184
# quota was exceeeded, so "get more storage" should be shown
1185
self.assert_space_header_correct(ACCOUNT_INFO['quota_total'] + 1)
1186
self.assertTrue(self.ui.ui.offer_frame.isVisible())
1188
# XXX: still pending to add tests about stopping the timer and the threads
1191
class LocalFoldersPanelAddFolderTestCase(BaseLocalFoldersPanelTestCase):
1192
"""Test suite for the add_folder method from LocalFoldersPanel."""
1194
def test_folder_is_added(self, folder_path=None, suggested=None):
1195
"""Adding a folder adds it to the folder list."""
1196
former_count = self.ui.ui.folders.topLevelItemCount()
1198
if folder_path is None:
1199
folder_path = self.path
1200
self.ui.add_folder(folder_path, suggested=suggested)
1202
new_count = self.ui.ui.folders.topLevelItemCount()
1203
self.assertEqual(new_count, former_count + 1)
1204
self.assert_folder_added(folder_path)
1206
def test_add_music_folder_adds_the_folder(self):
1207
"""Adding the purchased music folder adds it to the folder list."""
1208
self.test_folder_is_added(folder_path=MUSIC_PATH,
1209
suggested=MUSIC_REAL_PATH)
1211
def test_add_music_folder_adds_the_folder_with_suggested_path(self):
1212
"""Adding the purchased music folder adds it to the folder list."""
1213
suggested_path = '~/' + MUSIC_REAL_PATH
1214
self.test_folder_is_added(folder_path=MUSIC_PATH,
1215
suggested=suggested_path)
1217
def test_do_not_add_twice(self):
1218
"""The same folder will not be added twice."""
1219
assert self.ui.ui.folders.topLevelItemCount() == 0
1221
self.ui.add_folder(self.path)
1222
self.ui.add_folder(self.path)
1224
self.assert_folder_added(self.path)
1225
self.assertEqual(1, self.ui.ui.folders.topLevelItemCount())
1227
def test_do_not_call_backend(self):
1228
"""Adding a folder do not call the backend."""
1229
self.ui.backend._called.clear()
1230
self.ui.ui.add_folder_button.folderCreated.emit(self.path)
1232
self.assertEqual(self.ui.backend._called, {})
1234
def test_on_folder_created(self):
1235
"""When a folder was created, subscribe to it."""
1236
self.ui.add_folder(self.path)
1238
folders = self.ui.ui.folders
1239
item = folders.topLevelItem(folders.topLevelItemCount() - 1)
1240
assert item.checkState(gui.LOCAL_SUBSCRIPTION_COL) == gui.UNCHECKED
1242
self.ui.ui.add_folder_button.folderCreated.emit(self.path)
1244
subscribed = item.checkState(gui.LOCAL_SUBSCRIPTION_COL) == gui.CHECKED
1245
self.assertTrue(subscribed)
1248
class LocalFoldersPanelApplyChangesTestCase(BaseLocalFoldersPanelTestCase):
1249
"""Test suite for the apply_changes method from LocalFoldersPanel."""
1251
@defer.inlineCallbacks
1253
yield super(LocalFoldersPanelApplyChangesTestCase, self).setUp()
1254
self.changes_applied = defer.Deferred()
1255
self.ui.backend._called.clear()
1256
self.ui.changesApplied.connect(lambda:
1257
self.changes_applied.callback(None))
1259
@defer.inlineCallbacks
1260
def test_apply_changes_calls_backend(self):
1261
"""When applying changes, the calls to the backend are made."""
1262
yield self.ui.apply_changes()
1263
yield self.changes_applied
1265
@defer.inlineCallbacks
1266
def test_apply_changes_stop_threads(self):
1267
"""When applying changes, threads are stopped."""
1268
yield self.ui.apply_changes()
1269
yield self.changes_applied
1271
@defer.inlineCallbacks
1272
def test_apply_changes_with_no_changes(self):
1273
"""If there are no changes to apply, the backend is not called."""
1274
yield self.ui.apply_changes()
1275
yield self.changes_applied
1276
self.assertEqual(self.ui.backend._called, {})
1278
def test_timer_is_stopped(self):
1279
"""When applying changes, timer is stopped."""
1280
yield self.ui.apply_changes()
1281
yield self.changes_applied
1282
self.assertFalse(self.ui.timer.isActive())
1284
# XXX: more tests are needed, to cover that only those newly added folders,
1285
# and those newly subscribed or unsibscribed folders are modified by
1286
# calling the backend by either create_folder or change_volume_settings