feat: add webhook case management
This commit is contained in:
@@ -3,12 +3,102 @@ from __future__ import annotations
|
||||
import json
|
||||
import tempfile
|
||||
import unittest
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from cold_display_guard.main import restore_runtime_state
|
||||
from cold_display_guard.cases import CaseStore
|
||||
from cold_display_guard.main import case_sink_path, deliver_runtime_webhooks, persist_case_updates, restore_runtime_state
|
||||
|
||||
|
||||
UTC = timezone.utc
|
||||
|
||||
|
||||
class RuntimeRestoreTests(unittest.TestCase):
|
||||
def test_case_sink_path_uses_default_logs_location(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
root = Path(tmpdir)
|
||||
|
||||
path = case_sink_path(root, {})
|
||||
|
||||
self.assertEqual(path, (root / "logs" / "cases.jsonl").resolve())
|
||||
|
||||
def test_persist_case_updates_writes_case_snapshots(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
path = Path(tmpdir) / "cases.jsonl"
|
||||
store = CaseStore()
|
||||
|
||||
snapshots = persist_case_updates(
|
||||
store,
|
||||
path,
|
||||
[
|
||||
{
|
||||
"event": "time_alarm",
|
||||
"ts": datetime(2026, 6, 9, 9, 0, tzinfo=UTC).isoformat(),
|
||||
"batch_id": "batch_000001",
|
||||
"camera_id": "cam_01",
|
||||
"zone_id": "1",
|
||||
"zone_label": "区域 1",
|
||||
"severity": "alarm",
|
||||
"state": "alerted",
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
written = [json.loads(line) for line in path.read_text(encoding="utf-8").splitlines()]
|
||||
|
||||
self.assertEqual(len(snapshots), 1)
|
||||
self.assertEqual(written[0]["case_type"], "time_alarm")
|
||||
self.assertEqual(written[0]["case_status"], "open")
|
||||
|
||||
def test_deliver_runtime_webhooks_sends_event_and_case_payloads(self) -> None:
|
||||
deliveries: list[tuple[str, dict[str, object]]] = []
|
||||
|
||||
def fake_post(url: str, payload: dict[str, object], timeout: tuple[float, float]) -> tuple[int, str]:
|
||||
deliveries.append((url, payload))
|
||||
return 200, "ok"
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
audit_path = Path(tmpdir) / "webhook_delivery.jsonl"
|
||||
deliver_runtime_webhooks(
|
||||
[
|
||||
{
|
||||
"event": "time_alarm",
|
||||
"ts": datetime(2026, 6, 9, 9, 0, tzinfo=UTC).isoformat(),
|
||||
"batch_id": "batch_000001",
|
||||
"camera_id": "cam_01",
|
||||
"zone_id": "1",
|
||||
"zone_label": "区域 1",
|
||||
"severity": "alarm",
|
||||
"state": "alerted",
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"case_id": "case_batch_000001",
|
||||
"batch_id": "batch_000001",
|
||||
"case_type": "time_alarm",
|
||||
"case_status": "open",
|
||||
"source_event": "time_alarm",
|
||||
"handled_source": "",
|
||||
"created_at": datetime(2026, 6, 9, 9, 0, tzinfo=UTC).isoformat(),
|
||||
"updated_at": datetime(2026, 6, 9, 9, 0, tzinfo=UTC).isoformat(),
|
||||
}
|
||||
],
|
||||
{
|
||||
"webhooks": {
|
||||
"enabled": True,
|
||||
"event_url": "https://example.com/events",
|
||||
"case_url": "https://example.com/cases",
|
||||
}
|
||||
},
|
||||
audit_path,
|
||||
http_post=fake_post,
|
||||
)
|
||||
|
||||
self.assertEqual(len(deliveries), 2)
|
||||
self.assertEqual(deliveries[0][1]["kind"], "batch_event")
|
||||
self.assertEqual(deliveries[1][1]["kind"], "case_event")
|
||||
|
||||
def test_restore_runtime_state_uses_stable_occupancy_when_raw_metrics_flicker(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
diagnostics_path = Path(tmpdir) / "runtime_diagnostics.jsonl"
|
||||
|
||||
Reference in New Issue
Block a user