108 lines
4.6 KiB
Python
108 lines
4.6 KiB
Python
"""Тесты авторизации через 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)
|