"""Tests for change analyzer module.""" from unittest.mock import MagicMock, patch import pytest from src.analyzer import ( ChangeAnalyzer, ChangeSet, ChangeType, StagedChange, ) class TestStagedChange: """Tests for StagedChange class.""" def test_filename_property(self): """Test extracting filename from path.""" change = StagedChange( path="src/cli.py", change_type=ChangeType.MODIFIED ) assert change.filename == "cli.py" def test_is_new_true_for_added(self): """Test is_new returns True for added files.""" change = StagedChange( path="new_file.py", change_type=ChangeType.ADDED ) assert change.is_new is True def test_is_new_false_for_modified(self): """Test is_new returns False for modified files.""" change = StagedChange( path="existing.py", change_type=ChangeType.MODIFIED ) assert change.is_new is False def test_is_deleted_true_for_deleted(self): """Test is_deleted returns True for deleted files.""" change = StagedChange( path="deleted.py", change_type=ChangeType.DELETED ) assert change.is_deleted is True class TestChangeSet: """Tests for ChangeSet class.""" def test_added_property(self): """Test filtering added files.""" changes = ChangeSet([ StagedChange("a.py", ChangeType.ADDED), StagedChange("b.py", ChangeType.MODIFIED), StagedChange("c.py", ChangeType.ADDED), ]) assert len(changes.added) == 2 assert all(c.change_type == ChangeType.ADDED for c in changes.added) def test_deleted_property(self): """Test filtering deleted files.""" changes = ChangeSet([ StagedChange("a.py", ChangeType.DELETED), StagedChange("b.py", ChangeType.MODIFIED), ]) assert len(changes.deleted) == 1 def test_modified_property(self): """Test filtering modified files.""" changes = ChangeSet([ StagedChange("a.py", ChangeType.MODIFIED), StagedChange("b.py", ChangeType.MODIFIED), ]) assert len(changes.modified) == 2 def test_total_count(self): """Test counting total changes.""" changes = ChangeSet([ StagedChange("a.py", ChangeType.ADDED), StagedChange("b.py", ChangeType.DELETED), StagedChange("c.py", ChangeType.MODIFIED), ]) assert changes.total_count == 3 def test_file_paths(self): """Test getting all file paths.""" changes = ChangeSet([ StagedChange("a.py", ChangeType.ADDED), StagedChange("b.py", ChangeType.MODIFIED), ]) assert changes.file_paths == ["a.py", "b.py"] def test_has_changes_true(self): """Test has_changes returns True when changes exist.""" changes = ChangeSet([ StagedChange("a.py", ChangeType.ADDED), ]) assert changes.has_changes is True def test_has_changes_false_for_empty(self): """Test has_changes returns False for empty ChangeSet.""" changes = ChangeSet([]) assert changes.has_changes is False class TestChangeAnalyzer: """Tests for ChangeAnalyzer class.""" def test_init_with_repo_path(self): """Test initialization with repository path.""" analyzer = ChangeAnalyzer("/path/to/repo") assert analyzer.repo_path == "/path/to/repo" def test_init_without_repo_path(self): """Test initialization without repository path.""" analyzer = ChangeAnalyzer() assert analyzer.repo_path is None @patch("src.analyzer.Repo") def test_get_staged_changes_empty(self, mock_repo_class): """Test getting staged changes when empty.""" mock_repo = MagicMock() mock_repo.index.diff.return_value = [] mock_repo.index.diff.return_value = [] mock_repo.index.unmerged_blobs.return_value = {} mock_repo_class.return_value = mock_repo analyzer = ChangeAnalyzer("/tmp") result = analyzer.get_staged_changes() assert result.has_changes is False @patch("src.analyzer.Repo") def test_get_staged_changes_with_changes(self, mock_repo_class): """Test getting staged changes - verify method is called.""" mock_repo = MagicMock() mock_repo.index.diff.return_value = [] mock_repo.index.unmerged_blobs.return_value = {} mock_repo_class.return_value = mock_repo analyzer = ChangeAnalyzer("/tmp") analyzer.get_staged_changes() assert mock_repo.index.diff.called @patch("src.analyzer.Repo") def test_get_staged_changes_not_in_git_repo(self, mock_repo_class): """Test error when not in git repository.""" from git.exc import InvalidGitRepositoryError mock_repo_class.side_effect = InvalidGitRepositoryError() analyzer = ChangeAnalyzer("/tmp") with pytest.raises(ValueError, match="Not a git repository"): analyzer.get_staged_changes() @patch("src.analyzer.Repo") def test_get_changed_extensions(self, mock_repo_class): """Test getting file extensions from changes.""" mock_diff1 = MagicMock() mock_diff1.b_path = "src/cli.py" mock_diff1.a_path = "src/cli.py" mock_diff1.new_file = False mock_diff1.deleted_file = False mock_diff1.renamed_file = False mock_diff1.type_changed = False mock_diff2 = MagicMock() mock_diff2.b_path = "tests/test_cli.py" mock_diff2.a_path = "tests/test_cli.py" mock_diff2.new_file = False mock_diff2.deleted_file = False mock_diff2.renamed_file = False mock_diff2.type_changed = False mock_repo = MagicMock() mock_repo.index.diff.return_value = [mock_diff1, mock_diff2] mock_repo.index.unmerged_blobs.return_value = {} mock_repo_class.return_value = mock_repo analyzer = ChangeAnalyzer("/tmp") extensions = analyzer.get_changed_extensions() assert ".py" in extensions