"""
Unit tests for settings module in the configuration system.
Tests the Settings class and get_settings function.
"""
import pytest
import os
from unittest.mock import patch, MagicMock
from dataclasses import asdict
from commit_helper_mcp.config.settings import Settings, get_settings
from commit_helper_mcp.errors import ServiceError
class TestSettings:
"""Test suite for Settings class."""
def test_settings_default_values(self):
"""Test that Settings has correct default values."""
settings = Settings()
# Check default values
assert settings.default_sign_off is True
assert settings.git_timeout == 30
assert settings.max_commit_message_length == 1000
assert settings.default_repo_path is None
assert settings.allow_repository_traversal is False
assert settings.log_level == "INFO"
assert settings.enable_caching is True
assert settings.cache_ttl == 300
assert settings.validate_file_paths is True
assert settings.sanitize_inputs is True
# Check supported plugins
assert isinstance(settings.supported_plugins, list)
assert "ConventionalCommitsCz" in settings.supported_plugins
assert "ConventionalCommits" in settings.supported_plugins
def test_settings_to_dict(self):
"""Test that to_dict method returns all settings."""
settings = Settings()
settings_dict = settings.to_dict()
# Should have all fields
assert isinstance(settings_dict, dict)
assert "default_sign_off" in settings_dict
assert "git_timeout" in settings_dict
assert "max_commit_message_length" in settings_dict
assert "default_repo_path" in settings_dict
assert "allow_repository_traversal" in settings_dict
assert "supported_plugins" in settings_dict
assert "plugin_timeout" in settings_dict
assert "server_name" in settings_dict
assert "log_level" in settings_dict
assert "enable_caching" in settings_dict
assert "cache_ttl" in settings_dict
assert "validate_file_paths" in settings_dict
assert "sanitize_inputs" in settings_dict
# Should match dataclass asdict
assert settings_dict == asdict(settings)
def test_settings_from_environment(self):
"""Test that Settings can be initialized from environment variables."""
with patch.dict(
os.environ,
{
"COMMITIZEN_SIGN_OFF": "false",
"COMMITIZEN_GIT_TIMEOUT": "60",
"COMMITIZEN_REPO_PATH": "/custom/path",
"COMMITIZEN_LOG_LEVEL": "DEBUG",
"COMMITIZEN_ENABLE_CACHING": "false",
},
):
settings = Settings()
# Should use environment values
assert settings.default_sign_off is False
assert settings.git_timeout == 60
assert settings.default_repo_path == "/custom/path"
assert settings.log_level == "DEBUG"
assert settings.enable_caching is False
# Other values should be defaults
assert settings.max_commit_message_length == 1000
assert settings.allow_repository_traversal is False
assert settings.cache_ttl == 300
assert settings.validate_file_paths is True
assert settings.sanitize_inputs is True
def test_settings_invalid_environment_values(self):
"""Test that Settings handles invalid environment values gracefully."""
# Test with invalid boolean values
with patch.dict(
os.environ,
{
"COMMITIZEN_SIGN_OFF": "not_a_boolean",
"COMMITIZEN_ENABLE_CACHING": "not_a_boolean",
},
):
settings = Settings()
# Any value other than "true" (case-insensitive) will result in False
assert settings.default_sign_off is False
assert settings.enable_caching is False
# Test with invalid numeric values - should raise ServiceError
with patch.dict(os.environ, {"COMMITIZEN_GIT_TIMEOUT": "not_a_number"}):
with pytest.raises(ServiceError):
settings = Settings()
class TestGetSettings:
"""Test suite for get_settings function."""
def test_get_settings_singleton(self):
"""Test that get_settings returns a singleton instance."""
settings1 = get_settings()
settings2 = get_settings()
# Should be the same instance
assert settings1 is settings2
# Should be a Settings instance
assert isinstance(settings1, Settings)
def test_get_settings_with_environment(self):
"""Test that get_settings respects environment variables."""
# This test is redundant with test_settings_from_environment
# since get_settings() just returns a Settings instance
# We'll just verify that get_settings returns a Settings instance
settings = get_settings()
assert isinstance(settings, Settings)