Misc improvements

This commit is contained in:
2026-02-20 06:59:31 +00:00
committed by Anibal Angulo
parent 6edbca98bd
commit 29dc5ca851
33 changed files with 1844 additions and 420 deletions

View File

@@ -0,0 +1,166 @@
"""Tests for QuickReplySessionService."""
from unittest.mock import AsyncMock, Mock
from uuid import uuid4
import pytest
from capa_de_integracion.models.conversation import ConversationSession
from capa_de_integracion.models.quick_replies import QuickReplyScreen
from capa_de_integracion.services import QuickReplySessionService
from capa_de_integracion.services.quick_reply.content import QuickReplyContentService
from capa_de_integracion.services.storage.firestore import FirestoreService
from capa_de_integracion.services.storage.redis import RedisService
@pytest.fixture
def mock_redis():
"""Create mock Redis service."""
redis = Mock(spec=RedisService)
redis.save_session = AsyncMock()
return redis
@pytest.fixture
def mock_firestore():
"""Create mock Firestore service."""
firestore = Mock(spec=FirestoreService)
firestore.get_session_by_phone = AsyncMock()
firestore.create_session = AsyncMock()
firestore.update_pantalla_contexto = AsyncMock()
return firestore
@pytest.fixture
def mock_content():
"""Create mock QuickReplyContentService."""
content = Mock(spec=QuickReplyContentService)
content.get_quick_replies = AsyncMock()
return content
@pytest.fixture
def service(mock_redis, mock_firestore, mock_content):
"""Create QuickReplySessionService instance."""
return QuickReplySessionService(
redis_service=mock_redis,
firestore_service=mock_firestore,
quick_reply_content_service=mock_content,
)
@pytest.mark.asyncio
async def test_validate_phone_empty_string(service):
"""Test phone validation with empty string."""
with pytest.raises(ValueError, match="Phone number is required"):
service._validate_phone("")
@pytest.mark.asyncio
async def test_validate_phone_whitespace(service):
"""Test phone validation with whitespace only."""
with pytest.raises(ValueError, match="Phone number is required"):
service._validate_phone(" ")
@pytest.mark.asyncio
async def test_start_session_new_user(service, mock_firestore, mock_redis, mock_content):
"""Test starting a quick reply session for a new user."""
# Setup mocks
mock_firestore.get_session_by_phone.return_value = None # No existing session
# Mock create_session to return a session with the ID that was passed in
def create_session_side_effect(session_id, user_id, telefono, pantalla_contexto):
return ConversationSession.create(
session_id=session_id,
user_id=user_id,
telefono=telefono,
pantalla_contexto=pantalla_contexto,
)
mock_firestore.create_session.side_effect = create_session_side_effect
test_quick_replies = QuickReplyScreen(
header="Home Screen",
body=None,
button=None,
header_section=None,
preguntas=[],
)
mock_content.get_quick_replies.return_value = test_quick_replies
# Execute
result = await service.start_quick_reply_session(
telefono="555-1234",
_nombre="John",
pantalla_contexto="home",
)
# Verify
assert result.session_id is not None # Session ID should be generated
assert result.quick_replies.header == "Home Screen"
mock_firestore.get_session_by_phone.assert_called_once_with("555-1234")
mock_firestore.create_session.assert_called_once()
# Verify create_session was called with correct parameters
call_args = mock_firestore.create_session.call_args
assert call_args[0][2] == "555-1234" # telefono
assert call_args[0][3] == "home" # pantalla_contexto
mock_redis.save_session.assert_called_once()
mock_content.get_quick_replies.assert_called_once_with("home")
@pytest.mark.asyncio
async def test_start_session_existing_user(service, mock_firestore, mock_redis, mock_content):
"""Test starting a quick reply session for an existing user."""
# Setup mocks - existing session
test_session_id = "existing-session-123"
test_session = ConversationSession.create(
session_id=test_session_id,
user_id="user_by_phone_5551234",
telefono="555-1234",
pantalla_contexto="old_screen",
)
mock_firestore.get_session_by_phone.return_value = test_session
test_quick_replies = QuickReplyScreen(
header="Payments Screen",
body=None,
button=None,
header_section=None,
preguntas=[],
)
mock_content.get_quick_replies.return_value = test_quick_replies
# Execute
result = await service.start_quick_reply_session(
telefono="555-1234",
_nombre="John",
pantalla_contexto="pagos",
)
# Verify
assert result.session_id == test_session_id
assert result.quick_replies.header == "Payments Screen"
mock_firestore.get_session_by_phone.assert_called_once_with("555-1234")
mock_firestore.update_pantalla_contexto.assert_called_once_with(
test_session_id,
"pagos",
)
mock_firestore.create_session.assert_not_called()
mock_redis.save_session.assert_called_once()
mock_content.get_quick_replies.assert_called_once_with("pagos")
@pytest.mark.asyncio
async def test_start_session_invalid_phone(service):
"""Test starting session with invalid phone number."""
with pytest.raises(ValueError, match="Phone number is required"):
await service.start_quick_reply_session(
telefono="",
_nombre="John",
pantalla_contexto="home",
)