import tempfile import unittest import os from pathlib import Path from unittest.mock import patch import nlprog.config as config class ConfigTests(unittest.TestCase): def test_parse_config_value(self): self.assertTrue(config.parse_config_value("require_confirmation", "true")) self.assertEqual(config.parse_config_value("json_repair_retries", "3"), 3) self.assertEqual(config.parse_config_value("temperature", "0.5"), 0.5) self.assertIsNone(config.parse_config_value("base_url", "null")) def test_set_config_value_uses_temp_config_file(self): with tempfile.TemporaryDirectory() as tmp: config_file = Path(tmp) / "config.json" with patch.object(config, "CONFIG_DIR", Path(tmp)), patch.object(config, "CONFIG_FILE", config_file): config.write_default_config() config.set_config_value("provider", "opencode") data = config.read_config_file() self.assertEqual(data["provider"], "opencode") def test_active_model_overrides_loaded_config(self): with tempfile.TemporaryDirectory() as tmp: config_file = Path(tmp) / "config.json" with patch.object(config, "CONFIG_DIR", Path(tmp)): with patch.object(config, "CONFIG_FILE", config_file): with patch.dict(os.environ, {}, clear=True): config.write_default_config() config.add_model( "deepseek", provider="openai-compatible", model="deepseek-chat", base_url="https://api.deepseek.com/v1", api_key_env="DEEPSEEK_API_KEY", activate=True, ) loaded = config.load_config() self.assertEqual(loaded.provider, "openai-compatible") self.assertEqual(loaded.model, "deepseek-chat") self.assertEqual(loaded.base_url, "https://api.deepseek.com/v1") self.assertEqual(loaded.api_key_env, "DEEPSEEK_API_KEY") def test_legacy_config_without_active_model_still_loads_top_level_values(self): with tempfile.TemporaryDirectory() as tmp: config_file = Path(tmp) / "config.json" with patch.object(config, "CONFIG_DIR", Path(tmp)): with patch.object(config, "CONFIG_FILE", config_file): with patch.dict(os.environ, {}, clear=True): config.write_config_file( { "provider": "opencode", "model": "", "opencode_command": "opencode", } ) loaded = config.load_config() active, models = config.list_models() self.assertEqual(loaded.provider, "opencode") self.assertEqual(loaded.model, "") self.assertEqual(active, "current") self.assertEqual(models["current"]["provider"], "opencode") def test_model_registry_use_and_remove(self): with tempfile.TemporaryDirectory() as tmp: config_file = Path(tmp) / "config.json" with patch.object(config, "CONFIG_DIR", Path(tmp)), patch.object(config, "CONFIG_FILE", config_file): config.write_default_config() config.add_model("codex", provider="opencode", activate=True) config.add_model("mock2", provider="mock", model="mock-model") active, models = config.list_models() self.assertEqual(active, "codex") self.assertIn("codex", models) self.assertIn("mock2", models) with self.assertRaises(ValueError): config.remove_model("codex") config.use_model("mock2") config.remove_model("codex") _, models = config.list_models() self.assertNotIn("codex", models) if __name__ == "__main__": unittest.main()