Files
7000pctAUTO e0601734f1
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled
fix: resolve CI test failures with proper mock patching
2026-01-30 15:57:24 +00:00

228 lines
8.4 KiB
Python

"""Tests for cli.py."""
import tempfile
from pathlib import Path
from unittest.mock import patch, MagicMock
import pytest
from click.testing import CliRunner
from gitignore_generator.cli import main, generate, detect, list, show, cache, clear_cache
class TestCLI:
"""Tests for CLI commands."""
@pytest.fixture
def runner(self):
"""Create CLI runner."""
return CliRunner()
@pytest.fixture
def temp_dir(self):
"""Create temporary directory."""
with tempfile.TemporaryDirectory() as tmpdir:
yield Path(tmpdir)
def test_main_help(self, runner):
"""Test main help command."""
result = runner.invoke(main, ['--help'])
assert result.exit_code == 0
assert 'generate' in result.output
assert 'detect' in result.output
assert 'list' in result.output
def test_generate_help(self, runner):
"""Test generate help."""
result = runner.invoke(generate, ['--help'])
assert result.exit_code == 0
assert 'TECH' in result.output
assert '--output' in result.output
assert '--preview' in result.output
def test_generate_single_tech(self, runner):
"""Test generating gitignore for single tech."""
with patch('gitignore_generator.api.get_patterns') as mock:
mock.return_value = '__pycache__/\n*.pyc\n'
result = runner.invoke(generate, ['python', '--preview'])
assert result.exit_code == 0
assert '__pycache__' in result.output
def test_generate_multiple_techs(self, runner):
"""Test generating gitignore for multiple techs."""
with patch('gitignore_generator.api.get_patterns') as mock:
def side_effect(tech, force=False):
if tech == 'node':
return 'node_modules/\n'
elif tech == 'python':
return '__pycache__/\n'
return ''
mock.side_effect = side_effect
result = runner.invoke(generate, ['node', 'python', '--preview'])
assert result.exit_code == 0
assert 'node_modules' in result.output
assert '__pycache__' in result.output
def test_generate_to_file(self, runner, temp_dir):
"""Test generating gitignore to file."""
output_path = temp_dir / '.gitignore'
with patch('gitignore_generator.api.get_patterns') as mock:
mock.return_value = '__pycache__/\n'
result = runner.invoke(generate, ['python', '-o', str(output_path)])
assert result.exit_code == 0
assert output_path.exists()
content = output_path.read_text()
assert '__pycache__' in content
def test_generate_with_add_pattern(self, runner):
"""Test generating with additional pattern."""
with patch('gitignore_generator.api.get_patterns') as mock:
mock.return_value = '__pycache__/\n'
result = runner.invoke(generate, ['python', '--preview', '--add-pattern', '*.custom'])
assert result.exit_code == 0
assert '*.custom' in result.output
def test_generate_preview_and_output_conflict(self, runner, temp_dir):
"""Test that --preview and -o cannot be used together."""
output_path = temp_dir / '.gitignore'
with patch('gitignore_generator.api.get_patterns') as mock:
mock.return_value = '__pycache__/\n'
result = runner.invoke(generate, ['python', '--preview', '-o', str(output_path)])
assert result.exit_code != 0
assert 'cannot be used together' in result.output
def test_detect_help(self, runner):
"""Test detect help."""
result = runner.invoke(detect, ['--help'])
assert result.exit_code == 0
assert '--preview' in result.output
assert '--output' in result.output
def test_detect_no_project(self, runner, temp_dir):
"""Test detect when no project is found."""
with patch('gitignore_generator.detector.ProjectDetector') as mock_detector:
mock_instance = MagicMock()
mock_instance.detect.return_value = []
mock_instance.suggest_gitignore.return_value = []
mock_instance.get_detection_details.return_value = []
mock_detector.return_value = mock_instance
with runner.isolated_filesystem():
result = runner.invoke(detect, [])
assert result.exit_code == 0
assert 'No project type detected' in result.output
def test_detect_with_project(self, runner):
"""Test detect when project is found."""
from gitignore_generator import cli
with runner.isolated_filesystem():
with patch.object(cli, 'ProjectDetector') as mock_detector:
mock_instance = MagicMock()
mock_instance.detect.return_value = ['python']
mock_instance.suggest_gitignore.return_value = ['python']
mock_instance.get_detection_details.return_value = [
{'technology': 'python', 'matched_files': ['requirements.txt'], 'confidence': 1}
]
mock_detector.return_value = mock_instance
with patch('gitignore_generator.api.get_patterns') as mock_patterns:
mock_patterns.return_value = 'content'
result = runner.invoke(detect, ['--preview'])
assert result.exit_code == 0
assert 'python' in result.output
def test_list_help(self, runner):
"""Test list help."""
result = runner.invoke(list, ['--help'])
assert result.exit_code == 0
assert '--force-refresh' in result.output
def test_list_all(self, runner):
"""Test listing all technologies."""
with patch('gitignore_generator.cli.get_list') as mock:
mock.return_value = ['node', 'python', 'django']
result = runner.invoke(list, [])
assert result.exit_code == 0
assert 'node' in result.output
assert 'python' in result.output
def test_list_filtered(self, runner):
"""Test listing filtered technologies."""
with patch('gitignore_generator.cli.get_list') as mock:
mock.return_value = ['node', 'python', 'nodemon']
result = runner.invoke(list, ['node'])
assert result.exit_code == 0
assert 'Matching' in result.output
def test_show_help(self, runner):
"""Test show help."""
result = runner.invoke(show, ['--help'])
assert result.exit_code == 0
assert '--force-refresh' in result.output
def test_show_tech(self, runner):
"""Test showing patterns for a tech."""
with patch('gitignore_generator.cli.get_patterns') as mock:
mock.return_value = 'node_modules/\n*.log\n'
result = runner.invoke(show, ['node'])
assert result.exit_code == 0
assert 'node_modules' in result.output
def test_cache_help(self, runner):
"""Test cache help."""
result = runner.invoke(cache, ['--help'])
assert result.exit_code == 0
def test_cache_show_stats(self, runner):
"""Test showing cache stats."""
with patch('gitignore_generator.cli.CacheManager') as mock:
mock_instance = MagicMock()
mock_instance.get_stats.return_value = {
'total_items': 10,
'valid_items': 8,
'expired_items': 2,
'cache_dir': '/tmp/cache'
}
mock.return_value = mock_instance
result = runner.invoke(cache, [])
assert result.exit_code == 0
assert '10' in result.output
assert '8' in result.output
def test_clear_cache(self, runner):
"""Test clearing cache."""
with patch('gitignore_generator.cli.CacheManager') as mock:
mock_instance = MagicMock()
mock_instance.clear.return_value = 5
mock.return_value = mock_instance
result = runner.invoke(clear_cache, [])
assert result.exit_code == 0
assert '5' in result.output
def test_cli_error_handling(self, runner):
"""Test CLI error handling."""
with patch('gitignore_generator.cli.get_patterns') as mock:
from gitignore_generator.api import GitignoreIOError
mock.side_effect = GitignoreIOError("Test error")
result = runner.invoke(show, ['nonexistent'])
assert result.exit_code != 0
assert 'Error' in result.output