"""Config and runtime tests.""" from __future__ import annotations import os import tempfile import unittest from pathlib import Path from unittest.mock import patch from coinhunter.config import ensure_init_files, get_binance_credentials, load_config, load_env_file from coinhunter.runtime import get_runtime_paths class ConfigRuntimeTestCase(unittest.TestCase): def test_init_files_created_in_coinhunter_home(self): with tempfile.TemporaryDirectory() as tmp_dir, patch.dict(os.environ, {"COINHUNTER_HOME": str(Path(tmp_dir) / "home")}, clear=False): paths = get_runtime_paths() payload = ensure_init_files(paths) self.assertTrue(paths.config_file.exists()) self.assertTrue(paths.env_file.exists()) self.assertTrue(paths.logs_dir.exists()) self.assertEqual(payload["root"], str(paths.root)) def test_load_config_and_env(self): with tempfile.TemporaryDirectory() as tmp_dir, patch.dict( os.environ, {"COINHUNTER_HOME": str(Path(tmp_dir) / "home")}, clear=False, ): paths = get_runtime_paths() ensure_init_files(paths) paths.env_file.write_text("BINANCE_API_KEY=abc\nBINANCE_API_SECRET=def\n", encoding="utf-8") config = load_config(paths) loaded = load_env_file(paths) self.assertEqual(config["market"]["default_quote"], "USDT") self.assertEqual(loaded["BINANCE_API_KEY"], "abc") self.assertEqual(os.environ["BINANCE_API_SECRET"], "def") def test_env_file_overrides_existing_environment(self): with tempfile.TemporaryDirectory() as tmp_dir, patch.dict( os.environ, {"COINHUNTER_HOME": str(Path(tmp_dir) / "home"), "BINANCE_API_KEY": "old_key"}, clear=False, ): paths = get_runtime_paths() ensure_init_files(paths) paths.env_file.write_text("BINANCE_API_KEY=new_key\nBINANCE_API_SECRET=new_secret\n", encoding="utf-8") load_env_file(paths) self.assertEqual(os.environ["BINANCE_API_KEY"], "new_key") self.assertEqual(os.environ["BINANCE_API_SECRET"], "new_secret") def test_missing_credentials_raise(self): with tempfile.TemporaryDirectory() as tmp_dir, patch.dict( os.environ, {"COINHUNTER_HOME": str(Path(tmp_dir) / "home")}, clear=False, ): os.environ.pop("BINANCE_API_KEY", None) os.environ.pop("BINANCE_API_SECRET", None) paths = get_runtime_paths() ensure_init_files(paths) with self.assertRaisesRegex(RuntimeError, "Missing BINANCE_API_KEY"): get_binance_credentials(paths) def test_permission_error_is_explained(self): with tempfile.TemporaryDirectory() as tmp_dir, patch.dict( os.environ, {"COINHUNTER_HOME": str(Path(tmp_dir) / "home")}, clear=False, ): paths = get_runtime_paths() with patch("coinhunter.config.ensure_runtime_dirs", side_effect=PermissionError("no write access")): with self.assertRaisesRegex(RuntimeError, "Set COINHUNTER_HOME to a writable directory"): ensure_init_files(paths)