"""Tests for config.py: loading, validation, env overrides, save.""" from __future__ import annotations import textwrap from typing import TYPE_CHECKING import pytest if TYPE_CHECKING: from pathlib import Path from mcp_synology_filestation.config import ( AppConfig, ConnectionConfig, load_config, save_config, ) def _write_config(path: Path, content: str) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(textwrap.dedent(content), encoding="utf-8") def test_load_config_minimal(tmp_path: Path) -> None: """Minimal valid config loads successfully.""" cfg_file = tmp_path / "config.yaml" _write_config( cfg_file, """\ schema_version: 1 connection: host: nas.example.com """, ) config = load_config(cfg_file) assert config.connection.host == "nas.example.com" assert config.connection.port == 443 assert config.connection.https is True assert config.connection.verify_ssl is True assert config.connection.timeout == 30 assert config.alias is None def test_load_config_full(tmp_path: Path) -> None: """All fields are parsed correctly.""" cfg_file = tmp_path / "config.yaml" _write_config( cfg_file, """\ schema_version: 1 alias: home-nas connection: host: 192.168.1.2 port: 5001 https: true verify_ssl: false timeout: 60 """, ) config = load_config(cfg_file) assert config.connection.host == "192.168.1.2" assert config.connection.port == 5001 assert config.connection.verify_ssl is False assert config.connection.timeout == 60 assert config.alias == "home-nas" def test_load_config_missing_file(tmp_path: Path) -> None: """Missing config file raises FileNotFoundError.""" with pytest.raises(FileNotFoundError): load_config(tmp_path / "nonexistent.yaml") def test_load_config_wrong_schema_version(tmp_path: Path) -> None: """Wrong schema_version raises ValueError.""" cfg_file = tmp_path / "config.yaml" _write_config( cfg_file, """\ schema_version: 99 connection: host: nas.example.com """, ) with pytest.raises(ValueError, match="schema_version"): load_config(cfg_file) def test_load_config_missing_host(tmp_path: Path) -> None: """Missing host raises ValueError.""" cfg_file = tmp_path / "config.yaml" _write_config( cfg_file, """\ schema_version: 1 connection: {} """, ) with pytest.raises(ValueError, match="connection.host"): load_config(cfg_file) def test_load_config_env_override(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: """Environment variables override YAML values.""" cfg_file = tmp_path / "config.yaml" _write_config( cfg_file, """\ schema_version: 1 connection: host: original-host.example.com """, ) monkeypatch.setenv("SYNOLOGY_HOST", "env-host.example.com") monkeypatch.setenv("SYNOLOGY_PORT", "9999") config = load_config(cfg_file) assert config.connection.host == "env-host.example.com" assert config.connection.port == 9999 def test_base_url_https(tmp_path: Path) -> None: """base_url uses https scheme when https=True.""" cfg_file = tmp_path / "config.yaml" _write_config( cfg_file, """\ schema_version: 1 connection: host: nas.example.com port: 443 https: true """, ) config = load_config(cfg_file) assert config.base_url == "https://nas.example.com:443" def test_base_url_http(tmp_path: Path) -> None: """base_url uses http scheme when https=False.""" cfg_file = tmp_path / "config.yaml" _write_config( cfg_file, """\ schema_version: 1 connection: host: nas.example.com port: 5000 https: false """, ) config = load_config(cfg_file) assert config.base_url == "http://nas.example.com:5000" def test_keyring_service() -> None: """keyring_service is always the fixed service name.""" config = AppConfig( schema_version=1, connection=ConnectionConfig(host="anything"), ) assert config.keyring_service == "mcp-synology-filestation" def test_save_and_reload(tmp_path: Path) -> None: """save_config + load_config round-trips successfully.""" config = AppConfig( schema_version=1, connection=ConnectionConfig( host="nas.example.com", port=443, https=True, verify_ssl=False, timeout=45, ), alias="test", ) cfg_file = tmp_path / "config.yaml" save_config(config, cfg_file) loaded = load_config(cfg_file) assert loaded.connection.host == "nas.example.com" assert loaded.connection.verify_ssl is False assert loaded.connection.timeout == 45 assert loaded.alias == "test"