"""Tests for the analyzer module.""" import pytest from cli_diff_auditor.analyzer import AuditResult, DiffAuditor, FileAnalyzer from cli_diff_auditor.diff_parser import ChangeType, DiffHunk, DiffLine, FileDiff from cli_diff_auditor.rules import RulesLoader, Severity class TestAuditResult: """Test cases for AuditResult class.""" def test_add_finding_error(self): """Test adding an error finding.""" result = AuditResult() result.add_finding(type('Finding', (), { 'severity': Severity.ERROR })()) assert result.errors_count == 1 assert result.warnings_count == 0 assert result.info_count == 0 def test_add_finding_warning(self): """Test adding a warning finding.""" result = AuditResult() result.add_finding(type('Finding', (), { 'severity': Severity.WARNING })()) assert result.errors_count == 0 assert result.warnings_count == 1 assert result.info_count == 0 def test_add_finding_info(self): """Test adding an info finding.""" result = AuditResult() result.add_finding(type('Finding', (), { 'severity': Severity.INFO })()) assert result.errors_count == 0 assert result.warnings_count == 0 assert result.info_count == 1 def test_get_summary(self): """Test getting the summary.""" result = AuditResult() for _ in range(2): result.add_finding(type('Finding', (), {'severity': Severity.ERROR})()) for _ in range(3): result.add_finding(type('Finding', (), {'severity': Severity.WARNING})()) for _ in range(1): result.add_finding(type('Finding', (), {'severity': Severity.INFO})()) summary = result.get_summary() assert summary["error"] == 2 assert summary["warning"] == 3 assert summary["info"] == 1 assert summary["total"] == 6 def test_has_errors(self): """Test checking for errors.""" result = AuditResult() assert result.has_errors() is False result.add_finding(type('Finding', (), {'severity': Severity.ERROR})()) assert result.has_errors() is True def test_has_findings(self): """Test checking for any findings.""" result = AuditResult() assert result.has_findings() is False result.add_finding(type('Finding', (), {'severity': Severity.INFO})()) assert result.has_findings() is True class TestFileAnalyzer: """Test cases for FileAnalyzer class.""" def setup_method(self): """Set up test fixtures.""" self.rules_loader = RulesLoader() self.rules_loader.load_builtin_rules() self.analyzer = FileAnalyzer(self.rules_loader) def test_analyze_file_diff_finds_debug_print(self): """Test that debug prints are detected.""" file_diff = FileDiff(file_path="test.py") hunk = DiffHunk(old_start=1, old_lines=2, new_start=1, new_lines=2) hunk.lines = [ DiffLine(line_number=1, content="print('hello')", change_type=ChangeType.ADDED), ] file_diff.hunks.append(hunk) findings = self.analyzer.analyze_file_diff(file_diff) assert len(findings) == 1 assert findings[0].rule_id == "debug-print" def test_analyze_file_diff_finds_console_log(self): """Test that console.log is detected.""" file_diff = FileDiff(file_path="test.js") hunk = DiffHunk(old_start=1, old_lines=2, new_start=1, new_lines=2) hunk.lines = [ DiffLine(line_number=1, content="console.log('test')", change_type=ChangeType.ADDED), ] file_diff.hunks.append(hunk) findings = self.analyzer.analyze_file_diff(file_diff) assert len(findings) == 1 assert findings[0].rule_id == "console-log" def test_analyze_file_diff_ignores_clean_code(self): """Test that clean code has no findings.""" file_diff = FileDiff(file_path="test.py") hunk = DiffHunk(old_start=1, old_lines=2, new_start=1, new_lines=2) hunk.lines = [ DiffLine(line_number=1, content="def hello():", change_type=ChangeType.ADDED), DiffLine(line_number=2, content=" return 'world'", change_type=ChangeType.ADDED), ] file_diff.hunks.append(hunk) findings = self.analyzer.analyze_file_diff(file_diff) assert len(findings) == 0 def test_analyze_binary_file(self): """Test that binary files are skipped.""" file_diff = FileDiff(file_path="image.png", is_binary=True) hunk = DiffHunk(old_start=1, old_lines=1, new_start=1, new_lines=1) hunk.lines = [ DiffLine(line_number=1, content="binary data", change_type=ChangeType.ADDED), ] file_diff.hunks.append(hunk) findings = self.analyzer.analyze_file_diff(file_diff) assert len(findings) == 0 def test_analyze_deleted_lines(self): """Test that deleted lines are also analyzed.""" file_diff = FileDiff(file_path="test.py") hunk = DiffHunk(old_start=1, old_lines=2, new_start=1, new_lines=1) hunk.lines = [ DiffLine(line_number=1, content="print('old')", change_type=ChangeType.DELETED), ] file_diff.hunks.append(hunk) findings = self.analyzer.analyze_file_diff(file_diff) assert len(findings) == 1 assert findings[0].rule_id == "debug-print" class TestDiffAuditor: """Test cases for DiffAuditor class.""" def setup_method(self): """Set up test fixtures.""" self.auditor = DiffAuditor() def test_get_all_rules(self): """Test getting all rules.""" rules = self.auditor.get_rules() assert len(rules) > 0 assert any(r.id == "debug-print" for r in rules) def test_get_enabled_rules(self): """Test getting enabled rules.""" self.auditor.disable_rules(["debug-print", "console-log"]) enabled = self.auditor.get_enabled_rules() rule_ids = [r.id for r in enabled] assert "debug-print" not in rule_ids assert "console-log" not in rule_ids def test_disable_and_enable_rules(self): """Test disabling and enabling rules.""" self.auditor.disable_rules(["debug-print"]) enabled = self.auditor.get_enabled_rules() assert "debug-print" not in [r.id for r in enabled] self.auditor.enable_rules(["debug-print"]) enabled = self.auditor.get_enabled_rules() assert "debug-print" in [r.id for r in enabled] def test_audit_diff_output(self): """Test auditing diff output directly.""" diff_output = """diff --git a/test.py b/test.py index 1234567..89abcdef 100644 --- a/test.py +++ b/test.py @@ -1,2 +1,2 @@ -old +print('debug') """ result = self.auditor.audit_diff_output(diff_output) assert result.files_scanned == 1 assert result.has_findings() assert result.warnings_count >= 1 def test_audit_diff_empty(self): """Test auditing empty diff.""" result = self.auditor.audit_diff_output("") assert result.files_scanned == 0 assert not result.has_findings()