diff --git a/tests/unit/test_reporters.py b/tests/unit/test_reporters.py new file mode 100644 index 0000000..f7a7bed --- /dev/null +++ b/tests/unit/test_reporters.py @@ -0,0 +1,190 @@ +"""Tests for reporters.""" + +import json + +import pytest + +from depcheck.config import Config +from depcheck.models import Dependency, PackageManager, ScanResult, Severity, Vulnerability +from depcheck.reporters.json import JSONReporter +from depcheck.reporters.terminal import TerminalReporter + + +class TestTerminalReporter: + """Tests for terminal reporter.""" + + def test_report_empty_result(self): + """Test reporting empty result.""" + config = Config() + reporter = TerminalReporter(config) + + result = ScanResult() + + reporter.report(result) + + def test_report_with_outdated_packages(self): + """Test reporting with outdated packages.""" + config = Config() + reporter = TerminalReporter(config) + + dep = Dependency( + name="express", + current_version="4.18.2", + latest_version="4.19.2", + package_manager=PackageManager.NPM, + is_outdated=True, + ) + + result = ScanResult(dependencies=[dep]) + + reporter.report(result) + + +class TestJSONReporter: + """Tests for JSON reporter.""" + + def test_report_empty_result(self): + """Test JSON output for empty result.""" + config = Config() + reporter = JSONReporter(config) + + result = ScanResult() + json_output = reporter.report(result) + + data = json.loads(json_output) + assert data["summary"]["status"] == "success" + assert data["dependencies"] == [] + assert data["vulnerabilities"] == [] + + def test_report_with_dependencies(self): + """Test JSON output with dependencies.""" + config = Config() + reporter = JSONReporter(config) + + dep = Dependency( + name="express", + current_version="4.18.2", + latest_version="4.19.2", + package_manager=PackageManager.NPM, + is_outdated=True, + category="dependencies", + source_file="package.json", + ) + + result = ScanResult(dependencies=[dep], source_file="package.json") + json_output = reporter.report(result) + + data = json.loads(json_output) + assert len(data["dependencies"]) == 1 + assert data["dependencies"][0]["name"] == "express" + + def test_report_with_vulnerabilities(self): + """Test JSON output with vulnerabilities.""" + config = Config() + reporter = JSONReporter(config) + + dep = Dependency( + name="lodash", + current_version="4.17.20", + package_manager=PackageManager.NPM, + ) + vuln = Vulnerability( + cve_id="CVE-2021-23337", + severity=Severity.HIGH, + description="Command Injection", + affected_versions="<4.17.21", + fixed_version="4.17.21", + ) + + result = ScanResult(vulnerabilities=[(dep, vuln)]) + json_output = reporter.report(result) + + data = json.loads(json_output) + assert len(data["vulnerabilities"]) == 1 + assert data["vulnerabilities"][0]["cve_id"] == "CVE-2021-23337" + + def test_get_exit_code_success(self): + """Test exit code 0 for clean result.""" + config = Config(fail_level=Severity.MEDIUM) + reporter = JSONReporter(config) + + result = ScanResult() + exit_code = reporter.get_exit_code(result) + + assert exit_code == 0 + + def test_get_exit_code_with_critical(self): + """Test exit code 1 for critical vulnerability.""" + config = Config(fail_level=Severity.MEDIUM) + reporter = JSONReporter(config) + + dep = Dependency( + name="lodash", + current_version="4.17.20", + package_manager=PackageManager.NPM, + ) + vuln = Vulnerability( + cve_id="CVE-2020-8203", + severity=Severity.CRITICAL, + description="Prototype Pollution", + affected_versions="<4.17.19", + ) + + result = ScanResult(vulnerabilities=[(dep, vuln)]) + exit_code = reporter.get_exit_code(result) + + assert exit_code == 1 + + def test_get_exit_code_with_errors(self): + """Test exit code 2 for errors.""" + config = Config() + reporter = JSONReporter(config) + + result = ScanResult(scan_errors=["Failed to parse file"]) + exit_code = reporter.get_exit_code(result) + + assert exit_code == 2 + + def test_fail_level_threshold(self): + """Test fail level threshold behavior.""" + config = Config(fail_level=Severity.HIGH) + reporter = JSONReporter(config) + + dep = Dependency( + name="requests", + current_version="2.30.0", + package_manager=PackageManager.PIP, + ) + vuln = Vulnerability( + cve_id="CVE-2024-35195", + severity=Severity.MEDIUM, + description="Auth bypass", + affected_versions="<2.32.0", + ) + + result = ScanResult(vulnerabilities=[(dep, vuln)]) + exit_code = reporter.get_exit_code(result) + + assert exit_code == 0 + + def test_exit_code_with_high_fail_level_high(self): + """Test exit code when fail level is HIGH and vulnerability is HIGH.""" + config = Config(fail_level=Severity.HIGH) + reporter = JSONReporter(config) + + dep = Dependency( + name="lodash", + current_version="4.17.20", + package_manager=PackageManager.NPM, + ) + vuln = Vulnerability( + cve_id="CVE-2021-23337", + severity=Severity.HIGH, + description="Command Injection", + affected_versions="<4.17.21", + ) + + result = ScanResult(vulnerabilities=[(dep, vuln)]) + exit_code = reporter.get_exit_code(result) + + assert exit_code == 1