"""Tests for git_utils.py.""" import os import tempfile from datetime import datetime from pathlib import Path import pytest from src.git_utils import ( GitChange, GitCommit, GitError, NotGitRepositoryError, get_repo, get_staged_diff, get_unstaged_diff, get_commit_history, parse_conventional_commit, get_changed_files, ) class TestGetRepo: """Tests for get_repo function.""" def test_get_repo_valid_repository(self, temp_git_repo): """Test getting a valid git repository.""" repo = get_repo(temp_git_repo) assert repo is not None def test_get_repo_invalid_path(self): """Test getting a non-git directory.""" with tempfile.TemporaryDirectory() as tmpdir: with pytest.raises(NotGitRepositoryError): get_repo(tmpdir) class TestParseConventionalCommit: """Tests for parse_conventional_commit function.""" def test_parse_valid_commit_with_scope(self): """Test parsing a conventional commit with scope.""" message = "feat(auth): add user authentication" commit_type, scope, body = parse_conventional_commit(message) assert commit_type == "feat" assert scope == "auth" assert body is None def test_parse_valid_commit_without_scope(self): """Test parsing a conventional commit without scope.""" message = "fix: resolve critical bug" commit_type, scope, body = parse_conventional_commit(message) assert commit_type == "fix" assert scope is None assert body is None def test_parse_commit_with_body(self): """Test parsing a commit with body.""" message = """feat(api): add new endpoint This is the detailed description of the changes made.""" commit_type, scope, body = parse_conventional_commit(message) assert commit_type == "feat" assert scope == "api" assert body is not None assert "detailed description" in body def test_parse_non_conventional_commit(self): """Test parsing a non-conventional commit.""" message = "Just a regular commit message" commit_type, scope, body = parse_conventional_commit(message) assert commit_type is None assert scope is None assert body is None class TestGetCommitHistory: """Tests for get_commit_history function.""" def test_get_commit_history_empty_repo(self, temp_git_repo): """Test getting history from a repo with no commits.""" repo = get_repo(temp_git_repo) commits = get_commit_history(repo, limit=10) assert commits == [] def test_get_commit_history_with_commits(self, temp_git_repo): """Test getting history from a repo with commits.""" repo = get_repo(temp_git_repo) test_file = temp_git_repo / "test.txt" test_file.write_text("initial content") os.system("git add .") os.system("git commit -m 'feat: initial commit' --quiet") commits = get_commit_history(repo, limit=10) assert len(commits) >= 1 assert commits[0].commit_type == "feat" def test_get_commit_history_with_limit(self, temp_git_repo): """Test getting history with a limit.""" repo = get_repo(temp_git_repo) for i in range(5): test_file = temp_git_repo / f"test{i}.txt" test_file.write_text(f"content {i}") os.system("git add .") os.system(f"git commit -m 'chore: commit {i}' --quiet") commits = get_commit_history(repo, limit=3) assert len(commits) == 3 class TestGitChange: """Tests for GitChange dataclass.""" def test_git_change_creation(self): """Test creating a GitChange object.""" change = GitChange( file_path="src/main.py", change_type="M", diff_content="some diff content", staged=True, ) assert change.file_path == "src/main.py" assert change.change_type == "M" assert change.staged is True class TestGitCommit: """Tests for GitCommit dataclass.""" def test_git_commit_creation(self): """Test creating a GitCommit object.""" commit = GitCommit( sha="abc1234", message="feat: new feature", author="Test User", author_email="test@example.com", date=datetime.now(), commit_type="feat", scope="test", body="Additional details", ) assert commit.sha == "abc1234" assert commit.commit_type == "feat" assert commit.scope == "test"