diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py new file mode 100644 index 0000000..973f42b --- /dev/null +++ b/tests/integration/conftest.py @@ -0,0 +1,60 @@ +"""Fixtures for integration tests.""" + +import time + +import httpx +import pytest +from mcp import ClientSession +from mcp.client.sse import sse_client + + +GRIST_MCP_URL = "http://localhost:3000" +MOCK_GRIST_URL = "http://localhost:8484" +MAX_WAIT_SECONDS = 30 + + +def wait_for_service(url: str, timeout: int = MAX_WAIT_SECONDS) -> bool: + """Wait for a service to become healthy.""" + start = time.time() + while time.time() - start < timeout: + try: + response = httpx.get(f"{url}/health", timeout=2.0) + if response.status_code == 200: + return True + except httpx.RequestError: + pass + time.sleep(0.5) + return False + + +@pytest.fixture(scope="session") +def services_ready(): + """Ensure both services are healthy before running tests.""" + if not wait_for_service(MOCK_GRIST_URL): + pytest.fail(f"Mock Grist server not ready at {MOCK_GRIST_URL}") + if not wait_for_service(GRIST_MCP_URL): + pytest.fail(f"grist-mcp server not ready at {GRIST_MCP_URL}") + return True + + +@pytest.fixture +async def mcp_client(services_ready): + """Create an MCP client connected to grist-mcp via SSE.""" + async with sse_client(f"{GRIST_MCP_URL}/sse") as (read_stream, write_stream): + async with ClientSession(read_stream, write_stream) as session: + await session.initialize() + yield session + + +@pytest.fixture +def mock_grist_client(services_ready): + """HTTP client for interacting with mock Grist test endpoints.""" + with httpx.Client(base_url=MOCK_GRIST_URL, timeout=10.0) as client: + yield client + + +@pytest.fixture(autouse=True) +def clear_mock_grist_log(mock_grist_client): + """Clear the mock Grist request log before each test.""" + mock_grist_client.post("/_test/requests/clear") + yield