"""Тесты авторизации через Telegram.""" import datetime import pytest from fastapi import HTTPException from src import domain, dto, usecase from tests.conftest import MockDatabase, MockTelegramWriter @pytest.mark.asyncio async def test_new_user_registration(usecases: usecase.Usecase, mock_telegram: MockTelegramWriter) -> None: """Новый пользователь регистрируется через Telegram.""" input_data = dto.TelegramLoginInput(telegram_id=123456, username='testuser', chat_id=123456) await usecases.telegram_login(input_data) # Проверяем, что пользователь создан user = await usecases.database.get_user(telegram_id=123456) assert user is not None assert user.telegram_id == 123456 assert user.username == 'testuser' # Проверяем, что бот отправил сообщение с кнопкой assert len(mock_telegram.sent_messages) == 1 msg = mock_telegram.sent_messages[0] assert msg['button'] is not None assert 'token=' in msg['button']['url'] @pytest.mark.asyncio async def test_existing_user_login(usecases: usecase.Usecase, mock_database: MockDatabase) -> None: """Существующий пользователь получает токен для входа.""" # Создаём пользователя user = domain.User(telegram_id=123456, username='testuser') await mock_database.create_user(user) input_data = dto.TelegramLoginInput(telegram_id=123456, username='testuser', chat_id=123456) await usecases.telegram_login(input_data) # Проверяем, что не создался второй пользователь users_count = len(mock_database.users) assert users_count == 1 @pytest.mark.asyncio async def test_validate_login_token_success(usecases: usecase.Usecase, mock_database: MockDatabase) -> None: """Валидный токен обменивается на JWT.""" user = domain.User(telegram_id=123456, username='testuser') await mock_database.create_user(user) token = 'test_token_123' expires_at = datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=10) await mock_database.create_login_token(user.id, token, expires_at) result = await usecases.validate_login_token(dto.ValidateLoginTokenInput(token=token)) assert result.access_token.startswith('jwt_token_') assert str(user.id) in result.access_token # Проверяем, что токен помечен как использованный login_token = await mock_database.get_login_token(token) assert login_token is not None assert login_token.used_at is not None @pytest.mark.asyncio async def test_validate_login_token_not_found(usecases: usecase.Usecase) -> None: """Несуществующий токен вызывает ошибку.""" with pytest.raises(HTTPException) as exc_info: await usecases.validate_login_token(dto.ValidateLoginTokenInput(token='nonexistent')) assert exc_info.value.status_code == 404 assert 'Login token not found' in str(exc_info.value.detail) @pytest.mark.asyncio async def test_validate_login_token_already_used(usecases: usecase.Usecase, mock_database: MockDatabase) -> None: """Использованный токен вызывает ошибку.""" user = domain.User(telegram_id=123456, username='testuser') await mock_database.create_user(user) token = 'test_token_123' expires_at = datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=10) await mock_database.create_login_token(user.id, token, expires_at) await mock_database.mark_token_as_used(token) with pytest.raises(HTTPException) as exc_info: await usecases.validate_login_token(dto.ValidateLoginTokenInput(token=token)) assert exc_info.value.status_code == 400 assert 'already been used' in str(exc_info.value.detail) @pytest.mark.asyncio async def test_validate_login_token_expired(usecases: usecase.Usecase, mock_database: MockDatabase) -> None: """Истекший токен вызывает ошибку.""" user = domain.User(telegram_id=123456, username='testuser') await mock_database.create_user(user) token = 'test_token_123' expires_at = datetime.datetime.now(datetime.UTC) - datetime.timedelta(minutes=1) await mock_database.create_login_token(user.id, token, expires_at) with pytest.raises(HTTPException) as exc_info: await usecases.validate_login_token(dto.ValidateLoginTokenInput(token=token)) assert exc_info.value.status_code == 400 assert 'expired' in str(exc_info.value.detail)