diff --git a/gitignore_generator/tests/test_cli.py b/gitignore_generator/tests/test_cli.py new file mode 100644 index 0000000..08a80b7 --- /dev/null +++ b/gitignore_generator/tests/test_cli.py @@ -0,0 +1,155 @@ +"""Tests for CLI commands.""" + +import os +import sys +import tempfile +from pathlib import Path +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +import pytest +from click.testing import CliRunner + +from gitignore_generator.cli import main +from gitignore_generator import __version__ + + +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: + orig_cwd = os.getcwd() + os.chdir(tmpdir) + yield Path(tmpdir) + os.chdir(orig_cwd) + + def test_version_flag(self, runner): + """Test --version flag.""" + result = runner.invoke(main, ["--version"]) + assert result.exit_code == 0 + assert f"v{__version__}" in result.output + + def test_generate_command(self, runner, temp_dir): + """Test generate command.""" + result = runner.invoke(main, ["generate", "python"]) + assert result.exit_code == 0 + assert ".gitignore" in result.output + + def test_generate_multiple_templates(self, runner, temp_dir): + """Test generating multiple templates.""" + result = runner.invoke(main, ["generate", "python", "javascript"]) + assert result.exit_code == 0 + assert "successfully generated" in result.output.lower() + assert ".gitignore" in result.output.lower() + + def test_generate_with_ide(self, runner, temp_dir): + """Test generating with IDE template.""" + result = runner.invoke(main, ["generate", "python", "--ide", "vscode"]) + assert result.exit_code == 0 + + def test_generate_invalid_template(self, runner, temp_dir): + """Test generate with invalid template.""" + result = runner.invoke(main, ["generate", "nonexistent_template"]) + assert result.exit_code != 0 + assert "not found" in result.output.lower() + + def test_generate_with_output(self, runner, temp_dir): + """Test generate with custom output file.""" + result = runner.invoke(main, ["generate", "python", "-o", "custom.gitignore"]) + assert result.exit_code == 0 + assert os.path.exists("custom.gitignore") + + def test_list_command(self, runner): + """Test list command.""" + result = runner.invoke(main, ["list"]) + assert result.exit_code == 0 + assert "python" in result.output.lower() + assert "javascript" in result.output.lower() + + def test_list_by_category(self, runner): + """Test list by category.""" + result = runner.invoke(main, ["list", "--category", "languages"]) + assert result.exit_code == 0 + + def test_search_command(self, runner): + """Test search command.""" + result = runner.invoke(main, ["search", "python"]) + assert result.exit_code == 0 + assert "python" in result.output.lower() + + def test_search_no_results(self, runner): + """Test search with no results.""" + result = runner.invoke(main, ["search", "nonexistent12345"]) + assert result.exit_code == 0 + assert "no templates found" in result.output.lower() + + def test_validate_valid_file(self, runner, temp_dir): + """Test validating a valid .gitignore file.""" + Path(".gitignore").write_text("*.pyc\n__pycache__/\n") + result = runner.invoke(main, ["validate", ".gitignore"]) + assert result.exit_code == 0 + assert "Valid" in result.output + + def test_validate_invalid_file(self, runner, temp_dir): + """Test validating an invalid .gitignore file.""" + Path(".gitignore").write_text("test\\n") + result = runner.invoke(main, ["validate", ".gitignore"]) + assert result.exit_code == 0 + assert "Invalid" in result.output or "ERROR" in result.output + + def test_template_add(self, runner, temp_dir): + """Test adding a custom template.""" + with tempfile.NamedTemporaryFile(mode="w", suffix=".gitignore", delete=False) as f: + f.write("# Custom\ncustom.txt\n") + temp_file = f.name + + try: + result = runner.invoke(main, ["template-add", "my_template", temp_file]) + assert result.exit_code == 0 + assert "my_template" in result.output.lower() + finally: + os.unlink(temp_file) + + def test_template_remove(self, runner): + """Test removing a custom template.""" + result = runner.invoke(main, ["template-remove", "nonexistent"]) + assert result.exit_code != 0 + + def test_template_export(self, runner, temp_dir): + """Test exporting a template.""" + result = runner.invoke(main, ["template-export", "python", "exported.gitignore"]) + assert result.exit_code == 0 + assert os.path.exists("exported.gitignore") + + def test_template_info(self, runner): + """Test template info command.""" + result = runner.invoke(main, ["info", "python"]) + assert result.exit_code == 0 + assert "python" in result.output.lower() + assert "Patterns" in result.output or "Lines" in result.output + + def test_generate_overwrite_prompt(self, runner, temp_dir): + """Test overwrite prompt for existing file.""" + Path(".gitignore").write_text("old content") + result = runner.invoke(main, ["generate", "python", "-f"]) + assert result.exit_code == 0 + + def test_interactive_command_exists(self, runner): + """Test interactive command exists.""" + result = runner.invoke(main, ["--help"]) + assert "interactive" in result.output.lower() + + def test_generate_no_templates_error(self, runner, temp_dir): + """Test error when no templates specified.""" + result = runner.invoke(main, ["generate"]) + assert result.exit_code != 0 + assert "no templates" in result.output.lower()