From 9bb1993e7768f721ab2260b407c58ec8dbb5f29c Mon Sep 17 00:00:00 2001 From: deeplow Date: Thu, 29 Feb 2024 11:17:30 +0000 Subject: [PATCH] Create tests/test_settings.py with extra coverage Previously settings was implicitly tested on tests/gui/test_updater.py. However this was concerned with updater-related tests only, which incidentally covered almost all of settings.py. However, a few tests were missing. This commit increases the test coverage, but also tests additional test conditions. The goal is to help us increase the test coverage of the previous scenario, which tested for the persistence of user data (settings). This way we can drop the requirement to test this on linux hosts, which is slightly harder (more cumbersome) to do. --- tests/gui/test_updater.py | 21 +------- tests/test_settings.py | 103 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 20 deletions(-) create mode 100644 tests/test_settings.py diff --git a/tests/gui/test_updater.py b/tests/gui/test_updater.py index a8a4f48..60470f5 100644 --- a/tests/gui/test_updater.py +++ b/tests/gui/test_updater.py @@ -18,6 +18,7 @@ from dangerzone.gui import updater as updater_module from dangerzone.gui.updater import UpdateReport, UpdaterThread from dangerzone.util import get_version +from ..test_settings import default_settings_0_4_1, save_settings from . import generate_isolated_updater, qt_updater, updater @@ -34,26 +35,6 @@ def default_updater_settings() -> dict: } -def default_settings_0_4_1() -> dict: - """Get the default settings for the 0.4.1 Dangerzone release.""" - return { - "save": True, - "archive": True, - "ocr": True, - "ocr_language": "English", - "open": True, - "open_app": None, - "safe_extension": "-safe.pdf", - } - - -def save_settings(tmp_path: Path, settings: dict) -> None: - """Mimic the way Settings save a dictionary to a settings.json file.""" - settings_filename = tmp_path / "settings.json" - with open(settings_filename, "w") as settings_file: - json.dump(settings, settings_file, indent=4) - - def assert_report_equal(report1: UpdateReport, report2: UpdateReport) -> None: assert report1.version == report2.version assert report1.changelog == report2.changelog diff --git a/tests/test_settings.py b/tests/test_settings.py new file mode 100644 index 0000000..148300b --- /dev/null +++ b/tests/test_settings.py @@ -0,0 +1,103 @@ +import collections +import json +import os +from pathlib import Path +from unittest.mock import PropertyMock + +import pytest +from pytest_mock import MockerFixture + +from dangerzone.settings import * + + +def default_settings_0_4_1() -> dict: + """Get the default settings for the 0.4.1 Dangerzone release.""" + return { + "save": True, + "archive": True, + "ocr": True, + "ocr_language": "English", + "open": True, + "open_app": None, + "safe_extension": "-safe.pdf", + } + + +@pytest.fixture +def settings(tmp_path: Path, mocker: MockerFixture) -> Settings: + dz_core = mocker.MagicMock() + type(dz_core).appdata_path = PropertyMock(return_value=tmp_path) + return Settings(dz_core) + + +def save_settings(tmp_path: Path, settings: dict) -> None: + """Mimic the way Settings save a dictionary to a settings.json file.""" + settings_filename = tmp_path / "settings.json" + with open(settings_filename, "w") as settings_file: + json.dump(settings, settings_file, indent=4) + + +def test_no_settings_file_creates_new_one(settings: Settings) -> None: + """Default settings file is created on first run""" + assert os.path.isfile(settings.settings_filename) + new_settings_dict = json.load(open(settings.settings_filename)) + assert sorted(new_settings_dict.items()) == sorted( + settings.generate_default_settings().items() + ) + + +def test_corrupt_settings(tmp_path: Path, mocker: MockerFixture) -> None: + # Set some broken settings file + corrupt_settings_dict = "{:}" + with open(tmp_path / SETTINGS_FILENAME, "w") as settings_file: + settings_file.write(corrupt_settings_dict) + + # Initialize settings + dz_core = mocker.MagicMock() + type(dz_core).appdata_path = PropertyMock(return_value=tmp_path) + settings = Settings(dz_core) + assert os.path.isfile(settings.settings_filename) + + # Check if settings file was reset to the default + new_settings_dict = json.load(open(settings.settings_filename)) + assert new_settings_dict != corrupt_settings_dict + assert sorted(new_settings_dict.items()) == sorted( + settings.generate_default_settings().items() + ) + + +def test_new_default_setting(tmp_path: Path, mocker: MockerFixture) -> None: + # Initialize settings + dz_core = mocker.MagicMock() + type(dz_core).appdata_path = PropertyMock(return_value=tmp_path) + settings = Settings(dz_core) + settings.save() + + # Ensure new default setting is imported into settings + with mocker.patch( + "dangerzone.settings.Settings.generate_default_settings", + return_value={"mock_setting": 1}, + ): + settings2 = Settings(dz_core) + assert settings2.get("mock_setting") == 1 + + +def test_new_settings_added(tmp_path: Path, mocker: MockerFixture) -> None: + # Initialize settings + dz_core = mocker.MagicMock() + type(dz_core).appdata_path = PropertyMock(return_value=tmp_path) + settings = Settings(dz_core) + + # Add new setting + settings.set("new_setting_autosaved", 20, autosave=True) + settings.set( + "new_setting", 10 + ) # XXX has to be afterwards; otherwise this will be saved + + # Simulate new app startup (settings recreation) + settings2 = Settings(dz_core) + + # Check if new setting persisted + assert 20 == settings2.get("new_setting_autosaved") + with pytest.raises(KeyError): + settings2.get("new_setting")