Files
ai-exchange/tests/unit/test_visual_snapshot_capture_service.py
T
2026-05-12 07:57:13 +08:00

111 lines
4.5 KiB
Python

import tempfile
import unittest
from pathlib import Path
from src.services.visual_watch.snapshot_capture_service import VisualSnapshotCaptureService
class VisualSnapshotCaptureServiceTests(unittest.TestCase):
def test_capture_watch_run_snapshot_writes_html_and_manifest(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
service = VisualSnapshotCaptureService(
review_packet_service=_ReviewPacketService(),
output_root=Path(tmp),
browser_capture_enabled=False,
)
result = service.capture_watch_run_snapshot(
watch_run={
"id": 11,
"trigger_type": "candidate_actionable_watch",
"instrument_id": 1,
"candidate_id": 22,
"signal_id": 33,
"decision_packet_id": 44,
"symbol": "BTC-USDT",
"timeframe": "1m",
"status": "reserved",
},
source_name="unit_capture",
)
self.assertEqual(result["status"], "captured")
self.assertEqual(result["capture_mode"], "review_packet_html")
self.assertEqual(result["browser_capture_status"], "disabled")
self.assertEqual(result["source_name"], "unit_capture")
self.assertTrue(Path(result["image_path"]).is_file())
self.assertTrue(Path(result["html_path"]).is_file())
self.assertTrue(Path(result["artifact_path"]).is_file())
html = Path(result["image_path"]).read_text(encoding="utf-8")
self.assertIn("Visual Watch Snapshot", html)
self.assertIn("BTC-USDT", html)
self.assertIn("confirm_ticket", html)
self.assertEqual(result["payload"]["review_packet_summary"]["recent_alert_count"], 1)
def test_capture_watch_run_snapshot_can_write_browser_screenshot(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
def fake_browser_capture(*, url, screenshot_path, viewport):
Path(screenshot_path).write_bytes(b"\x89PNG\r\n\x1a\nunit")
return {
"status": "captured",
"url": url,
"image_path": str(screenshot_path),
"viewport": viewport or {},
}
service = VisualSnapshotCaptureService(
review_packet_service=_ReviewPacketService(),
output_root=Path(tmp),
browser_capture_func=fake_browser_capture,
)
result = service.capture_watch_run_snapshot(
watch_run={
"id": 12,
"trigger_type": "candidate_actionable_watch",
"instrument_id": 1,
"decision_packet_id": 44,
"symbol": "BTC-USDT",
"timeframe": "1m",
"status": "reserved",
},
source_name="unit_browser_capture",
viewport={"width": 800, "height": 600},
)
self.assertEqual(result["status"], "captured")
self.assertEqual(result["capture_mode"], "browser_screenshot")
self.assertEqual(result["browser_capture_status"], "captured")
self.assertTrue(str(result["image_path"]).endswith(".png"))
self.assertTrue(Path(result["screenshot_path"]).is_file())
self.assertTrue(Path(result["html_path"]).is_file())
self.assertEqual(result["payload"]["browser_capture"]["status"], "captured")
class _ReviewPacketService:
def build_packet(self, *, instrument_id: int) -> dict:
return {
"instrument_id": instrument_id,
"generated_ts": "2026-05-11T01:00:00+00:00",
"decision_packet": {
"id": 44,
"status": "actionable",
"action_recommendation": "confirm_ticket",
},
"recent_alerts": [{"id": 1}],
"recent_notes": [{"id": 2}],
"recent_executions": [{"id": 3}],
"weekly_review": {"entry_count": 4},
"trust_score": {"models": [{"model_code": "research_council"}]},
"research_council": {"id": 31},
"research_council_summary": {
"present": True,
"overall_stance": "observe_only",
},
"research_council_optimization_review": {"health_state": "healthy"},
}
if __name__ == "__main__":
unittest.main()