import pytest import importlib import yaml from app.config import EmbeddingProvider @pytest.fixture def tmp_config_file(tmp_path): """ Creates a temporary config.yaml file and returns its path. Corrected the 'provider' value to be lowercase 'mock' to match the Enum. """ config_content = { "application": { "project_name": "Test Project from YAML", "log_level": "WARNING" }, "llm_providers": {"deepseek_model_name": "deepseek-from-yaml"}, "embedding_provider": { # This value must be lowercase to match the Pydantic Enum member "provider": "mock", "model_name": "embedding-model-from-yaml" } } config_path = tmp_path / "test_config.yaml" with open(config_path, 'w') as f: yaml.dump(config_content, f) return str(config_path) @pytest.fixture(autouse=True) def mock_api_keys(monkeypatch): """ Automatically sets mock API keys for all tests to prevent the ValueError from being raised in config.py. """ monkeypatch.setenv("DEEPSEEK_API_KEY", "mock_deepseek_key") monkeypatch.setenv("GEMINI_API_KEY", "mock_gemini_key") # Also set a default EMBEDDING_API_KEY for completeness monkeypatch.setenv("EMBEDDING_API_KEY", "mock_embedding_key") def test_env_var_overrides_yaml(monkeypatch, tmp_config_file): """Tests that an env var overrides YAML for DEEPSEEK_MODEL_NAME.""" monkeypatch.setenv("CONFIG_PATH", tmp_config_file) monkeypatch.setenv("DEEPSEEK_MODEL_NAME", "deepseek-from-env") from app import config importlib.reload(config) assert config.settings.DEEPSEEK_MODEL_NAME == "deepseek-from-env" def test_env_var_overrides_default(monkeypatch): """Tests that env var overrides hardcoded default when YAML is missing.""" monkeypatch.setenv("CONFIG_PATH", "/path/that/does/not/exist.yaml") monkeypatch.setenv("DEEPSEEK_MODEL_NAME", "deepseek-from-env") from app import config importlib.reload(config) assert config.settings.DEEPSEEK_MODEL_NAME == "deepseek-from-env" def test_hardcoded_default_is_used_last(monkeypatch): """Tests fallback to hardcoded default if ENV and YAML missing.""" monkeypatch.setenv("CONFIG_PATH", "/path/that/does/not/exist.yaml") monkeypatch.delenv("DEEPSEEK_MODEL_NAME", raising=False) from app import config importlib.reload(config) assert config.settings.DEEPSEEK_MODEL_NAME == "deepseek-chat" # -------------------------- # ✅ LOG_LEVEL TESTS # -------------------------- def test_log_level_env_overrides_yaml(monkeypatch, tmp_config_file): """Tests LOG_LEVEL: ENV > YAML > default.""" monkeypatch.setenv("CONFIG_PATH", tmp_config_file) monkeypatch.setenv("LOG_LEVEL", "DEBUG") from app import config importlib.reload(config) assert config.settings.LOG_LEVEL == "DEBUG" def test_log_level_yaml_over_default(monkeypatch, tmp_config_file): """Tests LOG_LEVEL uses YAML when ENV is not set.""" monkeypatch.setenv("CONFIG_PATH", tmp_config_file) monkeypatch.delenv("LOG_LEVEL", raising=False) from app import config importlib.reload(config) assert config.settings.LOG_LEVEL == "WARNING" def test_log_level_default_used(monkeypatch): """Tests LOG_LEVEL falls back to default when neither ENV nor YAML set.""" monkeypatch.setenv("CONFIG_PATH", "/does/not/exist.yaml") monkeypatch.delenv("LOG_LEVEL", raising=False) from app import config importlib.reload(config) assert config.settings.LOG_LEVEL == "INFO" # -------------------------- # ✅ EMBEDDING PROVIDER TESTS # -------------------------- def test_embedding_provider_env_overrides_yaml(monkeypatch, tmp_config_file): """Tests EMBEDDING_PROVIDER: ENV > YAML > default.""" monkeypatch.setenv("CONFIG_PATH", tmp_config_file) monkeypatch.setenv("EMBEDDING_PROVIDER", "GOOGLE_GENAI") from app import config importlib.reload(config) assert config.settings.EMBEDDING_PROVIDER == EmbeddingProvider.GOOGLE_GENAI def test_embedding_provider_yaml_overrides_default(monkeypatch, tmp_config_file): """Tests EMBEDDING_PROVIDER uses YAML when ENV is not set.""" monkeypatch.setenv("CONFIG_PATH", tmp_config_file) monkeypatch.delenv("EMBEDDING_PROVIDER", raising=False) from app import config importlib.reload(config) assert config.settings.EMBEDDING_PROVIDER == EmbeddingProvider.MOCK def test_embedding_provider_default_used(monkeypatch): """Tests EMBEDDING_PROVIDER falls back to default when neither ENV nor YAML set.""" monkeypatch.setenv("CONFIG_PATH", "/does/not/exist.yaml") monkeypatch.delenv("EMBEDDING_PROVIDER", raising=False) from app import config importlib.reload(config) assert config.settings.EMBEDDING_PROVIDER == EmbeddingProvider.GOOGLE_GENAI # -------------------------- # ✅ EMBEDDING MODEL NAME TESTS # -------------------------- def test_embedding_model_name_env_overrides_yaml(monkeypatch, tmp_config_file): """Tests EMBEDDING_MODEL_NAME: ENV > YAML > default.""" monkeypatch.setenv("CONFIG_PATH", tmp_config_file) monkeypatch.setenv("EMBEDDING_MODEL_NAME", "embedding-model-from-env") from app import config importlib.reload(config) assert config.settings.EMBEDDING_MODEL_NAME == "embedding-model-from-env" def test_embedding_model_name_yaml_overrides_default(monkeypatch, tmp_config_file): """Tests EMBEDDING_MODEL_NAME uses YAML when ENV is not set.""" monkeypatch.setenv("CONFIG_PATH", tmp_config_file) monkeypatch.delenv("EMBEDDING_MODEL_NAME", raising=False) from app import config importlib.reload(config) assert config.settings.EMBEDDING_MODEL_NAME == "embedding-model-from-yaml" def test_embedding_model_name_default_used(monkeypatch): """Tests EMBEDDING_MODEL_NAME falls back to default when neither ENV nor YAML set.""" monkeypatch.setenv("CONFIG_PATH", "/does/not/exist.yaml") from app import config importlib.reload(config) assert config.settings.EMBEDDING_MODEL_NAME == "models/text-embedding-004"