"""Tests for app.config — Settings model and environment variable overrides.""" import os import pytest from app.config import Settings def _clear_kmn_env(monkeypatch): """Remove all KMTN_ prefixed env vars so Settings reads pure defaults.""" keys = [k for k in os.environ if k.startswith("KMTN_")] for k in keys: monkeypatch.delenv(k, raising=False) class TestSettingsDefaults: """Verify Settings defaults match documented behavior.""" def test_default_database_url(self, monkeypatch): _clear_kmn_env(monkeypatch) settings = Settings() assert "postgresql" in settings.DATABASE_URL assert "kmountain" in settings.DATABASE_URL def test_default_env_is_development(self, monkeypatch): _clear_kmn_env(monkeypatch) settings = Settings() assert settings.ENV == "development" def test_default_jwt_expire_minutes(self, monkeypatch): _clear_kmn_env(monkeypatch) settings = Settings() assert settings.JWT_EXPIRE_MINUTES == 1440 def test_default_download_token_minutes(self, monkeypatch): _clear_kmn_env(monkeypatch) settings = Settings() assert settings.DOWNLOAD_TOKEN_MINUTES == 10 def test_default_cors_origins(self, monkeypatch): _clear_kmn_env(monkeypatch) settings = Settings() assert "http://localhost:4200" in settings.CORS_ORIGINS def test_empty_admin_credentials_by_default(self, monkeypatch): _clear_kmn_env(monkeypatch) settings = Settings() assert settings.ADMIN_USERNAME == "" assert settings.ADMIN_PASSWORD == "" class TestSettingsEnvOverride: """Verify KMTN_ prefixed env vars override defaults.""" def test_database_url_from_env(self, monkeypatch): monkeypatch.setenv("KMTN_DATABASE_URL", "sqlite+aiosqlite:///test.db") settings = Settings() assert settings.DATABASE_URL == "sqlite+aiosqlite:///test.db" def test_env_from_env(self, monkeypatch): monkeypatch.setenv("KMTN_ENV", "production") settings = Settings() assert settings.ENV == "production" def test_jwt_secret_from_env(self, monkeypatch): monkeypatch.setenv("KMTN_JWT_SECRET_KEY", "my-custom-secret") settings = Settings() assert settings.JWT_SECRET_KEY == "my-custom-secret" def test_jwt_expire_override(self, monkeypatch): monkeypatch.setenv("KMTN_JWT_EXPIRE_MINUTES", "60") settings = Settings() assert settings.JWT_EXPIRE_MINUTES == 60 def test_logs_dir_override(self, monkeypatch): monkeypatch.setenv("KMTN_LOGS_DIR", "/custom/logs") settings = Settings() assert settings.LOGS_DIR == "/custom/logs" def test_geolite2_path_override(self, monkeypatch): monkeypatch.setenv("KMTN_GEOLITE2_DB_PATH", "/custom/geo.mmdb") settings = Settings() assert settings.GEOLITE2_DB_PATH == "/custom/geo.mmdb" def test_theme_json_path_override(self, monkeypatch): monkeypatch.setenv("KMTN_THEME_JSON_PATH", "/custom/theme.json") settings = Settings() assert settings.THEME_JSON_PATH == "/custom/theme.json" def test_admin_credentials_from_env(self, monkeypatch): monkeypatch.setenv("KMTN_ADMIN_USERNAME", "admin") monkeypatch.setenv("KMTN_ADMIN_PASSWORD", "secure123") settings = Settings() assert settings.ADMIN_USERNAME == "admin" assert settings.ADMIN_PASSWORD == "secure123" def test_website_url_override(self, monkeypatch): monkeypatch.setenv("KMTN_WEBSITE_URL", "https://example.com") settings = Settings() assert settings.WEBSITE_URL == "https://example.com" def test_static_upstream_url_override(self, monkeypatch): monkeypatch.setenv("KMTN_STATIC_UPSTREAM_URL", "http://frontend:80") settings = Settings() assert settings.STATIC_UPSTREAM_URL == "http://frontend:80" def test_cors_origins_override(self, monkeypatch): # pydantic-settings parses JSON lists for list[str] fields monkeypatch.setenv("KMTN_CORS_ORIGINS", '["https://example.com"]') settings = Settings() assert settings.CORS_ORIGINS == ["https://example.com"] def test_kmn_prefix_is_required(self, monkeypatch): """Non-prefixed env vars should NOT override settings.""" monkeypatch.setenv("JWT_SECRET_KEY", "should-not-apply") settings = Settings() assert settings.JWT_SECRET_KEY != "should-not-apply"