"""Jev 감정 공급자 설정 계약.""" from __future__ import annotations import os import unittest from unittest.mock import AsyncMock, patch from pydantic import SecretStr, ValidationError from .config import Settings from . import main class JevSettingsTest(unittest.TestCase): def test_defaults_keep_legacy_provider(self) -> None: with patch.dict( os.environ, { "VIGNETTE_CLIENT_AFFECT_PROVIDER": "legacy", "TYPESAFE_API_KEY": "", "OPENROUTER_API_KEY": "", }, clear=False, ): configured = Settings(_env_file=None) self.assertEqual("legacy", configured.client_affect_provider) self.assertEqual("openrouter", configured.jev_provider) self.assertEqual("~typesafe/jev-latest", configured.jev_model) self.assertEqual(1.2, configured.jev_timeout_seconds) self.assertEqual(0.65, configured.jev_min_confidence) def test_default_openrouter_jev_requires_its_own_key(self) -> None: with self.assertRaisesRegex(ValidationError, "OPENROUTER_API_KEY"): Settings( _env_file=None, client_affect_provider="jev", typesafe_api_key=SecretStr("typesafe-only-key"), openrouter_api_key=SecretStr(""), ) def test_explicit_typesafe_jev_requires_typesafe_key(self) -> None: with self.assertRaisesRegex(ValidationError, "TYPESAFE_API_KEY"): Settings( _env_file=None, client_affect_provider="jev", jev_provider="typesafe", openrouter_api_key=SecretStr("openrouter-only-key"), typesafe_api_key=SecretStr(""), ) def test_jev_environment_aliases_and_limits_apply(self) -> None: with patch.dict( os.environ, { "VIGNETTE_CLIENT_AFFECT_PROVIDER": "jev", "VIGNETTE_JEV_PROVIDER": "openrouter", "OPENROUTER_API_KEY": "unit-test-openrouter-key", "VIGNETTE_JEV_MODEL": "~typesafe/jev-latest", "VIGNETTE_JEV_TIMEOUT_SECONDS": "0.4", "VIGNETTE_JEV_MIN_CONFIDENCE": "0.8", }, clear=False, ): configured = Settings(_env_file=None) self.assertEqual("jev", configured.client_affect_provider) self.assertEqual("openrouter", configured.jev_provider) self.assertEqual( "unit-test-openrouter-key", configured.openrouter_api_key.get_secret_value(), ) self.assertEqual(0.4, configured.jev_timeout_seconds) self.assertEqual(0.8, configured.jev_min_confidence) def test_timeout_bounds_are_enforced(self) -> None: with self.assertRaises(ValidationError): Settings(_env_file=None, jev_timeout_seconds=0.09) with self.assertRaises(ValidationError): Settings(_env_file=None, jev_timeout_seconds=10.1) class JevHealthStatusTest(unittest.IsolatedAsyncioTestCase): async def test_health_exposes_configuration_without_claiming_live_readiness(self) -> None: with ( patch.object(main, "healthcheck", AsyncMock(return_value=True)), patch.object( main.engine_client, "health_detail", AsyncMock(return_value={"ok": True}), ), ): response = await main.health() self.assertEqual(main.settings.client_affect_provider, response["client_affect_provider"]) self.assertEqual(main.settings.jev_model, response["jev"]["model"]) self.assertEqual(main.settings.jev_provider, response["jev"]["provider"]) self.assertIn("configured", response["jev"]) self.assertFalse(response["jev"]["live_verified"]) if __name__ == "__main__": unittest.main()