172 lines
5.7 KiB
Python
172 lines
5.7 KiB
Python
"""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.get_session = AsyncMock()
|
|
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_redis.get_session.return_value = None # No session in Redis
|
|
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_redis.get_session.assert_called_once_with("555-1234")
|
|
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_redis.get_session.return_value = None # Not in Redis cache
|
|
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_redis.get_session.assert_called_once_with("555-1234")
|
|
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",
|
|
)
|