"""Tests for configuration management module Tests for KBSettings and get_settings function using pydantic-settings. """ import os import pytest from pathlib import Path from unittest.mock import patch, MagicMock from pydantic import ValidationError as PydanticValidationError from kb_workflow.pipeline.config import KBSettings, get_settings class TestKBSettings: """Tests for KBSettings class""" def test_kbsettings_has_base_path_field(self): """Test KBSettings has base_path field""" settings = KBSettings( base_path="/tmp/kb", archive_path="/tmp/archive" ) assert settings.base_path == "/tmp/kb" def test_kbsettings_has_archive_path_field(self): """Test KBSettings has archive_path field""" settings = KBSettings( base_path="/tmp/kb", archive_path="/tmp/archive" ) assert settings.archive_path == "/tmp/archive" def test_kbsettings_optional_fields_can_be_empty(self): """Test optional fields accept empty string when explicitly set""" settings = KBSettings( base_path="/tmp/kb", archive_path="/tmp/archive", git_root="", git_user="", git_email="" ) assert settings.git_root == "" assert settings.git_user == "" assert settings.git_email == "" def test_kbsettings_hf_token_is_secret(self): """Test hf_token is SecretStr type""" from pydantic import SecretStr settings = KBSettings( base_path="/tmp/kb", archive_path="/tmp/archive", hf_token="secret_token" ) assert isinstance(settings.hf_token, SecretStr) def test_kbsettings_zhihu_cookie_is_secret(self): """Test zhihu_cookie is SecretStr type""" from pydantic import SecretStr settings = KBSettings( base_path="/tmp/kb", archive_path="/tmp/archive", zhihu_cookie="secret_cookie" ) assert isinstance(settings.zhihu_cookie, SecretStr) def test_kbsettings_missing_base_path_raises_error(self): """Test missing base_path raises ValidationError""" # Clear env vars that might provide values with patch.dict(os.environ, {}, clear=True): with pytest.raises(PydanticValidationError) as exc_info: KBSettings(archive_path="/tmp/archive", _env_file=None) assert "base_path" in str(exc_info.value).lower() def test_kbsettings_missing_archive_path_raises_error(self): """Test missing archive_path raises ValidationError""" # Clear env vars that might provide values with patch.dict(os.environ, {}, clear=True): with pytest.raises(PydanticValidationError) as exc_info: KBSettings(base_path="/tmp/kb", _env_file=None) assert "archive_path" in str(exc_info.value).lower() def test_kbsettings_can_set_optional_fields(self): """Test optional fields can be set""" settings = KBSettings( base_path="/tmp/kb", archive_path="/tmp/archive", git_root="/tmp/repo", git_user="testuser", git_email="test@example.com" ) assert settings.git_root == "/tmp/repo" assert settings.git_user == "testuser" assert settings.git_email == "test@example.com" class TestGetSettings: """Tests for get_settings function""" def test_get_settings_returns_kbsettings(self): """Test get_settings returns KBSettings instance""" with patch.dict(os.environ, { "KB_BASE_PATH": "/tmp/kb", "KB_ARCHIVE_PATH": "/tmp/archive" }, clear=False): # Clear cache before test get_settings.cache_clear() settings = get_settings() assert isinstance(settings, KBSettings) def test_get_settings_returns_singleton(self): """Test get_settings returns same instance (cached)""" with patch.dict(os.environ, { "KB_BASE_PATH": "/tmp/kb", "KB_ARCHIVE_PATH": "/tmp/archive" }, clear=False): # Clear cache before test get_settings.cache_clear() settings1 = get_settings() settings2 = get_settings() assert settings1 is settings2 def test_get_settings_uses_env_vars_with_prefix(self): """Test get_settings reads from KB_ prefixed env vars""" with patch.dict(os.environ, { "KB_BASE_PATH": "/custom/kb", "KB_ARCHIVE_PATH": "/custom/archive" }, clear=False): # Clear cache before test get_settings.cache_clear() settings = get_settings() assert settings.base_path == "/custom/kb" assert settings.archive_path == "/custom/archive" class TestKBSettingsEnvFile: """Tests for KBSettings env file loading""" def test_kbsettings_model_config_has_env_file(self): """Test KBSettings model_config has env_file setting""" assert hasattr(KBSettings, "model_config") assert "env_file" in KBSettings.model_config def test_kbsettings_model_config_has_env_prefix(self): """Test KBSettings model_config has env_prefix setting""" assert KBSettings.model_config.get("env_prefix") == "KB_" def test_kbsettings_model_config_ignores_extra(self): """Test KBSettings model_config ignores extra fields""" assert KBSettings.model_config.get("extra") == "ignore"