"""Tests for CLI commands.""" import os import tempfile from pathlib import Path from unittest.mock import patch import pytest from typer.testing import CliRunner from gitignore_cli.main import app runner = CliRunner() class TestGenerateCommand: """Tests for the generate command.""" def test_generate_single_template(self): """Test generating .gitignore with a single template.""" with tempfile.TemporaryDirectory() as tmpdir: os.chdir(tmpdir) result = runner.invoke(app, ["generate", "nodejs"]) assert result.exit_code == 0, f"Exit code: {result.exit_code}, Output: {result.output}" assert ".gitignore" in os.listdir(".") def test_generate_multiple_templates(self): """Test generating .gitignore with multiple templates.""" with tempfile.TemporaryDirectory() as tmpdir: os.chdir(tmpdir) result = runner.invoke(app, ["generate", "nodejs", "vscode"]) assert result.exit_code == 0, f"Exit code: {result.exit_code}, Output: {result.output}" assert ".gitignore" in os.listdir(".") def test_generate_with_output_flag(self): """Test generating .gitignore with custom output path.""" with tempfile.TemporaryDirectory() as tmpdir: output_path = Path(tmpdir) / "custom.gitignore" result = runner.invoke(app, [ "generate", "nodejs", "--output", str(output_path) ]) assert result.exit_code == 0, f"Exit code: {result.exit_code}, Output: {result.output}" assert output_path.exists() def test_generate_dry_run(self): """Test generating preview without writing file.""" with tempfile.TemporaryDirectory() as tmpdir: os.chdir(tmpdir) result = runner.invoke(app, ["generate", "nodejs", "--dry-run"]) assert result.exit_code == 0, f"Exit code: {result.exit_code}, Output: {result.output}" assert ".gitignore" not in os.listdir(".") def test_generate_nonexistent_template(self): """Test generating with nonexistent template.""" with tempfile.TemporaryDirectory() as tmpdir: os.chdir(tmpdir) result = runner.invoke(app, ["generate", "nonexistent"]) assert result.exit_code == 1, f"Exit code: {result.exit_code}, Output: {result.output}" assert "not found" in result.output.lower() class TestListCommand: """Tests for the list command.""" def test_list_all_templates(self): """Test listing all templates.""" result = runner.invoke(app, ["list"]) assert result.exit_code == 0 assert "python" in result.output or "nodejs" in result.output def test_list_by_category(self): """Test listing templates by category.""" result = runner.invoke(app, ["list", "--category", "language"]) assert result.exit_code == 0 def test_list_nonexistent_category(self): """Test listing templates by nonexistent category.""" result = runner.invoke(app, ["list", "--category", "nonexistent"]) assert result.exit_code == 0 assert "no templates" in result.output.lower() class TestSearchCommand: """Tests for the search command.""" def test_search_templates(self): """Test searching for templates.""" result = runner.invoke(app, ["search", "nodejs"]) assert result.exit_code == 0 assert "nodejs" in result.output.lower() def test_search_no_results(self): """Test searching with no results.""" result = runner.invoke(app, ["search", "xyznonexistent"]) assert result.exit_code == 0 assert "no templates" in result.output.lower() class TestShowCommand: """Tests for the show command.""" def test_show_template(self): """Test showing a specific template.""" result = runner.invoke(app, ["show", "nodejs"]) assert result.exit_code == 0, f"Exit code: {result.exit_code}, Output: {result.output}" assert "node_modules" in result.output.lower() or "log" in result.output.lower() def test_show_nonexistent_template(self): """Test showing a nonexistent template.""" result = runner.invoke(app, ["show", "nonexistent"]) assert result.exit_code == 1 assert "not found" in result.output.lower() class TestPreviewCommand: """Tests for the preview command.""" def test_preview_templates(self): """Test previewing template patterns.""" result = runner.invoke(app, ["preview", "nodejs"]) assert result.exit_code == 0, f"Exit code: {result.exit_code}, Output: {result.output}" assert "Preview" in result.output def test_preview_multiple_templates(self): """Test previewing multiple templates.""" result = runner.invoke(app, ["preview", "nodejs", "vscode"]) assert result.exit_code == 0, f"Exit code: {result.exit_code}, Output: {result.output}" class TestCustomCommands: """Tests for custom pattern commands.""" def test_custom_add(self, temp_dir: Path): """Test adding a custom pattern.""" with patch("gitignore_cli.custom_patterns.CUSTOM_PATTERNS_FILE", temp_dir / "custom_patterns.yaml"): result = runner.invoke(app, ["custom-add", "*.custom", "--description", "Custom files"]) assert result.exit_code == 0 assert "Added" in result.output def test_custom_list_empty(self, temp_dir: Path): """Test listing custom patterns when none exist.""" with patch("gitignore_cli.custom_patterns.CUSTOM_PATTERNS_FILE", temp_dir / "custom_patterns.yaml"): result = runner.invoke(app, ["custom-list"]) assert result.exit_code == 0 def test_custom_remove(self, temp_dir: Path): """Test removing a custom pattern.""" with patch("gitignore_cli.custom_patterns.CUSTOM_PATTERNS_FILE", temp_dir / "custom_patterns.yaml"): runner.invoke(app, ["custom-add", "*.test"]) result = runner.invoke(app, ["custom-remove", "*.test"]) assert result.exit_code == 0 assert "Removed" in result.output def test_custom_toggle(self, temp_dir: Path): """Test toggling a custom pattern.""" with patch("gitignore_cli.custom_patterns.CUSTOM_PATTERNS_FILE", temp_dir / "custom_patterns.yaml"): runner.invoke(app, ["custom-add", "*.toggle"]) result = runner.invoke(app, ["custom-toggle", "*.toggle"]) assert result.exit_code == 0 assert "disabled" in result.output.lower() or "enabled" in result.output.lower()