feat: тесты

This commit is contained in:
Artem Tsyrulnikov
2025-11-10 16:21:14 +03:00
parent cd167fdb43
commit b43042c745
13 changed files with 949 additions and 6 deletions

107
tests/test_auth.py Normal file
View File

@@ -0,0 +1,107 @@
"""Тесты авторизации через 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)