"""Tests for configuration management.""" import pytest from pydantic import ValidationError from aegis_gitea_mcp.config import get_settings, reset_settings def test_settings_from_env(mock_env: None) -> None: """Test loading settings from environment variables.""" settings = get_settings() assert settings.gitea_base_url == "https://gitea.example.com" assert settings.gitea_token == "test-token-12345" assert settings.mcp_host == "127.0.0.1" assert settings.mcp_port == 8080 assert settings.log_level == "DEBUG" def test_settings_defaults(monkeypatch: pytest.MonkeyPatch) -> None: """Test default values when not specified.""" monkeypatch.setenv("GITEA_URL", "https://gitea.example.com") monkeypatch.setenv("GITEA_TOKEN", "test-token") monkeypatch.setenv("MCP_API_KEYS", "a" * 64) settings = get_settings() assert settings.mcp_host == "127.0.0.1" assert settings.mcp_port == 8080 assert settings.log_level == "INFO" assert settings.max_file_size_bytes == 1_048_576 assert settings.request_timeout_seconds == 30 def test_settings_validation_missing_required(monkeypatch: pytest.MonkeyPatch, tmp_path) -> None: """Test that missing required fields raise validation errors.""" monkeypatch.delenv("GITEA_URL", raising=False) monkeypatch.delenv("GITEA_TOKEN", raising=False) # Change to tmp directory so .env file won't be found monkeypatch.chdir(tmp_path) reset_settings() with pytest.raises(ValidationError): get_settings() def test_settings_invalid_log_level(monkeypatch: pytest.MonkeyPatch) -> None: """Test that invalid log levels are rejected.""" monkeypatch.setenv("GITEA_URL", "https://gitea.example.com") monkeypatch.setenv("GITEA_TOKEN", "test-token") monkeypatch.setenv("MCP_API_KEYS", "a" * 64) monkeypatch.setenv("LOG_LEVEL", "INVALID") reset_settings() with pytest.raises(ValidationError): get_settings() def test_settings_empty_token(monkeypatch: pytest.MonkeyPatch) -> None: """Test that empty tokens are rejected.""" monkeypatch.setenv("GITEA_URL", "https://gitea.example.com") monkeypatch.setenv("GITEA_TOKEN", " ") monkeypatch.setenv("MCP_API_KEYS", "a" * 64) reset_settings() with pytest.raises(ValidationError): get_settings() def test_settings_singleton(mock_env: None) -> None: """Test that get_settings returns same instance.""" settings1 = get_settings() settings2 = get_settings() assert settings1 is settings2 def test_write_mode_requires_whitelist_or_allow_all(monkeypatch: pytest.MonkeyPatch) -> None: """Write mode without whitelist must be rejected unless allow-all is enabled.""" monkeypatch.setenv("GITEA_URL", "https://gitea.example.com") monkeypatch.setenv("GITEA_TOKEN", "test-token") monkeypatch.setenv("MCP_API_KEYS", "a" * 64) monkeypatch.setenv("WRITE_MODE", "true") monkeypatch.delenv("WRITE_REPOSITORY_WHITELIST", raising=False) monkeypatch.setenv("WRITE_ALLOW_ALL_TOKEN_REPOS", "false") reset_settings() with pytest.raises(ValidationError): get_settings() def test_write_mode_allows_all_token_repos(monkeypatch: pytest.MonkeyPatch) -> None: """Allow-all mode should pass validation without explicit repository whitelist.""" monkeypatch.setenv("GITEA_URL", "https://gitea.example.com") monkeypatch.setenv("GITEA_TOKEN", "test-token") monkeypatch.setenv("MCP_API_KEYS", "a" * 64) monkeypatch.setenv("WRITE_MODE", "true") monkeypatch.delenv("WRITE_REPOSITORY_WHITELIST", raising=False) monkeypatch.setenv("WRITE_ALLOW_ALL_TOKEN_REPOS", "true") reset_settings() settings = get_settings() assert settings.write_allow_all_token_repos is True def _oauth_env(monkeypatch: pytest.MonkeyPatch) -> None: """Apply a minimal, valid OAuth-mode environment.""" monkeypatch.setenv("GITEA_URL", "https://gitea.example.com") monkeypatch.setenv("OAUTH_MODE", "true") monkeypatch.setenv("GITEA_OAUTH_CLIENT_ID", "test-client-id") monkeypatch.setenv("GITEA_OAUTH_CLIENT_SECRET", "test-client-secret") monkeypatch.setenv("STARTUP_VALIDATE_GITEA", "false") def test_oauth_state_secret_too_short_is_rejected(monkeypatch: pytest.MonkeyPatch) -> None: """OAUTH_STATE_SECRET shorter than 32 characters must fail validation.""" _oauth_env(monkeypatch) monkeypatch.setenv("OAUTH_STATE_SECRET", "short-secret") reset_settings() with pytest.raises(ValidationError, match="at least 32 characters"): get_settings() def test_oauth_state_secret_minimum_length_accepted(monkeypatch: pytest.MonkeyPatch) -> None: """A 32+ character OAUTH_STATE_SECRET passes validation.""" _oauth_env(monkeypatch) monkeypatch.setenv("OAUTH_STATE_SECRET", "x" * 32) reset_settings() settings = get_settings() assert settings.oauth_mode is True assert len(settings.oauth_state_secret) == 32