feat(compliance): Gold Standard Deployment - Strict JSON, Stability Fixes, & Full Coverage Tests
66a0e97 | import asyncio | |
| import pytest | |
| from unittest.mock import MagicMock, AsyncMock, patch | |
| from app.utils.guvi_handler import GUVIHandler | |
| from app.api.schemas import GUVIInputRequest, GUVIOutputResponseInternal, GUVIEngagementMetrics, GUVIIntelligence | |
| # Mock objects | |
| mock_orchestrator = MagicMock() | |
| mock_orchestrator.initialized = True | |
| mock_orchestrator.conversation_manager.get_or_create = AsyncMock(return_value={"history": []}) | |
| mock_orchestrator.process_message = AsyncMock(return_value={ | |
| "conversation": {"message_count": 2}, | |
| "is_scam": True, | |
| "threat_level": "HIGH", | |
| "should_finalize": True, | |
| "aggregated_intelligence": {"sys_callback_sent": False} | |
| }) | |
| mock_orchestrator.conversation_manager.update_intelligence = AsyncMock() | |
| async def test_handshake_compliance(): | |
| """Test that handshake (message=None) returns strictly minimal reply and NO data.""" | |
| handler = GUVIHandler() | |
| # Mock orchestrator inside handler | |
| with patch("app.utils.guvi_handler.orchestrator", mock_orchestrator): | |
| request = GUVIInputRequest(sessionId="test-session", message=None) | |
| response = await handler.process_guvi_message(request) | |
| assert response.reply == "Hello?" | |
| assert response.data is None | |
| assert response.status == "success" | |
| async def test_callback_trigger_logic(): | |
| """Test that callback fires when total_messages >= 2 and scam detected.""" | |
| handler = GUVIHandler() | |
| mock_bg_tasks = MagicMock() | |
| # Mock orchestrator result for scam | |
| mock_orchestrator.process_message.return_value = { | |
| "conversation": {"message_count": 1}, # 1 turn = 2 messages | |
| "is_scam": True, | |
| "threat_level": "HIGH", | |
| "should_finalize": True, | |
| "aggregated_intelligence": {"sys_callback_sent": False}, | |
| "honeypot_response": "I am interested" | |
| } | |
| with patch("app.utils.guvi_handler.orchestrator", mock_orchestrator): | |
| # Mock callback client imports (target the SOURCE, since it's locally imported) | |
| with patch("app.utils.callback_client.guvi_callback") as mock_cb: | |
| with patch("app.utils.guvi_handler.get_session_state", return_value="active"): | |
| with patch("app.utils.guvi_handler.set_session_state"): | |
| request = GUVIInputRequest(sessionId="test-session", message={"text": "scam"}) | |
| await handler.process_guvi_message(request, background_tasks=mock_bg_tasks) | |
| # Verify Background Task Added | |
| mock_bg_tasks.add_task.assert_called_once() | |
| print("✅ Background task scheduled for callback") | |
| # Verify DB Update Mock | |
| mock_orchestrator.conversation_manager.update_intelligence.assert_called_with( | |
| "test-session", {"sys_callback_sent": True} | |
| ) | |
| print("✅ Intelligence updated (sys_callback_sent=True)") | |
| if __name__ == "__main__": | |
| # Manual run wrapper for environment without pytest | |
| loop = asyncio.get_event_loop() | |
| print("Running Handshake Test...") | |
| loop.run_until_complete(test_handshake_compliance()) | |
| print("Running Callback Trigger Test...") | |
| loop.run_until_complete(test_callback_trigger_logic()) | |
| print("🎉 ALL COMPLIANCE TESTS PASSED") | |