"""Tests the config provers.""" import json from pathlib import Path from unittest.mock import mock_open, patch import pytest from _pytest.monkeypatch import MonkeyPatch from aki_prj23_transparenzregister.config.config_providers import ( EnvironmentConfigProvider, JsonFileConfigProvider, get_config_provider, ) from aki_prj23_transparenzregister.config.config_template import ( PostgreConnectionString, SQLiteConnectionString, ) def test_json_provider_init_fail() -> None: """Tests the file not found error if an unknown filepath is given for the JsonFileConfigProvider.""" with pytest.raises(FileNotFoundError): JsonFileConfigProvider("file-that-does-not-exist") def test_json_provider_init_no_json() -> None: """Tests if a non json file throws the correct error.""" with patch("os.path.isfile") as mock_isfile, patch( "builtins.open", mock_open(read_data="fh1da23of4!hdo4s") ): mock_isfile.return_value = True with pytest.raises(TypeError): JsonFileConfigProvider("non-json-file") def test_json_provider_init() -> None: """Tests the JsonFileConfigProvider creation.""" data = {"hello": "world"} input_data = json.dumps(data) with patch("os.path.isfile") as mock_isfile, patch( "builtins.open", mock_open(read_data=input_data) ): mock_isfile.return_value = True provider = JsonFileConfigProvider("someWhere") assert provider.__data__ == data @pytest.mark.parametrize("as_path", [True, False]) def test_get_config_provider_json(as_path: bool) -> None: """Tests the JsonFileConfigProvider creation by the factory method.""" data = {"hello": "world"} input_data = json.dumps(data) with patch("os.path.isfile") as mock_isfile: mock_isfile.return_value = True with patch("builtins.open", mock_open(read_data=input_data)): config_provider = get_config_provider( Path("some_where.json") if as_path else "some_where.json" ) assert isinstance(config_provider, JsonFileConfigProvider) assert config_provider.__data__ == data @pytest.mark.parametrize("args", ["ENV", "env", "", None, "PYTHON_", "ELSE_"]) def test_get_config_provider_env(args: str | None) -> None: env_provider = get_config_provider(args) assert isinstance(env_provider, EnvironmentConfigProvider) def test_get_config_provider_fail() -> None: with pytest.raises(ValueError, match="No configuration found"): get_config_provider("something-else") def test_json_provider_get_sql() -> None: """Tests if the config provider can return the postgre config string.""" data = { "postgres": { "username": "user", "password": "pass", "host": "localhost", "database": "postgres", "port": 420, } } input_data = json.dumps(data) with patch("os.path.isfile") as mock_isfile: mock_isfile.return_value = True with patch("builtins.open", mock_open(read_data=input_data)): config = JsonFileConfigProvider("someWhere").get_sql_connection_string() assert isinstance(config, PostgreConnectionString) assert config.username == data["postgres"]["username"] assert config.password == data["postgres"]["password"] assert config.host == data["postgres"]["host"] assert config.database == data["postgres"]["database"] assert config.port == data["postgres"]["port"] assert isinstance(str(config), str) assert "Mongo" not in str(config) assert "Postgre" in str(config) assert isinstance(str(JsonFileConfigProvider("someWhere")), str) assert str(config) in str(JsonFileConfigProvider("someWhere")) assert "Mongo" not in str(JsonFileConfigProvider("someWhere")) @pytest.mark.parametrize("additional_data", [True, False]) def test_json_provider_get_sqlit3(additional_data: bool) -> None: """Tests if the config provider can return the sqlite config string.""" data = { "sqlite": "some.db", } if additional_data: data |= { "postgres": { # type: ignore "username": "user", "password": "pass", "host": "localhost", "database": "postgres", "port": 420, } } input_data = json.dumps(data) with patch("os.path.isfile") as mock_isfile: mock_isfile.return_value = True with patch("builtins.open", mock_open(read_data=input_data)): assert JsonFileConfigProvider( "someWhere" ).get_sql_connection_string() == SQLiteConnectionString("some.db") def test_json_provider_get_mongo() -> None: """Tests the JsonConfigProvider for the mongo db.""" data = { "mongo": { "username": "user", "password": "pass", "host": "localhost", "database": "mongo", "port": 420, } } input_data = json.dumps(data) with patch("os.path.isfile") as mock_isfile: mock_isfile.return_value = True with patch("builtins.open", mock_open(read_data=input_data)): config = JsonFileConfigProvider("someWhere").get_mongo_connection_string() assert config.username == data["mongo"]["username"] assert config.password == data["mongo"]["password"] assert config.hostname == data["mongo"]["host"] assert config.database == data["mongo"]["database"] assert config.port == data["mongo"]["port"] assert isinstance(str(config), str) assert "Mongo" in str(config) assert "Postgre" not in str(config) assert isinstance(str(JsonFileConfigProvider("someWhere")), str) assert str(config) in str(JsonFileConfigProvider("someWhere")) assert "Postgre" not in str(JsonFileConfigProvider("someWhere")) def test_env_provider_constructor(monkeypatch: MonkeyPatch) -> None: env_configs = {"PYTHON_TEST": "test", "NOT_PYTHON_TEST": ""} for key, value in env_configs.items(): monkeypatch.setenv(key, value) provider = EnvironmentConfigProvider() assert "TEST" in provider.__data__ assert provider.__data__["TEST"] == "test" assert "NOT_PYTHON_TEST" not in provider.__data__ def test_env_provider_postgres(monkeypatch: MonkeyPatch) -> None: env_configs = { "PYTHON_POSTGRES_USERNAME": "postgres-user", "PYTHON_POSTGRES_PASSWORD": "postgres-pw", "PYTHON_POSTGRES_HOST": "localhost", "PYTHON_POSTGRES_DATABASE": "postgres", "PYTHON_POSTGRES_PORT": "5432", } for env_config in env_configs.items(): monkeypatch.setenv(*env_config) provider = EnvironmentConfigProvider() conn_string = provider.get_sql_connection_string() assert isinstance(conn_string, PostgreConnectionString) assert conn_string.database == env_configs["PYTHON_POSTGRES_DATABASE"] assert conn_string.host == env_configs["PYTHON_POSTGRES_HOST"] assert conn_string.password == env_configs["PYTHON_POSTGRES_PASSWORD"] assert conn_string.port == env_configs["PYTHON_POSTGRES_PORT"] assert conn_string.username == env_configs["PYTHON_POSTGRES_USERNAME"] @pytest.mark.parametrize("additional_args", [True, False]) def test_env_provider_sqlite(additional_args: bool, monkeypatch: MonkeyPatch) -> None: env_configs = {"PYTHON_SQLITE_PATH": "some.db"} if additional_args: env_configs |= { "PYTHON_POSTGRES_USERNAME": "postgres-user", "PYTHON_POSTGRES_PASSWORD": "postgres-pw", "PYTHON_POSTGRES_HOST": "localhost", "PYTHON_POSTGRES_DATABASE": "postgres", "PYTHON_POSTGRES_PORT": "5432", } for env_config in env_configs.items(): monkeypatch.setenv(*env_config) provider = EnvironmentConfigProvider() assert provider.get_sql_connection_string() == SQLiteConnectionString("some.db") @pytest.mark.parametrize("prefix", ["", "NON_PYTHON", "ELSE"]) def test_env_provider_mongodb(prefix: str, monkeypatch: MonkeyPatch) -> None: env_data = { "MONGO_USERNAME": "username", "MONGO_HOST": "localhost", "MONGO_PASSWORD": "password", "MONGO_PORT": 27017, "MONGO_DATABASE": "transparenzregister", } for key, value in env_data.items(): monkeypatch.setenv(f"{prefix if prefix else 'PYTHON_'}{key}", str(value)) if prefix: provider = EnvironmentConfigProvider(prefix) else: provider = EnvironmentConfigProvider() provider.__data__ = env_data conn_string = provider.get_mongo_connection_string() assert conn_string.database == env_data["MONGO_DATABASE"] assert conn_string.hostname == env_data["MONGO_HOST"] assert conn_string.password == env_data["MONGO_PASSWORD"] assert conn_string.port == env_data["MONGO_PORT"] assert conn_string.username == env_data["MONGO_USERNAME"]