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