"""Unit tests for CLI commands.""" import pytest from click.testing import CliRunner from unittest.mock import patch, MagicMock import sys from io import StringIO from loglens.cli.commands import analyze, watch, report, patterns, info @pytest.fixture def runner(): """Click CLI runner.""" return CliRunner() class TestAnalyzeCommand: """Tests for analyze command.""" @patch('loglens.cli.commands.LogAnalyzer') def test_analyze_file(self, mock_analyzer_class, runner, tmp_path): """Test analyzing a log file.""" mock_analyzer = MagicMock() mock_result = MagicMock() mock_result.format_detected = MagicMock(value="json") mock_result.total_lines = 3 mock_result.parsed_count = 3 mock_result.error_count = 1 mock_result.warning_count = 1 mock_result.critical_count = 0 mock_result.debug_count = 0 mock_result.top_errors = [] mock_result.suggestions = [] mock_result.entries = [] mock_analyzer.analyze.return_value = mock_result mock_analyzer_class.return_value = mock_analyzer log_file = tmp_path / "test.log" log_file.write_text('{"level": "INFO", "message": "Test"}\n') result = runner.invoke(analyze, [str(log_file)]) assert result.exit_code == 0 @patch('loglens.cli.commands.LogAnalyzer') def test_analyze_json_output(self, mock_analyzer_class, runner, tmp_path): """Test analyze with JSON output.""" mock_analyzer = MagicMock() mock_result = MagicMock() mock_result.format_detected = MagicMock(value="json") mock_result.total_lines = 1 mock_result.parsed_count = 1 mock_result.error_count = 0 mock_result.warning_count = 0 mock_result.critical_count = 0 mock_result.debug_count = 0 mock_result.top_errors = [] mock_result.suggestions = [] mock_result.entries = [] mock_result.analysis_time.isoformat.return_value = "2024-01-15T10:30:00" mock_analyzer.analyze_file.return_value = mock_result mock_analyzer_class.return_value = mock_analyzer log_file = tmp_path / "test.log" log_file.write_text('{"level": "INFO", "message": "Test"}\n') result = runner.invoke(analyze, [str(log_file)]) assert result.exit_code == 0 def test_analyze_no_files(self, runner): """Test analyze with no files.""" result = runner.invoke(analyze, ["--help"]) assert result.exit_code == 0 class TestWatchCommand: """Tests for watch command.""" def test_watch_no_files(self, runner): """Test watch with no files.""" result = runner.invoke(watch, []) assert result.exit_code == 1 assert "Error" in result.output class TestReportCommand: """Tests for report command.""" @patch('loglens.cli.commands.LogAnalyzer') def test_report_to_file(self, mock_analyzer_class, runner, tmp_path): """Test report generation to file.""" mock_analyzer = MagicMock() mock_result = MagicMock() mock_result.format_detected = MagicMock(value="json") mock_result.total_lines = 1 mock_result.parsed_count = 1 mock_result.critical_count = 0 mock_result.error_count = 0 mock_result.warning_count = 0 mock_result.suggestions = [] mock_analyzer.analyze_file.return_value = mock_result mock_analyzer_class.return_value = mock_analyzer log_file = tmp_path / "test.log" log_file.write_text('{"level": "INFO", "message": "Test"}\n') output_file = tmp_path / "report.txt" result = runner.invoke(report, [str(log_file), "--output", str(output_file)]) assert result.exit_code == 0 assert output_file.exists() class TestPatternsCommand: """Tests for patterns command.""" @patch('loglens.cli.commands.LogAnalyzer') def test_list_patterns(self, mock_analyzer_class, runner): """Test listing patterns.""" mock_analyzer = MagicMock() mock_analyzer.list_patterns_by_group.return_value = { "exceptions": [{"name": "Python Exception", "severity": "error", "description": ""}] } mock_analyzer_class.return_value = mock_analyzer result = runner.invoke(patterns) assert result.exit_code == 0 class TestInfoCommand: """Tests for info command.""" def test_info(self, runner): """Test info command displays version.""" result = runner.invoke(info) assert result.exit_code == 0 assert "LogLens" in result.output