"""Unit tests for the TenzaiValidationSummary dynamic-section results panel."""
from TenzaiValidationSummary import _severity_counts, build_summary_html
FINDINGS = [{"finding": f"Medium finding {i}", "severity": "Medium", "detail": "x"} for i in range(6)] + [
{"finding": f"Low finding {i}", "severity": "Low", "detail": "y"} for i in range(3)
]
COMPLETE_FIELDS = {
"tenzaiassessmentstatus": "Complete",
"tenzaiissuevalidated": "true",
"tenzaicreditusage": 48.41,
"tenzaireferenceurl": "https://app.tenzai.io/checks/abc",
"tenzaifindings": FINDINGS,
}
def test_severity_counts_tallies_by_level():
counts = _severity_counts(FINDINGS)
assert counts["Medium"] == 6
assert counts["Low"] == 3
assert counts["High"] == 0
assert counts["Critical"] == 0
def test_severity_counts_tolerates_emoji_and_case():
counts = _severity_counts([{"severity": "🟠High"}, {"severity": "critical"}, {"severity": " Low "}])
assert counts["High"] == 1
assert counts["Critical"] == 1
assert counts["Low"] == 1
def test_build_summary_html_complete_validated():
html = build_summary_html(COMPLETE_FIELDS)
assert "Tenzai validation" in html
assert "Assessment complete" in html
# The verdict lives in the "Result" stat cell (Figma has no hero headline).
assert ">Result<" in html
assert "Exposure Exploit<" not in html # the old Exploit cell is dropped (Figma stat card)
# Severity renders as the Figma "Findings severity" badge row.
assert "Findings severity" in html
assert "48.41 ACU" in html
assert "https://app.tenzai.io/checks/abc" in html
assert "View in Tenzai" in html
# The panel lists each finding (title) under a "Findings confirmed" section.
assert "Findings confirmed" in html
assert "Medium finding 0" in html
assert "Low finding 0" in html
# Findings render as expandable disclosures (no separate grid).
assert " (the entry sanitizer strips them).
assert "" in findings_cell
assert ">2" not in findings_cell
assert "Findings severity" in html
def test_no_extra_sections_when_all_findings_are_own():
"""With only own findings, neither the discovered nor the unverified section renders."""
html = build_summary_html(COMPLETE_FIELDS)
assert "Findings confirmed" in html
assert "Discovered during validation" not in html
assert "correlation unverified" not in html
def test_reference_and_agent_log_links_render_in_header():
"""Reference + agent log are header actions, not strip cells; the agent log derives /findings -> /log."""
fields = {**COMPLETE_FIELDS, "tenzaireferenceurl": "https://app.tenzai.io/apps/a/tests/b/findings"}
html = build_summary_html(fields)
assert "View in Tenzai" in html
assert "View agent log" in html
assert "/apps/a/tests/b/log" in html
def test_verification_step_payload_renders_as_monospace_block():
"""A numbered step ending in ': `payload`' lifts the payload into its own code block."""
rationale = "## Description\n\n1. Probe the host with a payload: `GET /cgi-bin/.%2e/etc/passwd HTTP/1.1`"
html = build_summary_html({**COMPLETE_FIELDS, "tenzaiissuerationale": rationale})
assert "GET /cgi-bin/.%2e/etc/passwd HTTP/1.1" in html
def test_hard_broken_lines_share_one_paragraph():
"""Markdown hard breaks (two trailing spaces) keep related lines in one -joined paragraph,
not one gapped paragraph per line — so header fields render tight like the Tenzai app."""
rationale = (
"## Description\n\n**CVE:** CVE-2024-23897 \n**Reported Severity:** Critical \n**Affected Asset:** http://192.0.2.10:80"
)
html = build_summary_html({**COMPLETE_FIELDS, "tenzaiissuerationale": rationale})
# The three fields are one paragraph joined by , not three separate margin'd divs.
assert "CVE-2024-23897 " in html
assert "Reported Severity: Critical " in html
def test_long_rationale_keeps_all_verification_steps():
"""A full exposure assessment (all 5 verification steps + preconditions) is not truncated, and
truncation — when it does occur — lands on a whole-line boundary, never mid-step."""
steps = "\n".join(f"{i}. Verification step number {i} with enough words to add length." for i in range(1, 6))
rationale = f"## Description\n\n**Vulnerability Description:** \nA long narrative. {'x ' * 200}\n\n{steps}"
html = build_summary_html({**COMPLETE_FIELDS, "tenzaiissuerationale": rationale})
for i in range(1, 6):
assert f"Verification step number {i}" in html
def test_header_renders_logo_lockup():
"""The compact header renders the Tenzai logo (base64 ) beside the 'Tenzai validation'
wordline; both are present."""
from TenzaiValidationSummary import LOGO_DATA_URI
html = build_summary_html(COMPLETE_FIELDS)
assert "Tenzai validation" in html
assert " is stripped by the entry sanitizer.
assert "