docs/tests/conftest.py
markov 2bab3cf60a Добавлены E2E тесты для Team Board API
- Полный набор тестов для всех модулей API
- test_auth.py: аутентификация и JWT токены
- test_members.py: CRUD участников, агенты, токены
- test_projects.py: CRUD проектов, участники проектов
- test_tasks.py: CRUD задач, этапы, назначения, зависимости
- test_chat.py: сообщения, комментарии, mentions
- test_files.py: upload/download файлов проектов
- test_labels.py: CRUD лейблов, привязка к задачам
- test_websocket.py: WebSocket подключения и события
- test_streaming.py: агентный стриминг через WebSocket
- conftest.py: фикстуры для подключения к API
- requirements.txt: зависимости pytest, httpx, websockets
- pytest.ini: настройки asyncio для pytest
2026-03-13 22:47:19 +01:00

174 lines
5.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Conftest для E2E тестов Team Board API
Содержит фикстуры для подключения к API и создания тестовых данных
"""
import pytest
import pytest_asyncio
import httpx
import uuid
from typing import Dict, Any, Optional
@pytest.fixture(scope="session")
def base_url():
"""Базовый URL для API"""
return "http://localhost:8100/api/v1"
@pytest_asyncio.fixture
async def admin_token(base_url: str) -> str:
"""Получает JWT токен администратора"""
async with httpx.AsyncClient() as client:
response = await client.post(f"{base_url}/auth/login", json={
"login": "admin",
"password": "teamboard"
})
assert response.status_code == 200
data = response.json()
return data["token"]
@pytest.fixture
def agent_token():
"""Bearer токен для агента из документации"""
return "tb-coder-dev-token"
@pytest.fixture
def http_client(base_url: str, admin_token: str):
"""HTTP клиент с авторизацией для админа"""
headers = {"Authorization": f"Bearer {admin_token}"}
return httpx.AsyncClient(base_url=base_url, headers=headers, timeout=30.0)
@pytest.fixture
def agent_client(base_url: str, agent_token: str):
"""HTTP клиент с авторизацией для агента"""
headers = {"Authorization": f"Bearer {agent_token}"}
return httpx.AsyncClient(base_url=base_url, headers=headers, timeout=30.0)
@pytest_asyncio.fixture
async def test_project(http_client: httpx.AsyncClient) -> Dict[str, Any]:
"""Создаёт тестовый проект и удаляет его после теста"""
project_slug = f"test-project-{uuid.uuid4().hex[:8]}"
project_data = {
"name": f"Test Project {project_slug}",
"slug": project_slug,
"description": "Test project for E2E tests",
"repo_urls": ["https://github.com/test/repo"]
}
response = await http_client.post("/projects", json=project_data)
assert response.status_code == 201
project = response.json()
yield project
# Cleanup - удаляем проект
await http_client.delete(f"/projects/{project['id']}")
@pytest_asyncio.fixture
async def test_user(http_client: httpx.AsyncClient) -> Dict[str, Any]:
"""Создаёт тестового пользователя и удаляет его после теста"""
user_slug = f"test-user-{uuid.uuid4().hex[:8]}"
user_data = {
"name": f"Test User {user_slug}",
"slug": user_slug,
"type": "human",
"role": "member"
}
response = await http_client.post("/members", json=user_data)
assert response.status_code == 201
user = response.json()
yield user
# Cleanup - помечаем пользователя неактивным
await http_client.delete(f"/members/{user['id']}")
@pytest_asyncio.fixture
async def test_agent(http_client: httpx.AsyncClient) -> Dict[str, Any]:
"""Создаёт тестового агента и удаляет его после теста"""
agent_slug = f"test-agent-{uuid.uuid4().hex[:8]}"
agent_data = {
"name": f"Test Agent {agent_slug}",
"slug": agent_slug,
"type": "agent",
"role": "member",
"agent_config": {
"capabilities": ["coding", "testing"],
"labels": ["backend", "python"],
"chat_listen": "mentions",
"task_listen": "assigned",
"prompt": "Test agent for E2E tests"
}
}
response = await http_client.post("/members", json=agent_data)
assert response.status_code == 201
agent = response.json()
yield agent
# Cleanup
await http_client.delete(f"/members/{agent['id']}")
@pytest_asyncio.fixture
async def test_task(http_client: httpx.AsyncClient, test_project: Dict[str, Any]) -> Dict[str, Any]:
"""Создаёт тестовую задачу в проекте"""
task_data = {
"title": "Test Task",
"description": "Test task for E2E tests",
"type": "task",
"status": "backlog",
"priority": "medium"
}
response = await http_client.post(f"/tasks?project_id={test_project['id']}", json=task_data)
assert response.status_code == 201
task = response.json()
yield task
# Cleanup - задача удалится вместе с проектом
@pytest_asyncio.fixture
async def test_label(http_client: httpx.AsyncClient) -> Dict[str, Any]:
"""Создаёт тестовый лейбл"""
label_slug = f"test-label-{uuid.uuid4().hex[:8]}"
label_data = {
"name": label_slug,
"color": "#ff5733"
}
response = await http_client.post("/labels", json=label_data)
assert response.status_code == 201
label = response.json()
yield label
# Cleanup
await http_client.delete(f"/labels/{label['id']}")
def assert_uuid(value: str):
"""Проверяет что строка является валидным UUID"""
try:
uuid.UUID(value)
except (ValueError, TypeError):
pytest.fail(f"'{value}' is not a valid UUID")
def assert_timestamp(value: str):
"""Проверяет что строка является валидным ISO timestamp"""
import datetime
try:
datetime.datetime.fromisoformat(value.replace('Z', '+00:00'))
except ValueError:
pytest.fail(f"'{value}' is not a valid ISO timestamp")