diff --git a/notes_app/controller/notes_controller.py b/notes_app/controller/notes_controller.py index 3fce051..44ab2f9 100644 --- a/notes_app/controller/notes_controller.py +++ b/notes_app/controller/notes_controller.py @@ -1,3 +1,4 @@ +from datetime import datetime from notes_app.view.notes_view import NotesView @@ -53,6 +54,9 @@ def save_file_data(self, data) -> None: with open(self.model.file_path, "w") as f: f.write(data) except Exception as exc: + # another attempt at writing at least a dump file + with open(f"__dump__{datetime.now():%Y_%m_%d_%H_%M_%S}", "w") as f: + f.write(data) raise exc self.model.update() diff --git a/notes_app/view/notes_view.py b/notes_app/view/notes_view.py index 06d59d7..b9b69db 100644 --- a/notes_app/view/notes_view.py +++ b/notes_app/view/notes_view.py @@ -722,7 +722,9 @@ def save_current_section_to_file(self): self.controller.save_file_data(data=raw_text_data) except Exception as exc: - self.show_error_bar(error_message=f"Error while saving file, details: {exc}") + self.show_error_bar( + error_message=f"Error while saving file, try recovering from dump file, details: {exc}" + ) return def press_menu_item_save_file(self, *args): diff --git a/tests/conftest.py b/tests/conftest.py index 8ba599b..d439cfe 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,6 +22,7 @@ EMPTY_FILE_PATH = f"{TEST_OVERRIDE_DEFAULT_NOTES_FILE_DIR_PATH}/{EMPTY_FILE_NAME}" EMPTY_FILE_CONTENT = """""" +DUMP_FILES_PATH = f"{TEST_OVERRIDE_DEFAULT_NOTES_FILE_DIR_PATH}/" defaults = Defaults() defaults.DEFAULT_NOTES_FILE_NAME = TEST_OVERRIDE_DEFAULT_NOTES_FILE_PATH @@ -91,6 +92,12 @@ def delete_default_notes_empty_file(): os.remove(EMPTY_FILE_PATH) +def delete_dump_files(): + for file in os.listdir(DUMP_FILES_PATH): + if file.startswith("__dump__"): + os.remove(file) + + @pytest.fixture(autouse=True) def get_default_test_files_state(): create_settings_file() @@ -102,6 +109,7 @@ def get_default_test_files_state(): delete_model_file() delete_default_notes_file() delete_default_notes_empty_file() + delete_dump_files() @pytest.fixture diff --git a/tests/test_unit_controller.py b/tests/test_unit_controller.py index b59da9a..e9b68a8 100644 --- a/tests/test_unit_controller.py +++ b/tests/test_unit_controller.py @@ -2,7 +2,7 @@ from time import sleep from datetime import datetime -from os import path, remove +from os import path, remove, listdir, getcwd from os.path import exists from notes_app.defaults import Defaults @@ -116,6 +116,18 @@ def test_save_file_data_handle_error(self, get_app): assert controller.model.file_size > 0 # exact file size differs between OS types assert datetime.fromtimestamp(controller.model.last_updated_on) >= _epoch_before + # assert the file gets correctly dumped to disk + dump_files_to_evaluate = [] + for file in listdir(getcwd()): + if file.startswith("__dump__"): + dump_files_to_evaluate.append(file) + + # assert only 1 dump file is written + assert len(dump_files_to_evaluate) == 1 + with open(file=dump_files_to_evaluate[0], mode="r") as f: + assert f.readlines() == [' Quod equidem non reprehendo\n', + ' Quis istum dolorem timet !\n'] + def test_get_screen(self, get_app): controller = get_app.controller assert isinstance(controller.get_screen(), NotesView) diff --git a/tests/test_unit_view.py b/tests/test_unit_view.py index bc1e3cd..8d0f48a 100644 --- a/tests/test_unit_view.py +++ b/tests/test_unit_view.py @@ -886,7 +886,7 @@ def test_save_current_section_to_file_handle_error(self, get_app): ) assert isinstance(screen.snackbar, CustomSnackbar) - assert screen.snackbar.text.startswith("Error while saving file, details:") + assert screen.snackbar.text.startswith("Error while saving file, try recovering from dump file, details:") def test_press_menu_item_save_file_is_not_external_update(self, get_app): # setting model._last_updated_on manually will guarantee model.external_update returns False