From 5aed1e6456885c575e2fe29a4c78de345dd6b484 Mon Sep 17 00:00:00 2001 From: Keith Vassallo Date: Mon, 29 Apr 2024 11:38:41 +0100 Subject: [PATCH] Continued to improve reminder test coverage. --- .../reminders/model/remindercontainer.py | 14 +++- tests/test_reminder.py | 28 +++++-- tests/test_remindercontainer.py | 84 +++++++++++++------ 3 files changed, 94 insertions(+), 32 deletions(-) diff --git a/taskbridge/reminders/model/remindercontainer.py b/taskbridge/reminders/model/remindercontainer.py index 37208d9..ccc8659 100644 --- a/taskbridge/reminders/model/remindercontainer.py +++ b/taskbridge/reminders/model/remindercontainer.py @@ -492,6 +492,8 @@ def sync_container_deletions(discovered_local: List[LocalList], discovered_remot # Sync local deletions to remote if fail == "fail_retrieve": helpers.DATA_LOCATION = Path("/") + else: + helpers.DATA_LOCATION = Path.home() / "Library" / "Application Support" / "TaskBridge" try: with closing(sqlite3.connect(helpers.db_folder())) as connection: connection.row_factory = sqlite3.Row @@ -518,6 +520,8 @@ def sync_container_deletions(discovered_local: List[LocalList], discovered_remot # Empty table if fail == "fail_delete": helpers.DATA_LOCATION = Path("/") + else: + helpers.DATA_LOCATION = Path.home() / "Library" / "Application Support" / "TaskBridge" try: with closing(sqlite3.connect(helpers.db_folder())) as connection: connection.row_factory = sqlite3.Row @@ -655,10 +659,16 @@ def sync_reminder_deletions(fail: str = None) -> tuple[bool, str] | tuple[bool, return False, message for container in ReminderContainer.CONTAINER_LIST: + if not container.sync: + continue success, data = container.load_local_reminders() if not success or fail == "fail_load_local": return False, 'Failed to load local reminders: {}'.format(data) - success, data = container.load_remote_reminders() + if not fail == "fail_load_remote": + success, data = container.load_remote_reminders() + else: + success = False + data = "Explicitly set to fail to load reminders" if not success or fail == "fail_load_remote": return False, 'Failed to load remote reminders: {}'.format(data) @@ -689,6 +699,8 @@ def sync_reminder_deletions(fail: str = None) -> tuple[bool, str] | tuple[bool, # Empty table if fail == "fail_db": helpers.DATA_LOCATION = Path("/") + else: + helpers.DATA_LOCATION = Path.home() / "Library" / "Application Support" / "TaskBridge" try: with closing(sqlite3.connect(helpers.db_folder())) as connection: connection.row_factory = sqlite3.Row diff --git a/tests/test_reminder.py b/tests/test_reminder.py index ff230f7..0dd3ea8 100644 --- a/tests/test_reminder.py +++ b/tests/test_reminder.py @@ -1,6 +1,7 @@ import datetime import os import json +from pathlib import Path import pytest import caldav @@ -19,6 +20,7 @@ class TestReminder: + CALDAV_CONNECTED: bool = False @staticmethod def __create_reminder_from_local() -> Reminder: @@ -60,19 +62,35 @@ def __create_reminder_from_remote() -> Reminder: return reminder @staticmethod - def __connect_caldav(): - conf_file = helpers.settings_folder() / 'conf.json' + def __connect_caldav(fail: bool = False, test_caldav: bool = True): + if TestReminder.CALDAV_CONNECTED and not fail: + TestReminder.CALDAV_CONNECTED = False + return + + if test_caldav: + conf_file = Path(os.path.abspath(os.path.dirname(__file__))) / "conf.json" + else: + conf_file = helpers.settings_folder() / 'conf.json' if not os.path.exists(conf_file): - assert False, "Failed to load configuration file." - with open(helpers.settings_folder() / 'conf.json', 'r') as fp: + assert False, "Failed to load configuration file at {}".format(conf_file) + + with open(conf_file, 'r') as fp: settings = json.load(fp) ReminderController.CALDAV_USERNAME = settings['caldav_username'] ReminderController.CALDAV_URL = settings['caldav_url'] ReminderController.CALDAV_HEADERS = {} - ReminderController.CALDAV_PASSWORD = keyring.get_password("TaskBridge", "CALDAV-PWD") + + if fail: + ReminderController.CALDAV_PASSWORD = 'bogus' + elif test_caldav: + ReminderController.CALDAV_PASSWORD = config('TEST_CALDAV_PASSWORD') + else: + ReminderController.CALDAV_PASSWORD = keyring.get_password("TaskBridge", "CALDAV-PWD") + ReminderController.TO_SYNC = settings['reminder_sync'] ReminderController.connect_caldav() + TestReminder.CALDAV_CONNECTED = True def test_create_from_local(self): uuid = "x-apple-id://1234-5678-9012" diff --git a/tests/test_remindercontainer.py b/tests/test_remindercontainer.py index db42de2..f9ce878 100644 --- a/tests/test_remindercontainer.py +++ b/tests/test_remindercontainer.py @@ -26,15 +26,18 @@ class TestReminderContainer: @staticmethod def __connect_caldav(fail: bool = False, test_caldav: bool = True): if TestReminderContainer.CALDAV_CONNECTED and not fail: - TestReminderContainer.CALDAV_CONNECTED = False return + if fail: + helpers.CALDAV_PRINCIPAL = None + TestReminderContainer.CALDAV_CONNECTED = False + if test_caldav: - conf_file = os.getcwd() + "/conf.json" + conf_file = Path(os.path.abspath(os.path.dirname(__file__))) / "conf.json" else: conf_file = helpers.settings_folder() / 'conf.json' if not os.path.exists(conf_file): - assert False, "Failed to load configuration file." + assert False, "Failed to load configuration file at {}".format(conf_file) with open(conf_file, 'r') as fp: settings = json.load(fp) @@ -71,6 +74,12 @@ def __create_reminder_from_local() -> Reminder: reminder = Reminder.create_from_local(values) return reminder + @staticmethod + def __reset_state() -> None: + helpers.DRY_RUN = False + TestReminderContainer.__connect_caldav() + helpers.DATA_LOCATION = Path.home() / "Library" / "Application Support" / "TaskBridge" + # noinspection SpellCheckingInspection @staticmethod def __create_reminder_from_remote() -> Reminder: @@ -115,13 +124,15 @@ def __get_sync_container() -> ReminderContainer: @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires CalDAV credentials") def test_load_caldav_calendars(self): - TestReminderContainer.__connect_caldav() + TestReminderContainer.__reset_state() success, remote_calendars = ReminderContainer.load_caldav_calendars() assert success is True assert len(remote_calendars) > 0 @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud") def test_load_local_lists(self): + TestReminderContainer.__reset_state() + success, local_lists = ReminderContainer.load_local_lists() assert success is True assert len(local_lists) > 0 @@ -132,6 +143,8 @@ def test_load_local_lists(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud") def test_count_local_completed(self): + TestReminderContainer.__reset_state() + success, data = ReminderContainer.count_local_completed() assert success is True assert isinstance(data, int) @@ -142,12 +155,16 @@ def test_count_local_completed(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud") def test_delete_local_completed(self): + TestReminderContainer.__reset_state() + success, data = ReminderContainer.delete_local_completed() assert success is True success, count = ReminderContainer.count_local_completed() assert count == 0 def test_assoc_list_local_remote(self): + TestReminderContainer.__reset_state() + mock_local = [LocalList("sync_me"), LocalList("do_not_sync_me")] mock_remote = [RemoteCalendar(calendar_name="sync_me"), RemoteCalendar(calendar_name="do_not_sync_me")] mock_sync = ['sync_me'] @@ -167,6 +184,8 @@ def test_assoc_list_local_remote(self): ReminderContainer.CONTAINER_LIST.clear() def test_assoc_list_remote_local(self): + TestReminderContainer.__reset_state() + mock_local = [LocalList("sync_me"), LocalList("do_not_sync_me")] mock_remote = [RemoteCalendar(calendar_name="sync_me"), RemoteCalendar(calendar_name="do_not_sync_me")] mock_sync = ['sync_me'] @@ -194,8 +213,8 @@ def test_assoc_list_remote_local(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud and CalDAV credentials") def test_create_linked_containers(self): - helpers.DRY_RUN = False - TestReminderContainer.__connect_caldav() + TestReminderContainer.__reset_state() + mock_local = [LocalList("sync_me"), LocalList("do_not_sync_me"), LocalList("Reminders"), @@ -242,6 +261,8 @@ def test_create_linked_containers(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires local filesystem.") def test_seed_container_table(self): + TestReminderContainer.__reset_state() + ReminderContainer.seed_container_table() try: with closing(sqlite3.connect(helpers.db_folder())) as connection: @@ -264,6 +285,8 @@ def test_seed_container_table(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires local filesystem.") def test_persist_containers(self): + TestReminderContainer.__reset_state() + ReminderContainer(LocalList("sync_me"), RemoteCalendar(calendar_name="sync_me"), True) ReminderContainer(LocalList("do_not_sync_me"), RemoteCalendar(calendar_name="do_not_sync_me"), False) ReminderContainer.persist_containers() @@ -301,6 +324,8 @@ def test_persist_containers(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires local filesystem.") def test_seed_reminder_table(self): + TestReminderContainer.__reset_state() + ReminderContainer.seed_reminder_table() try: with closing(sqlite3.connect(helpers.db_folder())) as connection: @@ -324,6 +349,8 @@ def test_seed_reminder_table(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires local filesystem.") def test_persist_reminders(self): + TestReminderContainer.__reset_state() + container = ReminderContainer(LocalList("sync_me"), RemoteCalendar(calendar_name="sync_me"), True) local_reminder = Reminder("local_uuid", "local_name", None, datetime.datetime.now(), None, None, None, None, False) @@ -368,8 +395,7 @@ def test_persist_reminders(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires CalDAV credentials") def test__delete_remote_containers(self): - helpers.DRY_RUN = False - TestReminderContainer.__connect_caldav() + TestReminderContainer.__reset_state() # Create a remote container to_delete = RemoteCalendar(calendar_name='DELETE_ME') @@ -410,7 +436,7 @@ def test__delete_remote_containers(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud") def test__delete_local_containers(self): - helpers.DRY_RUN = False + TestReminderContainer.__reset_state() # Create a local container to_delete = LocalList('DELETE_ME') @@ -452,9 +478,7 @@ def test__delete_local_containers(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud and CalDAV credentials") def test_sync_container_deletions(self): - helpers.DRY_RUN = False - TestReminderContainer.__connect_caldav() - helpers.DATA_LOCATION = Path.home() / "Library" / "Application Support" / "TaskBridge" + TestReminderContainer.__reset_state() for run in range(4): fail = None @@ -533,6 +557,7 @@ def test_sync_container_deletions(self): assert remote_presence is None # Clean Up + TestReminderContainer.__reset_state() ReminderContainer.CONTAINER_LIST.clear() try: with closing(sqlite3.connect(helpers.db_folder())) as connection: @@ -546,7 +571,7 @@ def test_sync_container_deletions(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud and CalDAV credentials") def test__delete_remote_reminders(self): - helpers.DRY_RUN = False + TestReminderContainer.__reset_state() sync_container = TestReminderContainer.__get_sync_container() @@ -612,7 +637,7 @@ def test__delete_remote_reminders(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud and CalDAV credentials") def test__delete_local_reminders(self): - helpers.DRY_RUN = False + TestReminderContainer.__reset_state() sync_container = TestReminderContainer.__get_sync_container() @@ -679,7 +704,8 @@ def test__delete_local_reminders(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud") def test_get_saved_reminders(self): - helpers.DRY_RUN = False + TestReminderContainer.__reset_state() + sync_container = TestReminderContainer.__get_sync_container() # Create a local reminder @@ -716,9 +742,7 @@ def test_get_saved_reminders(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud and CalDAV credentials") def test_sync_reminder_deletions(self): - helpers.DRY_RUN = False - TestReminderContainer.__connect_caldav() - helpers.DATA_LOCATION = Path.home() / "Library" / "Application Support" / "TaskBridge" + TestReminderContainer.__reset_state() tests = [None, 'fail_seed', 'fail_load_local', 'fail_load_remote', 'fail_get_saved', 'fail_db'] for run in range(6): @@ -745,7 +769,7 @@ def test_sync_reminder_deletions(self): assert False, 'Failed to create remote reminder.' success, data = to_delete_remote.upsert_local(sync_container) if not success: - assert False, 'Failed to create remote task.' + assert False, 'Failed to create local task.' # Refresh the container with the new reminders, sync, and persist sync_container.load_local_reminders() @@ -791,6 +815,7 @@ def test_sync_reminder_deletions(self): assert remote_presence is None # Clean Up + TestReminderContainer.__reset_state() delete_reminder_script = reminderscript.delete_reminder_script helpers.run_applescript(delete_reminder_script, synced_local.uuid) remote_object = sync_container.remote_calendar.cal_obj.search(todo=True, uid=to_delete_remote.uuid) @@ -809,7 +834,8 @@ def test_sync_reminder_deletions(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud") def test_load_local_reminders(self): - helpers.DRY_RUN = False + TestReminderContainer.__reset_state() + sync_container = TestReminderContainer.__get_sync_container() # Create a local reminder @@ -842,7 +868,8 @@ def test_load_local_reminders(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires CalDAV credentials") def test_load_remote_reminders(self): - helpers.DRY_RUN = False + TestReminderContainer.__reset_state() + sync_container = TestReminderContainer.__get_sync_container() # Create a remote reminder @@ -868,7 +895,8 @@ def test_load_remote_reminders(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud and CalDAV credentials") def test_sync_local_reminders_to_remote(self): - helpers.DRY_RUN = False + TestReminderContainer.__reset_state() + sync_container = TestReminderContainer.__get_sync_container() fail = None @@ -918,7 +946,8 @@ def test_sync_local_reminders_to_remote(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud and CalDAV credentials") def test_sync_remote_reminders_to_local(self): - helpers.DRY_RUN = False + TestReminderContainer.__reset_state() + sync_container = TestReminderContainer.__get_sync_container() fail = None @@ -968,7 +997,8 @@ def test_sync_remote_reminders_to_local(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud and CalDAV credentials") def test_sync_reminders(self): - helpers.DRY_RUN = False + TestReminderContainer.__reset_state() + sync_container = TestReminderContainer.__get_sync_container() fail = None @@ -1056,8 +1086,8 @@ def test___repr__(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud and CalDAV credentials") def test_disconnected_caldav(self): - helpers.DRY_RUN = False - TestReminderContainer.__connect_caldav(True) + TestReminderContainer.__reset_state() + TestReminderContainer.__connect_caldav(fail=True) ReminderContainer.CONTAINER_LIST.clear() # Fail to load remote calendars @@ -1099,6 +1129,8 @@ def test_disconnected_caldav(self): @pytest.mark.skipif(TEST_ENV != 'local', reason="Requires Mac system with iCloud and CalDAV credentials") def test_unavailable_db(self): + TestReminderContainer.__reset_state() + helpers.DATA_LOCATION = Path("/") success, data = ReminderContainer.seed_container_table()