autoscan / tests /test_html_report.py
Chris4K's picture
Upload 384 files
a2a5bfd verified
"""Tests for report.html — generate_html_report, _aggregate, _render_finding."""
import pytest
from report.html import generate_html_report
def _finding(**kwargs) -> dict:
defaults = dict(
tool="bandit", rule="B101", severity="WARNING",
confidence="likely", file="test.py", line=10,
message="Shell injection risk",
owasp=["A01:2021-Broken_Access_Control"],
category="security",
remediation="Use subprocess.run without shell=True",
)
defaults.update(kwargs)
return defaults
class TestGenerateHtmlReport:
def test_returns_string(self):
html = generate_html_report([], {})
assert isinstance(html, str)
def test_contains_html_tag(self):
html = generate_html_report([], {})
assert "<html" in html.lower() or "<!doctype" in html.lower()
def test_empty_findings_produces_zero_count(self):
html = generate_html_report([], {"title": "Empty Test"})
# Zero counts should appear somewhere
assert "0" in html
def test_finding_message_in_output(self):
f = _finding(message="Hardcoded password detected")
html = generate_html_report([f], {})
assert "Hardcoded password detected" in html
def test_owasp_badge_rendered(self):
f = _finding(owasp=["A01:2021-Broken_Access_Control"])
html = generate_html_report([f], {})
assert "A01" in html
def test_unmapped_owasp_excluded_from_badge(self):
f = _finding(owasp=["UNMAPPED"])
html = generate_html_report([f], {})
assert "UNMAPPED" not in html
def test_remediation_rendered(self):
f = _finding(remediation="Upgrade the vulnerable dependency to >=2.0")
html = generate_html_report([f], {})
assert "Upgrade the vulnerable dependency" in html
def test_finding_without_remediation(self):
f = _finding(remediation="")
html = generate_html_report([f], {})
assert isinstance(html, str)
def test_severity_high_preserved(self):
f = _finding(severity="HIGH")
html = generate_html_report([f], {})
assert "HIGH" in html
def test_severity_medium_preserved(self):
f = _finding(severity="MEDIUM")
html = generate_html_report([f], {})
assert "MEDIUM" in html
def test_severity_low_preserved(self):
f = _finding(severity="LOW")
html = generate_html_report([f], {})
assert "LOW" in html
def test_error_severity_class(self):
f = _finding(severity="ERROR")
html = generate_html_report([f], {})
assert "error" in html
def test_performance_finding_in_perf_section(self):
f = _finding(category="performance", rule="PERF401", severity="WARNING")
html = generate_html_report([f], {})
assert "performance" in html.lower() or "PERF" in html
def test_footer_text_in_output(self):
html = generate_html_report([], {"footer": "MyCustomScanner v1.0"})
assert "MyCustomScanner v1.0" in html
def test_tool_and_rule_in_output(self):
f = _finding(tool="myTool", rule="MY-RULE-001")
html = generate_html_report([f], {})
assert "myTool" in html
assert "MY-RULE-001" in html
def test_file_and_line_in_output(self):
f = _finding(file="src/auth.py", line=42)
html = generate_html_report([f], {})
assert "src/auth.py" in html
assert "42" in html
def test_multiple_findings(self):
findings = [
_finding(severity="ERROR", message="Critical issue"),
_finding(severity="WARNING", message="Medium issue"),
_finding(severity="INFO", message="Low issue"),
]
html = generate_html_report(findings, {})
assert "Critical issue" in html
assert "Medium issue" in html
assert "Low issue" in html
def test_owasp_summary_section_generated(self):
findings = [_finding(owasp=["A01:2021-Broken_Access_Control"]) for _ in range(3)]
html = generate_html_report(findings, {})
assert "A01" in html
def test_xss_in_message_escaped(self):
f = _finding(message='<script>alert("xss")</script>')
html = generate_html_report([f], {})
# The raw script tag should be HTML-escaped
assert "<script>" not in html
def test_severity_counts_in_output(self):
findings = [
_finding(severity="ERROR"),
_finding(severity="ERROR"),
_finding(severity="WARNING"),
]
html = generate_html_report(findings, {})
# Should contain numbers for each severity count
assert "2" in html
assert "1" in html