From ff4e35e2d4f2f4164b75ad081d17979c01414042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= <40151420+ldericher@users.noreply.github.com> Date: Wed, 15 Nov 2023 09:23:50 +0100 Subject: [PATCH] add testing for `core.settings.Settings` --- api/ovdashboard_api/core/settings.py | 75 +++++---- api/poetry.lock | 46 ++++++ api/pyproject.toml | 1 + api/test/test_settings.py | 224 +++++++++++++++++++++++++++ 4 files changed, 307 insertions(+), 39 deletions(-) create mode 100644 api/test/test_settings.py diff --git a/api/ovdashboard_api/core/settings.py b/api/ovdashboard_api/core/settings.py index 1cc17e8..e1801af 100644 --- a/api/ovdashboard_api/core/settings.py +++ b/api/ovdashboard_api/core/settings.py @@ -18,12 +18,11 @@ class DAVSettings(BaseModel): Connection to a DAV server. """ - protocol: str | None = None - host: str | None = None - path: str | None = None + protocol: str = "https" + host: str = "example.com" - username: str | None = None - password: str | None = None + username: str = "ovd_user" + password: str = "password" cache_ttl: int = 60 * 10 @@ -33,21 +32,34 @@ class DAVSettings(BaseModel): Combined DAV URL. """ - return f"{self.protocol}://{self.host}{self.path}" + return f"{self.protocol}://{self.host}" -class WebDAVSettings(DAVSettings): +_DAV_DEFAULT = DAVSettings().model_dump() + + +class CalDAVSettings(DAVSettings): + """ + Connection to a CalDAV server. + """ + + path: str = "/remote.php/dav" + + @property + def url(self) -> str: + """ + Combined DAV URL. + """ + + return f"{super().url}{self.path}" + + +class WebDAVSettings(CalDAVSettings): """ Connection to a WebDAV server. """ - protocol: str = "https" - host: str = "example.com" - path: str = "/remote.php/dav" - prefix: str = "/ovdashboard" - - username: str = "ovd_user" - password: str = "password" + path: str = "/remote.php/webdav" config_filename: str = "config.txt" @@ -62,7 +74,10 @@ class WebDAVSettings(DAVSettings): Combined DAV URL. """ - return f"{self.protocol}://{self.host}{self.path}{self.prefix}" + return f"{super().url}{self.prefix}" + + +_WEBDAV_DEFAULT = WebDAVSettings().model_dump() class RedisSettings(BaseModel): @@ -132,7 +147,7 @@ class Settings(BaseSettings): # caldav settings ##### - caldav: DAVSettings = DAVSettings() + caldav: CalDAVSettings = CalDAVSettings() ##### # redis settings @@ -141,37 +156,19 @@ class Settings(BaseSettings): redis: RedisSettings = RedisSettings() @model_validator(mode="before") - @classmethod def validate_dav_settings(cls, data) -> dict[str, Any]: assert isinstance(data, dict) # ensure both settings dicts are created for key in ("webdav", "caldav"): - if key not in data: - data[key] = {} + data[key] = data.get(key, {}) - default_dav = DAVSettings( - protocol="https", - host="example.com", - username="ovdashboard", - password="secret", - ).model_dump() - - for key in default_dav: - # if "webdav" value is not specified, use default - if key not in data["webdav"] or data["webdav"][key] is None: - data["webdav"][key] = default_dav[key] + for key in _DAV_DEFAULT: + # if "webdav" value is not specified, use default value + data["webdav"][key] = data["webdav"].get(key, _WEBDAV_DEFAULT[key]) # if "caldav" value is not specified, use "webdav" value - if key not in data["caldav"] or data["caldav"][key] is None: - data["caldav"][key] = data["webdav"][key] - - # add default "path"s if None - if data["webdav"]["path"] is None: - data["webdav"]["path"] = "/remote.php/webdav" - - if data["caldav"]["path"] is None: - data["caldav"]["path"] = "/remote.php/dav" + data["caldav"][key] = data["caldav"].get(key, data["webdav"][key]) return data diff --git a/api/poetry.lock b/api/poetry.lock index f401e97..eaabfce 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -522,6 +522,17 @@ files = [ {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + [[package]] name = "isort" version = "5.12.0" @@ -787,6 +798,21 @@ files = [ docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] +[[package]] +name = "pluggy" +version = "1.3.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + [[package]] name = "pycodestyle" version = "2.11.1" @@ -961,6 +987,26 @@ files = [ {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, ] +[[package]] +name = "pytest" +version = "7.4.3" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, + {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + [[package]] name = "python-dateutil" version = "2.8.2" diff --git a/api/pyproject.toml b/api/pyproject.toml index c899f68..f18ce19 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -26,6 +26,7 @@ black = "^23.10.1" flake8 = "^6.1.0" flake8-isort = "^6.1.0" types-cachetools = "^5.3.0.6" +pytest = "^7.4.3" [build-system] build-backend = "poetry.core.masonry.api" diff --git a/api/test/test_settings.py b/api/test/test_settings.py new file mode 100644 index 0000000..d94e167 --- /dev/null +++ b/api/test/test_settings.py @@ -0,0 +1,224 @@ +import os + +import pytest + +from ovdashboard_api.core.settings import Settings + + +@pytest.fixture(autouse=True, scope="function") +def patch_settings_env_file(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr(os, "environ", {}) + monkeypatch.delitem(Settings.model_config, "env_file") + + +def test_empty(): + s = Settings.model_validate({}) + + assert s.log_level == "INFO" + assert s.production_mode is False + assert s.ui_directory == "/usr/local/share/ovdashboard_ui/html" + + assert s.ping_host == "1.0.0.0" + assert s.ping_port == 1 + + assert s.openapi_url == "/api/openapi.json" + assert s.docs_url == "/api/docs" + assert s.redoc_url == "/api/redoc" + + # webdav + + assert s.webdav.protocol == "https" + assert s.webdav.host == "example.com" + + assert s.webdav.username == "ovd_user" + assert s.webdav.password == "password" + + assert s.webdav.cache_ttl == 600 + + assert s.webdav.path == "/remote.php/webdav" + + assert s.webdav.config_filename == "config.txt" + + assert s.webdav.disable_check is False + assert s.webdav.retries == 20 + assert s.webdav.retry_delay == 30 + assert s.webdav.prefix == "/ovdashboard" + + # caldav + + assert s.caldav.protocol == "https" + assert s.caldav.host == "example.com" + + assert s.caldav.username == "ovd_user" + assert s.caldav.password == "password" + + assert s.caldav.cache_ttl == 600 + + assert s.caldav.path == "/remote.php/dav" + + +def test_prod(): + s = Settings.model_validate({"production_mode": True}) + + assert s.log_level == "INFO" + assert s.production_mode is True + + assert s.openapi_url is None + assert s.docs_url is None + assert s.redoc_url is None + + +def test_set_caldav(): + s = Settings.model_validate( + { + "caldav": { + "protocol": "cd_protocol", + "host": "cd_host", + "username": "cd_username", + "password": "cd_password", + "cache_ttl": "0", + "path": "cd_path", + } + } + ) + + # webdav + + assert s.webdav.protocol == "https" + assert s.webdav.host == "example.com" + + assert s.webdav.username == "ovd_user" + assert s.webdav.password == "password" + + assert s.webdav.cache_ttl == 600 + + assert s.webdav.path == "/remote.php/webdav" + + assert s.webdav.config_filename == "config.txt" + + assert s.webdav.disable_check is False + assert s.webdav.retries == 20 + assert s.webdav.retry_delay == 30 + assert s.webdav.prefix == "/ovdashboard" + + # caldav + + assert s.caldav.protocol == "cd_protocol" + assert s.caldav.host == "cd_host" + + assert s.caldav.username == "cd_username" + assert s.caldav.password == "cd_password" + + assert s.caldav.cache_ttl == 0 + + assert s.caldav.path == "cd_path" + + +def test_set_webdav(): + s = Settings.model_validate( + { + "webdav": { + "protocol": "wd_protocol", + "host": "wd_host", + "username": "wd_username", + "password": "wd_password", + "cache_ttl": "99", + "path": "wd_path", + "config_filename": "wd_config_filename", + "disable_check": "true", + "retries": "99", + "retry_delay": "99", + "prefix": "wd_prefix", + } + } + ) + + # webdav + + assert s.webdav.protocol == "wd_protocol" + assert s.webdav.host == "wd_host" + + assert s.webdav.username == "wd_username" + assert s.webdav.password == "wd_password" + + assert s.webdav.cache_ttl == 99 + + assert s.webdav.path == "wd_path" + + assert s.webdav.config_filename == "wd_config_filename" + + assert s.webdav.disable_check is True + assert s.webdav.retries == 99 + assert s.webdav.retry_delay == 99 + assert s.webdav.prefix == "wd_prefix" + + # caldav + + assert s.caldav.protocol == "wd_protocol" + assert s.caldav.host == "wd_host" + + assert s.caldav.username == "wd_username" + assert s.caldav.password == "wd_password" + + assert s.caldav.cache_ttl == 99 + + assert s.caldav.path == "/remote.php/dav" + + +def test_set_caldav_webdav(): + s = Settings.model_validate( + { + "webdav": { + "protocol": "wd_protocol", + "host": "wd_host", + "username": "wd_username", + "password": "wd_password", + "cache_ttl": "99", + "path": "wd_path", + "config_filename": "wd_config_filename", + "disable_check": "true", + "retries": "99", + "retry_delay": "99", + "prefix": "wd_prefix", + }, + "caldav": { + "protocol": "cd_protocol", + "host": "cd_host", + "username": "cd_username", + "password": "cd_password", + "cache_ttl": "0", + "path": "cd_path", + }, + } + ) + + # webdav + + assert s.webdav.protocol == "wd_protocol" + assert s.webdav.host == "wd_host" + + assert s.webdav.username == "wd_username" + assert s.webdav.password == "wd_password" + + assert s.webdav.cache_ttl == 99 + + assert s.webdav.path == "wd_path" + + assert s.webdav.config_filename == "wd_config_filename" + + assert s.webdav.disable_check is True + assert s.webdav.retries == 99 + assert s.webdav.retry_delay == 99 + assert s.webdav.prefix == "wd_prefix" + + # caldav + + assert s.caldav.protocol == "cd_protocol" + assert s.caldav.host == "cd_host" + + assert s.caldav.username == "cd_username" + assert s.caldav.password == "cd_password" + + assert s.caldav.cache_ttl == 0 + + assert s.caldav.path == "cd_path"