1
+"""Tests for SubmitReportRequest body-completeness validation.
2
+
3
+A report submitted without its human-readable body fields must be rejected, not
4
+silently persisted as a blank row. These are pure Pydantic-model tests — no DB
5
+or app wiring required.
6
+
7
+Run with: cd backend && pip install pytest && python -m pytest tests/
8
+"""
9
+
10
+import pytest
11
+from pydantic import ValidationError
12
+
13
+from app.ai_analyst.schema.ai_analyst import SubmitReportRequest
14
+
15
+COMPLETE = dict(
16
+ job_id="copilot-inv-1-abc",
17
+ alert_id=1,
18
+ customer_code="acme",
19
+ severity_assessment="High",
20
+ summary="Short tl;dr.",
21
+ report_markdown="# Full report\n\nDetails.",
22
+ recommended_actions="Isolate host.",
23
+)
24
+
25
+
26
+def test_complete_report_is_accepted():
27
+ req = SubmitReportRequest(**COMPLETE)
28
+ assert req.report_markdown == "# Full report\n\nDetails."
29
+
30
+
31
+@pytest.mark.parametrize("field", ["severity_assessment", "summary", "report_markdown", "recommended_actions"])
32
+def test_missing_body_field_is_rejected(field):
33
+ payload = {k: v for k, v in COMPLETE.items() if k != field}
34
+ with pytest.raises(ValidationError) as excinfo:
35
+ SubmitReportRequest(**payload)
36
+ assert field in str(excinfo.value)
37
+
38
+
39
+@pytest.mark.parametrize("field", ["summary", "report_markdown", "recommended_actions"])
40
+def test_blank_or_whitespace_body_field_is_rejected(field):
41
+ payload = {**COMPLETE, field: " "}
42
+ with pytest.raises(ValidationError) as excinfo:
43
+ SubmitReportRequest(**payload)
44
+ assert field in str(excinfo.value)
45
+
46
+
47
+def test_control_chars_only_body_is_rejected():
48
+ # strip_control_characters collapses this to "" before require_report_body runs.
49
+ payload = {**COMPLETE, "report_markdown": "\x00\x01\x02"}
50
+ with pytest.raises(ValidationError) as excinfo:
51
+ SubmitReportRequest(**payload)
52
+ assert "report_markdown" in str(excinfo.value)
53
+
54
+
55
+def test_minimal_call_missing_all_bodies_is_rejected():
56
+ # The exact failure mode from production: agent sends only the identifiers.
57
+ with pytest.raises(ValidationError):
58
+ SubmitReportRequest(job_id="j", alert_id=1, customer_code="acme")