minions-ai-agents/tests/test_onboarding.py

207 lines
7.0 KiB
Python

"""
Unit tests for the Onboarding module.
Tests time-aware greetings, user identification, and registration
logic without requiring external dependencies (Qdrant mock).
"""
import pytest
from unittest.mock import AsyncMock, MagicMock, patch
from datetime import datetime
# Import after mocking to avoid connection errors
import sys
sys.modules['src.clients'] = MagicMock()
from src.agents.onboarding import (
OnboardingManager,
UserProfile,
UserStatus,
)
class TestGetTimeGreeting:
"""Tests for get_time_greeting() function."""
@pytest.fixture
def onboarding(self):
"""Create OnboardingManager with mocked Qdrant."""
with patch('src.agents.onboarding.get_qdrant_client'):
manager = OnboardingManager()
return manager
def test_morning_greeting(self, onboarding):
"""Should return 'Bom dia' for morning hours (5-11)."""
with patch('src.agents.onboarding.datetime') as mock_dt:
mock_dt.now.return_value = datetime(2026, 2, 2, 9, 0, 0)
result = onboarding.get_time_greeting()
assert result == "Bom dia"
def test_afternoon_greeting(self, onboarding):
"""Should return 'Boa tarde' for afternoon hours (12-17)."""
with patch('src.agents.onboarding.datetime') as mock_dt:
mock_dt.now.return_value = datetime(2026, 2, 2, 15, 30, 0)
result = onboarding.get_time_greeting()
assert result == "Boa tarde"
def test_evening_greeting(self, onboarding):
"""Should return 'Boa noite' for evening hours (18-4)."""
with patch('src.agents.onboarding.datetime') as mock_dt:
mock_dt.now.return_value = datetime(2026, 2, 2, 20, 0, 0)
result = onboarding.get_time_greeting()
assert result == "Boa noite"
def test_late_night_greeting(self, onboarding):
"""Should return 'Boa noite' for late night (2am)."""
with patch('src.agents.onboarding.datetime') as mock_dt:
mock_dt.now.return_value = datetime(2026, 2, 2, 2, 0, 0)
result = onboarding.get_time_greeting()
assert result == "Boa noite"
class TestIsKnownUser:
"""Tests for is_known_user() function."""
@pytest.fixture
def onboarding(self):
"""Create OnboardingManager with mocked Qdrant."""
with patch('src.agents.onboarding.get_qdrant_client') as mock_qdrant:
manager = OnboardingManager()
manager._qdrant = mock_qdrant.return_value
return manager
@pytest.mark.asyncio
async def test_unknown_user_returns_false(self, onboarding):
"""Should return False for unknown telegram_id."""
onboarding._qdrant.scroll = AsyncMock(return_value=([], None))
result = await onboarding.is_known_user("999999999")
assert result is False
@pytest.mark.asyncio
async def test_known_user_returns_true(self, onboarding):
"""Should return True for registered user."""
mock_result = MagicMock()
mock_result.payload = {
"telegram_id": "123456",
"name": "João Silva",
"company": "iT Guys",
"tenant_id": "tenant_itguys",
"status": "registered",
"first_contact": "2026-01-01T10:00:00+00:00",
"last_contact": "2026-02-02T12:00:00+00:00",
"interaction_count": 5
}
onboarding._qdrant.scroll = AsyncMock(return_value=([mock_result], None))
result = await onboarding.is_known_user("123456")
assert result is True
class TestStartRegistration:
"""Tests for start_registration() function."""
@pytest.fixture
def onboarding(self):
"""Create OnboardingManager with mocked Qdrant."""
with patch('src.agents.onboarding.get_qdrant_client'):
manager = OnboardingManager()
return manager
def test_returns_welcome_message(self, onboarding):
"""Should return welcome message with greeting."""
with patch.object(onboarding, 'get_time_greeting', return_value="Boa tarde"):
result = onboarding.start_registration("123456")
assert "Boa tarde" in result
assert "nome" in result.lower()
assert "empresa" in result.lower()
def test_marks_user_as_pending(self, onboarding):
"""Should mark user as pending registration."""
onboarding.start_registration("123456")
assert onboarding.is_pending_registration("123456") is True
def test_unknown_user_not_pending(self, onboarding):
"""Unknown user should not be pending."""
assert onboarding.is_pending_registration("999999") is False
class TestUserProfile:
"""Tests for UserProfile dataclass."""
def test_to_dict_serialization(self):
"""Should serialize to dictionary correctly."""
profile = UserProfile(
telegram_id="123",
name="João",
company="iT Guys",
tenant_id="tenant_itguys",
status=UserStatus.REGISTERED,
first_contact=datetime(2026, 1, 1, 10, 0, 0),
last_contact=datetime(2026, 2, 2, 12, 0, 0)
)
result = profile.to_dict()
assert result["telegram_id"] == "123"
assert result["status"] == "registered"
assert "2026-01-01" in result["first_contact"]
def test_from_dict_deserialization(self):
"""Should deserialize from dictionary correctly."""
data = {
"telegram_id": "123",
"name": "Maria",
"company": "OESTEPAN",
"tenant_id": None,
"status": "non_client",
"first_contact": "2026-01-15T09:00:00",
"last_contact": "2026-01-15T09:00:00"
}
profile = UserProfile.from_dict(data)
assert profile.name == "Maria"
assert profile.status == UserStatus.NON_CLIENT
assert profile.tenant_id is None
class TestBuildGreeting:
"""Tests for build_greeting() function."""
@pytest.fixture
def onboarding(self):
"""Create OnboardingManager with mocked Qdrant."""
with patch('src.agents.onboarding.get_qdrant_client'):
manager = OnboardingManager()
return manager
def test_greeting_with_first_name(self, onboarding):
"""Should greet user by first name."""
profile = UserProfile(
telegram_id="123",
name="João Carlos Silva",
company="iT Guys",
tenant_id="tenant_itguys",
status=UserStatus.REGISTERED,
first_contact=datetime.now(),
last_contact=datetime.now()
)
with patch.object(onboarding, 'get_time_greeting', return_value="Bom dia"):
result = onboarding.build_greeting(profile)
assert "Bom dia, João!" in result