oauth+tests
All checks were successful
Deploy on push / deploy (push) Successful in 6m56s

This commit is contained in:
2025-09-23 20:49:25 +03:00
parent e0f3272bed
commit bf9515dd39
4 changed files with 423 additions and 27 deletions

View File

@@ -1,4 +1,4 @@
from unittest.mock import AsyncMock, MagicMock, patch
from unittest.mock import AsyncMock, MagicMock, patch, ANY
import time
import pytest
@@ -117,10 +117,29 @@ with (
@pytest.mark.asyncio
async def test_oauth_login_success(mock_request, mock_oauth_client):
"""Тест успешного начала OAuth авторизации"""
# pytest.skip("OAuth тест временно отключен из-за проблем с Redis")
# TODO: Implement test logic
assert True # Placeholder assertion
"""Тест успешного начала OAuth авторизации без SessionMiddleware"""
mock_request.path_params = {"provider": "google"}
# Мокаем OAuth клиент
with patch("auth.oauth.oauth.create_client", return_value=mock_oauth_client):
# Мокаем create_authorization_url как async функцию
mock_oauth_client.create_authorization_url = AsyncMock(return_value={
"url": "https://accounts.google.com/oauth/authorize?client_id=test&state=test_state"
})
# Мокаем Redis операции
with patch("auth.oauth.store_oauth_state") as mock_store:
response = await oauth_login_http(mock_request)
# Проверяем что это редирект
assert isinstance(response, RedirectResponse)
assert response.status_code == 302
# Проверяем что состояние сохранено в Redis
mock_store.assert_called_once()
# Проверяем что create_authorization_url вызван с правильными параметрами
mock_oauth_client.create_authorization_url.assert_called_once()
@pytest.mark.asyncio
async def test_oauth_login_invalid_provider(mock_request):
@@ -138,28 +157,71 @@ with (
@pytest.mark.asyncio
async def test_oauth_callback_success(mock_request, mock_oauth_client, oauth_db_session):
"""Тест успешного OAuth callback с правильной БД"""
# Простой тест без сложных моков - проверяем только импорт и базовую функциональность
from auth.oauth import oauth_callback_http
"""Тест успешного OAuth callback без SessionMiddleware"""
# Настраиваем mock request
mock_request.query_params = {
"state": "test_state",
"code": "test_code"
}
mock_request.url = "https://localhost:3000/oauth/google/callback?state=test_state&code=test_code"
mock_request.headers = {"user-agent": "test-agent"}
mock_request.client = MagicMock()
mock_request.client.host = "127.0.0.1"
# Проверяем, что функция импортируется
assert oauth_callback_http is not None
assert callable(oauth_callback_http)
# Мокаем OAuth данные из Redis
oauth_data = {
"provider": "google",
"code_verifier": "test_verifier",
"redirect_uri": "https://localhost:3000"
}
# Проверяем, что фикстуры работают
assert mock_request is not None
assert mock_oauth_client is not None
assert oauth_db_session is not None
# Мокаем токен от провайдера
mock_token = {
"access_token": "test_token",
"userinfo": {
"sub": "123",
"email": "test@gmail.com",
"name": "Test User",
"picture": "https://example.com/photo.jpg"
}
}
# Простая проверка - функция существует и может быть вызвана
# В реальном тесте здесь можно было бы замокать все зависимости
logger.info("✅ OAuth callback функция импортирована и готова к тестированию")
with patch("auth.oauth.get_oauth_state", return_value=oauth_data), \
patch("auth.oauth.oauth.create_client", return_value=mock_oauth_client), \
patch("auth.oauth.get_user_profile", return_value={
"id": "123",
"email": "test@gmail.com",
"name": "Test User",
"picture": "https://example.com/photo.jpg"
}), \
patch("auth.oauth._create_or_update_user") as mock_create_user, \
patch("auth.tokens.storage.TokenStorage.create_session", return_value="test_session_token"):
# Настраиваем мок пользователя
mock_user = MagicMock()
mock_user.id = 123
mock_user.name = "Test User"
mock_create_user.return_value = mock_user
# Настраиваем мок OAuth клиента
mock_oauth_client.fetch_access_token.return_value = mock_token
response = await oauth_callback_http(mock_request)
# Проверяем что это редирект
assert isinstance(response, RedirectResponse)
assert response.status_code == 307
# Проверяем что токен получен
mock_oauth_client.fetch_access_token.assert_called_once()
# Проверяем что пользователь создан/обновлен
mock_create_user.assert_called_once()
@pytest.mark.asyncio
async def test_oauth_callback_invalid_state(mock_request):
"""Тест с неправильным state параметром"""
mock_request.session = {"provider": "google", "state": "correct_state"}
mock_request.query_params["state"] = "wrong_state"
"""Тест с неправильным state параметром (session-free)"""
mock_request.query_params = {"state": "wrong_state"}
with patch("auth.oauth.get_oauth_state", return_value=None):
response = await oauth_callback_http(mock_request)
@@ -170,6 +232,20 @@ with (
if isinstance(body_content, memoryview):
body_content = bytes(body_content)
assert "Invalid or expired OAuth state" in body_content.decode()
@pytest.mark.asyncio
async def test_oauth_callback_missing_state(mock_request):
"""Тест без state параметра"""
mock_request.query_params = {}
response = await oauth_callback_http(mock_request)
assert isinstance(response, JSONResponse)
assert response.status_code == 400
body_content = response.body
if isinstance(body_content, memoryview):
body_content = bytes(body_content)
assert "Missing OAuth state parameter" in body_content.decode()
@pytest.mark.asyncio
async def test_oauth_callback_existing_user(mock_request, mock_oauth_client, oauth_db_session):
@@ -186,9 +262,54 @@ with (
assert mock_oauth_client is not None
assert oauth_db_session is not None
# Простая проверка - функция существует и может быть вызвана
# В реальном тесте здесь можно было бы замокать все зависимости
logger.info("✅ OAuth callback existing user функция импортирована и готова к тестированию")
# Тест Redis операций для OAuth состояния
from auth.oauth import store_oauth_state, get_oauth_state
# Проверяем что функции импортируются
assert store_oauth_state is not None
assert get_oauth_state is not None
logger.info("✅ OAuth Redis функции импортированы и готовы к тестированию")
@pytest.mark.asyncio
async def test_oauth_redis_state_operations():
"""Тест Redis операций для OAuth состояния"""
from auth.oauth import store_oauth_state, get_oauth_state
# Тестовые данные
test_state = "test_state_123"
test_data = {
"provider": "google",
"code_verifier": "test_verifier",
"redirect_uri": "https://localhost:3000",
"created_at": 1234567890
}
# Мокаем Redis операции
with patch("auth.oauth.redis") as mock_redis:
# Тест сохранения состояния
await store_oauth_state(test_state, test_data)
mock_redis.execute.assert_called_with(
"SETEX",
f"oauth_state:{test_state}",
600, # TTL
ANY # orjson.dumps(test_data)
)
# Тест получения состояния
import orjson
mock_redis.execute.side_effect = [
orjson.dumps(test_data), # GET
None # DEL
]
result = await get_oauth_state(test_state)
# Проверяем что данные корректно десериализованы
assert result == test_data
# Проверяем что вызваны правильные Redis команды
assert mock_redis.execute.call_count == 3 # SETEX + GET + DEL
# Импортируем необходимые модели
from orm.community import Community, CommunityAuthor