from __future__ import annotations import pytest from pydantic import ValidationError def _minimal_env(**overrides) -> dict: base = { "TESTNET_TOKEN": "t_test_123", "MAINNET_TOKEN": "t_live_456", "DERIBIT_CLIENT_ID": "id", "DERIBIT_CLIENT_SECRET": "secret", "DERIBIT_URL_LIVE": "https://www.deribit.com/api/v2", "DERIBIT_URL_TESTNET": "https://test.deribit.com/api/v2", "BYBIT_API_KEY": "k", "BYBIT_API_SECRET": "s", "BYBIT_URL_LIVE": "https://api.bybit.com", "BYBIT_URL_TESTNET": "https://api-testnet.bybit.com", "HYPERLIQUID_WALLET_ADDRESS": "0xabc", "HYPERLIQUID_API_WALLET_ADDRESS": "0xdef", "HYPERLIQUID_PRIVATE_KEY": "0x123", "HYPERLIQUID_URL_LIVE": "https://api.hyperliquid.xyz", "HYPERLIQUID_URL_TESTNET": "https://api.hyperliquid-testnet.xyz", "ALPACA_API_KEY_ID": "k", "ALPACA_SECRET_KEY": "s", "ALPACA_URL_LIVE": "https://api.alpaca.markets", "ALPACA_URL_TESTNET": "https://paper-api.alpaca.markets", "FRED_API_KEY": "x", "FINNHUB_API_KEY": "y", "CRYPTOPANIC_KEY": "z", "LUNARCRUSH_KEY": "w", } base.update(overrides) return base def test_settings_load_minimal(monkeypatch): for k, v in _minimal_env().items(): monkeypatch.setenv(k, v) monkeypatch.setenv("PORT", "9123") from cerbero_mcp.settings import Settings s = Settings() assert s.port == 9123 assert s.host == "0.0.0.0" assert s.testnet_token.get_secret_value() == "t_test_123" assert s.mainnet_token.get_secret_value() == "t_live_456" assert s.deribit.url_testnet.endswith("test.deribit.com/api/v2") assert s.bybit.max_leverage == 3 assert s.alpaca.max_leverage == 1 def test_settings_missing_token_fails(monkeypatch): env = _minimal_env() env.pop("TESTNET_TOKEN") for k, v in env.items(): monkeypatch.setenv(k, v) monkeypatch.delenv("TESTNET_TOKEN", raising=False) from cerbero_mcp.settings import Settings with pytest.raises(ValidationError): Settings() def test_settings_extras_ignored(monkeypatch): for k, v in _minimal_env().items(): monkeypatch.setenv(k, v) monkeypatch.setenv("UNRELATED_VAR", "ignored") from cerbero_mcp.settings import Settings s = Settings() assert s.testnet_token.get_secret_value() == "t_test_123" def test_settings_secret_str_no_leak(monkeypatch): for k, v in _minimal_env().items(): monkeypatch.setenv(k, v) from cerbero_mcp.settings import Settings s = Settings() assert "t_test_123" not in repr(s) assert "t_live_456" not in repr(s)