"""Tests for git hooks module.""" import os import tempfile from pathlib import Path from src.hooks import ( HookManager, is_hook_mode, ) class TestHookManager: """Tests for HookManager class.""" def test_init_with_repo_path(self): """Test initialization with repository path.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) assert manager.repo_path == Path(tmpdir) assert manager.hooks_dir == Path(tmpdir) / ".git" / "hooks" def test_get_hook_path(self): """Test getting hook file path.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) expected = Path(tmpdir) / ".git" / "hooks" / "prepare-commit-msg" assert manager.get_hook_path() == expected def test_hook_exists_false_when_no_file(self): """Test hook_exists returns False when no hook file.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) assert manager.hook_exists() is False def test_hook_exists_true_when_file_exists(self): """Test hook_exists returns True when hook file exists.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) hook_file = hooks_dir / "prepare-commit-msg" hook_file.write_text("# existing hook") assert manager.hook_exists() is True def test_has_our_hook_false_when_no_file(self): """Test has_our_hook returns False when no hook.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) assert manager.has_our_hook() is False def test_has_our_hook_true_when_our_hook(self): """Test has_our_hook returns True when our hook is installed.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) hook_file = hooks_dir / "prepare-commit-msg" hook_file.write_text("# commit-gen hook") assert manager.has_our_hook() is True def test_has_our_hook_false_when_other_hook(self): """Test has_our_hook returns False for other hooks.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) hook_file = hooks_dir / "prepare-commit-msg" hook_file.write_text("# other hook") assert manager.has_our_hook() is False def test_backup_existing_hook(self): """Test backing up existing hook.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) hook_file = hooks_dir / "prepare-commit-msg" hook_file.write_text("# existing hook") backup = manager.backup_existing_hook() assert backup is not None assert backup.exists() assert backup.read_text() == "# existing hook" def test_backup_existing_hook_no_file(self): """Test backup returns None when no file.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) backup = manager.backup_existing_hook() assert backup is None def test_install_hook_success(self): """Test successful hook installation.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) result = manager.install_hook() assert result.success is True assert manager.has_our_hook() is True def test_install_hook_creates_executable(self): """Test installed hook is executable.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) manager.install_hook() hook_file = manager.get_hook_path() mode = os.stat(hook_file).st_mode assert mode & 0o111 def test_install_hook_backs_up_existing(self): """Test hook installation backs up existing hook.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) hook_file = hooks_dir / "prepare-commit-msg" hook_file.write_text("# existing hook") result = manager.install_hook() assert result.success is True assert result.backup_path is not None def test_install_hook_no_backup_when_our_hook(self): """Test no backup when reinstalling our hook.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) hook_file = hooks_dir / "prepare-commit-msg" hook_file.write_text("# commit-gen hook") result = manager.install_hook() assert result.success is True assert result.backup_path is None def test_install_hook_no_hooks_dir(self): """Test install fails when .git/hooks doesn't exist.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) result = manager.install_hook() assert result.success is False assert "not found" in result.message def test_uninstall_hook_success(self): """Test successful hook uninstallation.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) hook_file = hooks_dir / "prepare-commit-msg" hook_file.write_text("# commit-gen hook") result = manager.uninstall_hook() assert result.success is True assert not manager.has_our_hook() def test_uninstall_hook_no_our_hook(self): """Test uninstall fails when our hook isn't installed.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) hook_file = hooks_dir / "prepare-commit-msg" hook_file.write_text("# other hook") result = manager.uninstall_hook() assert result.success is False def test_uninstall_hook_no_file(self):n """Test uninstall fails when no hook file.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) result = manager.uninstall_hook() assert result.success is False def test_restore_hook_success(self): """Test restoring backed up hook.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) hooks_dir = Path(tmpdir) / ".git" / "hooks" hooks_dir.mkdir(parents=True) hook_file = hooks_dir / "prepare-commit-msg" backup_file = hooks_dir / "prepare-commit-msg.backup" backup_file.write_text("# original hook") result = manager.restore_hook() assert result.success is True assert hook_file.exists() assert hook_file.read_text() == "# original hook" def test_restore_hook_no_backup(self): """Test restore fails when no backup exists.""" with tempfile.TemporaryDirectory() as tmpdir: manager = HookManager(tmpdir) result = manager.restore_hook() assert result.success is False class TestIsHookMode: """Tests for is_hook_mode function.""" def test_hook_mode_true(self): """Test detecting hook mode.""" assert is_hook_mode(["hook"]) is True assert is_hook_mode(["hook", "msgfile", "source"]) is True def test_hook_mode_false(self): """Test not hook mode.""" assert is_hook_mode([]) is False assert is_hook_mode(["generate"]) is False assert is_hook_mode(["--help"]) is False