""" 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")