from types import SimpleNamespace from typing import Dict import pytest from sqlalchemy.orm import Session from models.application_setting import ApplicationSetting from services import settings as settings_service from services.settings import CSS_COLOR_DEFAULTS @pytest.fixture(name="clean_env") def fixture_clean_env(monkeypatch: pytest.MonkeyPatch) -> Dict[str, str]: """Provide an isolated environment mapping for tests.""" env: Dict[str, str] = {} monkeypatch.setattr(settings_service, "os", SimpleNamespace(environ=env)) return env def test_css_key_to_env_var_formatting(): assert ( settings_service.css_key_to_env_var("--color-background") == "CALMINER_THEME_COLOR_BACKGROUND" ) assert ( settings_service.css_key_to_env_var("--color-primary-stronger") == "CALMINER_THEME_COLOR_PRIMARY_STRONGER" ) @pytest.mark.parametrize( "env_key,env_value", [ ("--color-background", "#ffffff"), ("--color-primary", "rgb(10, 20, 30)"), ("--color-accent", "rgba(1,2,3,0.5)"), ("--color-text-secondary", "hsla(210, 40%, 40%, 1)"), ], ) def test_read_css_color_env_overrides_valid_values( clean_env, env_key, env_value ): env_var = settings_service.css_key_to_env_var(env_key) clean_env[env_var] = env_value overrides = settings_service.read_css_color_env_overrides(clean_env) assert overrides[env_key] == env_value @pytest.mark.parametrize( "invalid_value", [ "", # empty "not-a-color", # arbitrary string "#12", # short hex "rgb(1,2)", # malformed rgb ], ) def test_read_css_color_env_overrides_invalid_values_raise( clean_env, invalid_value ): env_var = settings_service.css_key_to_env_var("--color-background") clean_env[env_var] = invalid_value with pytest.raises(ValueError): settings_service.read_css_color_env_overrides(clean_env) def test_read_css_color_env_overrides_ignores_missing(clean_env): overrides = settings_service.read_css_color_env_overrides(clean_env) assert overrides == {} def test_list_css_env_override_rows_returns_structured_data(clean_env): clean_env[settings_service.css_key_to_env_var("--color-primary")] = ( "#123456" ) rows = settings_service.list_css_env_override_rows(clean_env) assert rows == [ { "css_key": "--color-primary", "env_var": settings_service.css_key_to_env_var("--color-primary"), "value": "#123456", } ] def test_normalize_color_value_strips_and_validates(): assert settings_service._normalize_color_value(" #abcdef ") == "#abcdef" with pytest.raises(ValueError): settings_service._normalize_color_value(123) # type: ignore[arg-type] with pytest.raises(ValueError): settings_service._normalize_color_value(" ") with pytest.raises(ValueError): settings_service._normalize_color_value("#12") def test_ensure_css_color_settings_creates_defaults(db_session: Session): settings_service.ensure_css_color_settings(db_session) stored = { record.key: record.value for record in db_session.query(ApplicationSetting).all() } assert set(stored.keys()) == set(CSS_COLOR_DEFAULTS.keys()) assert stored == CSS_COLOR_DEFAULTS def test_update_css_color_settings_persists_changes(db_session: Session): settings_service.ensure_css_color_settings(db_session) updated = settings_service.update_css_color_settings( db_session, {"--color-background": "#000000", "--color-accent": "#abcdef"}, ) assert updated["--color-background"] == "#000000" assert updated["--color-accent"] == "#abcdef" stored = { record.key: record.value for record in db_session.query(ApplicationSetting).all() } assert stored["--color-background"] == "#000000" assert stored["--color-accent"] == "#abcdef" def test_get_css_color_settings_respects_env_overrides( db_session: Session, clean_env: Dict[str, str] ): settings_service.ensure_css_color_settings(db_session) override_value = "#112233" clean_env[settings_service.css_key_to_env_var("--color-background")] = ( override_value ) values = settings_service.get_css_color_settings(db_session) assert values["--color-background"] == override_value db_value = ( db_session.query(ApplicationSetting) .filter_by(key="--color-background") .one() .value ) assert db_value != override_value