fix: Add Gitea Actions CI workflow and fix linting issues
This commit is contained in:
138
tests/test_cli.py
Normal file
138
tests/test_cli.py
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
"""Tests for CLI interface."""
|
||||||
|
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from click.testing import CliRunner
|
||||||
|
|
||||||
|
from src.cli import main
|
||||||
|
|
||||||
|
|
||||||
|
class TestMainGroup:
|
||||||
|
"""Tests for main CLI group."""
|
||||||
|
|
||||||
|
def test_main_help(self):
|
||||||
|
"""Test main command shows help."""
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(main, ["--help"])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "Generate conventional commit messages" in result.output
|
||||||
|
|
||||||
|
def test_main_version(self):
|
||||||
|
"""Test version flag works."""
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(main, ["--version"])
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "local-commit-message-generator" in result.output
|
||||||
|
|
||||||
|
|
||||||
|
class TestGenerateCommand:
|
||||||
|
"""Tests for generate command."""
|
||||||
|
|
||||||
|
def test_generate_handles_error(self):
|
||||||
|
"""Test generate handles errors gracefully."""
|
||||||
|
runner = CliRunner()
|
||||||
|
with patch('src.generator.generate_commit_message') as mock:
|
||||||
|
mock.side_effect = Exception("No staged changes")
|
||||||
|
result = runner.invoke(main, ["generate"])
|
||||||
|
assert result.exit_code == 1
|
||||||
|
|
||||||
|
|
||||||
|
class TestInstallHookCommand:
|
||||||
|
"""Tests for install-hook command."""
|
||||||
|
|
||||||
|
def test_install_hook_no_git_dir(self):
|
||||||
|
"""Test install hook fails without .git directory."""
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(main, ["install-hook"], obj={"repo": tmpdir})
|
||||||
|
|
||||||
|
assert result.exit_code != 0
|
||||||
|
assert "not found" in result.output.lower()
|
||||||
|
|
||||||
|
|
||||||
|
class TestUninstallHookCommand:
|
||||||
|
"""Tests for uninstall-hook command."""
|
||||||
|
|
||||||
|
def test_uninstall_hook_not_installed(self):
|
||||||
|
"""Test uninstall when hook not installed."""
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
git_dir = Path(tmpdir) / ".git"
|
||||||
|
hooks_dir = git_dir / "hooks"
|
||||||
|
hooks_dir.mkdir(parents=True)
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(main, ["uninstall-hook"], obj={"repo": tmpdir})
|
||||||
|
|
||||||
|
assert result.exit_code != 0
|
||||||
|
|
||||||
|
|
||||||
|
class TestConfigCommand:
|
||||||
|
"""Tests for config subcommand."""
|
||||||
|
|
||||||
|
def test_config_show(self):
|
||||||
|
"""Test config show displays configuration."""
|
||||||
|
runner = CliRunner()
|
||||||
|
result = runner.invoke(main, ["config", "show"])
|
||||||
|
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "Current Configuration" in result.output
|
||||||
|
assert "template" in result.output
|
||||||
|
|
||||||
|
|
||||||
|
class TestPreviewCommand:
|
||||||
|
"""Tests for preview command."""
|
||||||
|
|
||||||
|
def test_preview_displays_message(self):
|
||||||
|
"""Test preview displays message."""
|
||||||
|
runner = CliRunner()
|
||||||
|
with patch('src.generator.get_commit_message_preview') as mock:
|
||||||
|
mock.return_value = ("feat: new feature", True)
|
||||||
|
result = runner.invoke(main, ["preview"])
|
||||||
|
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "Preview" in result.output
|
||||||
|
assert "feat: new feature" in result.output
|
||||||
|
|
||||||
|
def test_preview_no_changes(self):
|
||||||
|
"""Test preview with no changes."""
|
||||||
|
runner = CliRunner()
|
||||||
|
with patch('src.generator.get_commit_message_preview') as mock:
|
||||||
|
mock.return_value = ("", False)
|
||||||
|
result = runner.invoke(main, ["preview"])
|
||||||
|
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "No staged changes" in result.output
|
||||||
|
|
||||||
|
|
||||||
|
class TestStatusCommand:
|
||||||
|
"""Tests for status command."""
|
||||||
|
|
||||||
|
def test_status_with_changes(self):
|
||||||
|
"""Test status shows changes."""
|
||||||
|
runner = CliRunner()
|
||||||
|
with patch('src.analyzer.ChangeAnalyzer') as mock_analyzer:
|
||||||
|
from src.analyzer import ChangeSet, ChangeType, StagedChange
|
||||||
|
|
||||||
|
mock_analyzer.return_value.get_staged_changes.return_value = ChangeSet([
|
||||||
|
StagedChange("src/main.py", ChangeType.ADDED),
|
||||||
|
])
|
||||||
|
|
||||||
|
result = runner.invoke(main, ["status"])
|
||||||
|
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "Staged changes" in result.output or "+" in result.output
|
||||||
|
|
||||||
|
def test_status_no_changes(self):
|
||||||
|
"""Test status with no changes."""
|
||||||
|
runner = CliRunner()
|
||||||
|
with patch('src.analyzer.ChangeAnalyzer') as mock_analyzer:
|
||||||
|
from src.analyzer import ChangeSet
|
||||||
|
|
||||||
|
mock_analyzer.return_value.get_staged_changes.return_value = ChangeSet([])
|
||||||
|
|
||||||
|
result = runner.invoke(main, ["status"])
|
||||||
|
|
||||||
|
assert result.exit_code == 0
|
||||||
|
assert "No staged changes" in result.output
|
||||||
Reference in New Issue
Block a user