import csv import json import tempfile import unittest from pathlib import Path from netscaler_triage.presentation import present_results class PresentationTests(unittest.TestCase): def test_matches_are_separate_from_context_and_evidence_is_preserved(self) -> None: with tempfile.TemporaryDirectory() as temporary: output = Path(temporary) events = [ {"id": 1, "rules": [], "categories": ["update"]}, {"id": 2, "rules": [], "analysis_errors": ["timeout"]}, { "id": 3, "rules": ["probe"], "source": "=unsafe", "rule_details": [{"description": "A command probe, not execution."}], "indicator_matches": [{"status": "authorized_test"}], }, ] original = "".join(json.dumps(event) + "\n" for event in events) (output / "findings.jsonl").write_text(original) (output / "summary.json").write_text('{"status":"partial"}') (output / "IOCS.csv").write_text("type,value\n") (output / "inputs").mkdir() present_results(output, {"status": "partial", "counts": {"records": 3}}) with (output / "FINDINGS.csv").open() as handle: rows = list(csv.DictReader(handle)) self.assertEqual(len(rows), 1) self.assertEqual(rows[0]["event_id"], "3") self.assertEqual(rows[0]["source"], "'=unsafe") self.assertEqual(rows[0]["indicator_status"], "authorized_test") self.assertEqual((output / "details/findings.jsonl").read_text(), original) self.assertIn("Processing status: partial", (output / "SUMMARY.txt").read_text()) self.assertEqual( {path.name for path in output.iterdir()}, {"SUMMARY.txt", "FINDINGS.csv", "IOCS.csv", "details", "inputs"}, ) def test_no_matches_is_not_a_clean_verdict(self) -> None: with tempfile.TemporaryDirectory() as temporary: output = Path(temporary) (output / "findings.jsonl").write_text("") present_results(output, {"status": "complete"}) self.assertIn("No matches does not prove", (output / "SUMMARY.txt").read_text()) def test_file_hash_hit_is_visible_without_an_event_match(self) -> None: with tempfile.TemporaryDirectory() as temporary: output = Path(temporary) (output / "findings.jsonl").write_text("") hits = [{"source": "sample.bin", "basis": "original file SHA-256"}] (output / "file_hash_hits.json").write_text(json.dumps(hits)) present_results(output, {"status": "complete", "counts": {"file_hash_hits": 1}}) text = (output / "SUMMARY.txt").read_text() self.assertIn("Events matching a rule or indicator: 0", text) self.assertIn("Original-file SHA-256 indicator matches: 1", text) self.assertIn("details/file_hash_hits.json", text) self.assertEqual(json.loads((output / "details/file_hash_hits.json").read_text()), hits)