# #region Test.Schemas.Health [C:2] [TYPE Module] [SEMANTICS test,schema,health] # @BRIEF Tests for schemas/health.py — DashboardHealthItem, HealthSummaryResponse. # @RELATION BINDS_TO -> [HealthSchemas] # @TEST_EDGE: missing_field -> optional fields default correctly # @TEST_EDGE: invalid_type -> status pattern validation rejects bad values # @TEST_EDGE: serialization -> round-trip via model_dump/model_validate from datetime import datetime, timezone import pytest from pydantic import ValidationError from src.schemas.health import DashboardHealthItem, HealthSummaryResponse class TestDashboardHealthItem: """DashboardHealthItem — health status for a single dashboard.""" def make_item(self, **overrides): ts = datetime.now(timezone.utc) defaults = dict( dashboard_id="42", environment_id="env-1", status="PASS", last_check=ts, ) defaults.update(overrides) return DashboardHealthItem(**defaults) def test_minimal(self): item = self.make_item() assert item.dashboard_id == "42" assert item.environment_id == "env-1" assert item.status == "PASS" assert item.record_id is None assert item.dashboard_slug is None assert item.task_id is None assert item.run_id is None assert item.execution_path is None assert item.issues_count == 0 assert item.timings is None assert item.token_usage is None assert item.screenshot_paths is None assert item.chunk_count is None assert item.dashboard_name is None @pytest.mark.parametrize("status", ["PASS", "WARN", "FAIL", "UNKNOWN"]) def test_valid_status_values(self, status): item = self.make_item(status=status) assert item.status == status def test_invalid_status_raises(self): with pytest.raises(ValidationError, match="pattern"): self.make_item(status="INVALID") def test_lowercase_status_raises(self): with pytest.raises(ValidationError): self.make_item(status="pass") def test_with_all_v2_fields(self): ts = datetime.now(timezone.utc) item = DashboardHealthItem( record_id="rec-1", dashboard_id="42", environment_id="env-1", status="WARN", last_check=ts, task_id="task-1", run_id="run-1", policy_id="pol-1", summary="Some warnings", execution_path="screenshot", issues_count=3, timings={"total": 12.5}, token_usage={"prompt": 100}, screenshot_paths=["/screens/1.png"], chunk_count=4, dashboard_name="Sales Dashboard", ) assert item.record_id == "rec-1" assert item.execution_path == "screenshot" assert item.issues_count == 3 assert item.chunk_count == 4 def test_serialize_roundtrip(self): item = self.make_item() data = item.model_dump() restored = DashboardHealthItem.model_validate(data) assert restored.dashboard_id == "42" assert restored.status == "PASS" def test_timings_token_usage_optional(self): item = self.make_item(timings={"db": 1.0}, token_usage={"total": 50}) assert item.timings == {"db": 1.0} assert item.token_usage == {"total": 50} class TestHealthSummaryResponse: """HealthSummaryResponse — aggregated health summary.""" def test_empty(self): resp = HealthSummaryResponse(items=[], pass_count=0, warn_count=0, fail_count=0, unknown_count=0) assert resp.items == [] assert resp.pass_count == 0 def test_with_items(self): ts = datetime.now(timezone.utc) items = [ DashboardHealthItem(dashboard_id="1", environment_id="e1", status="PASS", last_check=ts), DashboardHealthItem(dashboard_id="2", environment_id="e1", status="FAIL", last_check=ts), ] resp = HealthSummaryResponse(items=items, pass_count=1, warn_count=0, fail_count=1, unknown_count=0) assert len(resp.items) == 2 assert resp.pass_count == 1 assert resp.fail_count == 1 def test_serialize_roundtrip(self): ts = datetime.now(timezone.utc) items = [DashboardHealthItem(dashboard_id="1", environment_id="e1", status="PASS", last_check=ts)] resp = HealthSummaryResponse(items=items, pass_count=1, warn_count=0, fail_count=0, unknown_count=0) data = resp.model_dump() restored = HealthSummaryResponse.model_validate(data) assert restored.pass_count == 1 assert len(restored.items) == 1 # #endregion Test.Schemas.Health