"""Tests for git_utils.py.""" from unittest.mock import MagicMock, patch import pytest from git_commit_generator.git_utils import GitUtils class TestGitUtils: """Test cases for GitUtils.""" @pytest.fixture def git_utils(self): """Create a GitUtils instance with mocked repository.""" with patch("git_commit_generator.git_utils.Repo") as mock_repo: repo = MagicMock() mock_repo.return_value = repo utils = GitUtils("/fake/path") utils.repo = repo yield utils def test_is_repo_true(self, git_utils): """Test is_repo returns True for valid repository.""" git_utils.repo.bare = False result = git_utils.is_repo() assert result is True def test_is_repo_false(self, git_utils): """Test is_repo returns False for invalid repository.""" git_utils.repo.bare = True result = git_utils.is_repo() assert result is False def test_get_staged_diff(self, git_utils): """Test getting staged diff.""" diff_mock = MagicMock() diff_mock.diff = b"diff --git a/file.py b/file.py" git_utils.repo.index.diff.return_value = [diff_mock] result = git_utils.get_staged_diff() assert "diff --git a/file.py b/file.py" in result def test_get_unstaged_diff(self, git_utils): """Test getting unstaged diff.""" diff_mock = MagicMock() diff_mock.diff = "diff --git a/file.py b/file.py" git_utils.repo.index.diff.return_value = [diff_mock] result = git_utils.get_unstaged_diff() assert "diff --git a/file.py b/file.py" in result def test_get_staged_files(self, git_utils): """Test getting list of staged files.""" diff_mock = MagicMock() diff_mock.a_path = "src/main.py" git_utils.repo.index.diff.return_value = [diff_mock] result = git_utils.get_staged_files() assert result == ["src/main.py"] def test_get_commit_history(self, git_utils): """Test getting commit history.""" commit_mock = MagicMock() commit_mock.hexsha = "abc1234567890" commit_mock.message = "feat: add new feature" commit_mock.author.name = "Test User" commit_mock.author.email = "test@example.com" commit_mock.committed_datetime.isoformat.return_value = "2024-01-15T10:30:00" git_utils.repo.iter_commits.return_value = [commit_mock] result = git_utils.get_commit_history(limit=10) assert len(result) == 1 assert result[0]["hash"] == "abc1234" assert result[0]["full_hash"] == "abc1234567890" assert result[0]["message"] == "feat: add new feature" def test_get_conventional_commits(self, git_utils): """Test filtering conventional commits.""" commit_mock = MagicMock() commit_mock.hexsha = "abc1234567890" commit_mock.message = "feat(api): new feature" commit_mock.author.name = "Test User" commit_mock.author.email = "test@example.com" commit_mock.committed_datetime.isoformat.return_value = "2024-01-15T10:30:00" git_utils.repo.iter_commits.return_value = [commit_mock] result = git_utils.get_conventional_commits() assert len(result) == 1 assert result[0]["type"] == "feat" assert result[0]["scope"] == "api" def test_get_file_scopes(self, git_utils): """Test extracting scopes from file paths.""" git_utils.get_changed_files = MagicMock(return_value=[ "api/routes.py", "auth/login.py", "tests/test_main.py", ]) result = git_utils.get_file_scopes() assert "api" in result assert "auth" in result def test_is_conventional_message_valid(self, git_utils): """Test conventional message validation.""" message = "feat(auth): add login functionality" result = git_utils._is_conventional_message(message) assert result is True def test_is_conventional_message_invalid(self, git_utils): """Test non-conventional message validation.""" message = "Added new feature" result = git_utils._is_conventional_message(message) assert result is False def test_parse_conventional_commit_full(self, git_utils): """Test parsing full conventional commit.""" message = "fix(database): resolve connection timeout issue" result = git_utils._parse_conventional_commit(message) assert result["type"] == "fix" assert result["scope"] == "database" assert result["description"] == "resolve connection timeout issue" def test_parse_conventional_commit_no_scope(self, git_utils): """Test parsing conventional commit without scope.""" message = "chore: update dependencies" result = git_utils._parse_conventional_commit(message) assert result["type"] == "chore" assert result["scope"] == "" assert result["description"] == "update dependencies"