2025-05-16 09:11:39 +03:00
|
|
|
|
"""
|
2025-09-25 09:40:12 +03:00
|
|
|
|
🧪 Общая конфигурация для тестов - DRY принцип
|
|
|
|
|
|
|
|
|
|
|
|
Централизованные настройки, константы и общие фикстуры.
|
2025-05-16 09:11:39 +03:00
|
|
|
|
"""
|
|
|
|
|
|
|
2025-09-25 09:40:12 +03:00
|
|
|
|
import pytest
|
|
|
|
|
|
from typing import Dict, Any
|
|
|
|
|
|
|
|
|
|
|
|
# 🔍 DRY: Общие константы для тестов
|
|
|
|
|
|
TEST_USER_IDS = {
|
|
|
|
|
|
"FOLLOWER": 2466,
|
|
|
|
|
|
"TARGET_AUTHOR": 9999,
|
|
|
|
|
|
"ADMIN": 1,
|
|
|
|
|
|
"REGULAR_USER": 100,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_EMAILS = {
|
|
|
|
|
|
"FOLLOWER": "follower@example.com",
|
|
|
|
|
|
"TARGET_AUTHOR": "target@example.com",
|
|
|
|
|
|
"ADMIN": "admin@example.com",
|
|
|
|
|
|
"REGULAR_USER": "user@example.com",
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TEST_SLUGS = {
|
|
|
|
|
|
"FOLLOWER": "test-follower",
|
|
|
|
|
|
"TARGET_AUTHOR": "test-target-author",
|
|
|
|
|
|
"ADMIN": "test-admin",
|
|
|
|
|
|
"REGULAR_USER": "test-user",
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 🔍 YAGNI: Только необходимые OAuth провайдеры для тестов
|
|
|
|
|
|
OAUTH_PROVIDERS = ["google", "github", "facebook"]
|
|
|
|
|
|
|
|
|
|
|
|
# 🔍 DRY: Общие настройки для Redis тестов
|
|
|
|
|
|
REDIS_TEST_CONFIG = {
|
|
|
|
|
|
"host": "127.0.0.1",
|
|
|
|
|
|
"port": 6379,
|
|
|
|
|
|
"db": 0,
|
|
|
|
|
|
"decode_responses": True,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 🔍 DRY: Общие HTTP статусы для тестов
|
|
|
|
|
|
HTTP_STATUS = {
|
|
|
|
|
|
"OK": 200,
|
|
|
|
|
|
"BAD_REQUEST": 400,
|
|
|
|
|
|
"UNAUTHORIZED": 401,
|
|
|
|
|
|
"FORBIDDEN": 403,
|
|
|
|
|
|
"NOT_FOUND": 404,
|
|
|
|
|
|
"REDIRECT": 307,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
|
|
def test_user_data() -> Dict[str, Any]:
|
|
|
|
|
|
"""🔍 DRY фикстура с тестовыми данными пользователей"""
|
|
|
|
|
|
return {
|
|
|
|
|
|
"ids": TEST_USER_IDS,
|
|
|
|
|
|
"emails": TEST_EMAILS,
|
|
|
|
|
|
"slugs": TEST_SLUGS,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
|
|
def oauth_test_data() -> Dict[str, Any]:
|
|
|
|
|
|
"""🔍 DRY фикстура с тестовыми данными OAuth"""
|
|
|
|
|
|
return {
|
|
|
|
|
|
"providers": OAUTH_PROVIDERS,
|
|
|
|
|
|
"valid_state": "valid_test_state_123",
|
|
|
|
|
|
"invalid_state": "invalid_state",
|
|
|
|
|
|
"auth_code": "test_auth_code_123",
|
|
|
|
|
|
"access_token": "test_access_token_123",
|
|
|
|
|
|
"redirect_uri": "https://localhost:3000",
|
|
|
|
|
|
"code_verifier": "test_code_verifier_123",
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
|
|
def redis_test_config() -> Dict[str, Any]:
|
|
|
|
|
|
"""🔍 DRY фикстура с конфигурацией Redis для тестов"""
|
|
|
|
|
|
return REDIS_TEST_CONFIG.copy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def skip_test_if_condition(condition: bool, reason: str):
|
|
|
|
|
|
"""🔍 DRY хелпер для условного пропуска тестов"""
|
|
|
|
|
|
if condition:
|
|
|
|
|
|
pytest.skip(reason)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def assert_response_status(response, expected_status: int, message: str = ""):
|
|
|
|
|
|
"""🔍 DRY хелпер для проверки статуса ответа"""
|
|
|
|
|
|
actual_status = getattr(response, 'status_code', None)
|
|
|
|
|
|
assert actual_status == expected_status, f"{message} Expected {expected_status}, got {actual_status}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def assert_json_contains(response_data: str, expected_keys: list, message: str = ""):
|
|
|
|
|
|
"""🔍 DRY хелпер для проверки содержимого JSON ответа"""
|
|
|
|
|
|
for key in expected_keys:
|
|
|
|
|
|
assert key in response_data, f"{message} Missing key '{key}' in response"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 🔍 YAGNI: Убираем сложные тестовые сценарии, оставляем простые
|
|
|
|
|
|
SIMPLE_TEST_SCENARIOS = {
|
|
|
|
|
|
"follow_success": {
|
|
|
|
|
|
"action": "follow",
|
|
|
|
|
|
"expected_error": None,
|
|
|
|
|
|
"expected_count": 1,
|
|
|
|
|
|
},
|
|
|
|
|
|
"follow_already_following": {
|
|
|
|
|
|
"action": "follow_duplicate",
|
|
|
|
|
|
"expected_error": "already following",
|
|
|
|
|
|
"expected_count": 1,
|
|
|
|
|
|
},
|
|
|
|
|
|
"unfollow_success": {
|
|
|
|
|
|
"action": "unfollow",
|
|
|
|
|
|
"expected_error": None,
|
|
|
|
|
|
"expected_count": 0,
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|