docs/tests/conftest.py
markov 7fcf4abed9 feat: isolated test infra — docker-compose.test.yml + test.sh
- Отдельная PostgreSQL в tmpfs (RAM)
- Отдельный Tracker на порту 8101
- Полная изоляция от прода
- ./test.sh для запуска
2026-03-14 10:28:11 +01:00

125 lines
3.9 KiB
Python

"""
Conftest для E2E тестов Team Board.
Ожидает что тестовый Tracker уже запущен на порту 8101 (через test.sh).
"""
import os
import pytest
import pytest_asyncio
import httpx
import uuid
from typing import Dict, Any
TEST_PORT = os.environ.get("TEST_PORT", "8101")
BASE_URL = f"http://localhost:{TEST_PORT}/api/v1"
WS_URL = f"ws://localhost:{TEST_PORT}"
@pytest.fixture(scope="session")
def base_url():
return BASE_URL
@pytest.fixture(scope="session")
def ws_url():
return WS_URL
@pytest_asyncio.fixture
async def admin_token(base_url: str) -> str:
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, f"Login failed: {response.text}"
return response.json()["token"]
@pytest.fixture
def agent_token():
return "tb-coder-dev-token"
@pytest_asyncio.fixture
async def http_client(base_url: str, admin_token: str):
headers = {"Authorization": f"Bearer {admin_token}"}
async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=30.0) as client:
yield client
@pytest_asyncio.fixture
async def agent_client(base_url: str, agent_token: str):
headers = {"Authorization": f"Bearer {agent_token}"}
async with httpx.AsyncClient(base_url=base_url, headers=headers, timeout=30.0) as client:
yield client
@pytest_asyncio.fixture
async def test_project(http_client: httpx.AsyncClient) -> Dict[str, Any]:
slug = f"test-{uuid.uuid4().hex[:8]}"
response = await http_client.post("/projects", json={
"name": f"Test {slug}", "slug": slug, "description": "E2E test",
})
assert response.status_code == 200
project = response.json()
yield project
await http_client.delete(f"/projects/{project['id']}")
@pytest_asyncio.fixture
async def test_user(http_client: httpx.AsyncClient) -> Dict[str, Any]:
slug = f"user-{uuid.uuid4().hex[:8]}"
response = await http_client.post("/members", json={
"name": f"User {slug}", "slug": slug, "type": "human", "role": "member",
})
assert response.status_code == 200
yield response.json()
@pytest_asyncio.fixture
async def test_agent(http_client: httpx.AsyncClient) -> Dict[str, Any]:
slug = f"agent-{uuid.uuid4().hex[:8]}"
response = await http_client.post("/members", json={
"name": f"Agent {slug}", "slug": slug, "type": "agent", "role": "member",
"agent_config": {"capabilities": ["coding"], "labels": ["backend"],
"chat_listen": "mentions", "task_listen": "assigned"},
})
assert response.status_code == 200
yield response.json()
@pytest_asyncio.fixture
async def test_task(http_client: httpx.AsyncClient, test_project: Dict[str, Any]) -> Dict[str, Any]:
response = await http_client.post(f"/tasks?project_id={test_project['id']}", json={
"title": "Test Task", "description": "E2E test", "type": "task",
"status": "backlog", "priority": "medium",
})
assert response.status_code == 200
yield response.json()
@pytest_asyncio.fixture
async def test_label(http_client: httpx.AsyncClient) -> Dict[str, Any]:
name = f"label-{uuid.uuid4().hex[:8]}"
response = await http_client.post("/labels", json={"name": name, "color": "#ff5733"})
assert response.status_code == 200
label = response.json()
yield label
await http_client.delete(f"/labels/{label['id']}")
# ---------- Helpers ----------
def assert_uuid(value: str):
try:
uuid.UUID(value)
except (ValueError, TypeError):
pytest.fail(f"'{value}' is not a valid UUID")
def assert_timestamp(value: str):
import datetime
try:
datetime.datetime.fromisoformat(value.replace('Z', '+00:00'))
except ValueError:
pytest.fail(f"'{value}' is not a valid ISO timestamp")