"""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", )