feat(mcp): 5 outils todos + tests
Ajoute mcp_server.py avec get_todos, create_todo, update_todo, postpone_todo, delete_todo. Ajoute test_mcp.py (7 tests). Corrige conftest pour injecter NullPool dans AsyncSessionLocal des outils MCP (évite les conflits d'event loop entre tests). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ from sqlalchemy.pool import NullPool
|
||||
from app.main import app
|
||||
from app.core import database
|
||||
from app.core.config import settings
|
||||
import app.api.mcp_server as mcp_server_module
|
||||
|
||||
|
||||
def make_test_engine():
|
||||
@@ -12,6 +13,19 @@ def make_test_engine():
|
||||
return create_async_engine(settings.database_url, poolclass=NullPool)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def mcp_nullpool_session():
|
||||
"""Remplace AsyncSessionLocal dans mcp_server par un sessionmaker NullPool
|
||||
pour éviter les conflits d'event loop entre tests."""
|
||||
engine = make_test_engine()
|
||||
test_session_factory = async_sessionmaker(engine, expire_on_commit=False)
|
||||
original = mcp_server_module.AsyncSessionLocal
|
||||
mcp_server_module.AsyncSessionLocal = test_session_factory
|
||||
yield
|
||||
mcp_server_module.AsyncSessionLocal = original
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def db_session():
|
||||
engine = make_test_engine()
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import json
|
||||
import pytest
|
||||
from app.api.mcp_server import (
|
||||
get_todos, create_todo, update_todo, postpone_todo, delete_todo,
|
||||
)
|
||||
|
||||
|
||||
async def test_get_todos_retourne_liste_json():
|
||||
result = await get_todos(status="pending")
|
||||
data = json.loads(result)
|
||||
assert isinstance(data, list)
|
||||
|
||||
|
||||
async def test_create_todo_outil_cree_une_tache():
|
||||
result = await create_todo(title="TEST_MCP_todo_create")
|
||||
data = json.loads(result)
|
||||
assert data["title"] == "TEST_MCP_todo_create"
|
||||
assert data["status"] == "pending"
|
||||
assert data["priority"] == "medium"
|
||||
# Cleanup
|
||||
await delete_todo(id=str(data["id"]))
|
||||
|
||||
|
||||
async def test_update_todo_outil():
|
||||
created = json.loads(await create_todo(title="TEST_MCP_todo_update"))
|
||||
result = await update_todo(id=str(created["id"]), status="done")
|
||||
data = json.loads(result)
|
||||
assert data["status"] == "done"
|
||||
await delete_todo(id=str(created["id"]))
|
||||
|
||||
|
||||
async def test_postpone_todo_outil():
|
||||
created = json.loads(await create_todo(title="TEST_MCP_todo_postpone"))
|
||||
result = await postpone_todo(id=str(created["id"]), days=3)
|
||||
data = json.loads(result)
|
||||
assert data["postponed_count"] == 1
|
||||
await delete_todo(id=str(created["id"]))
|
||||
|
||||
|
||||
async def test_delete_todo_outil():
|
||||
created = json.loads(await create_todo(title="TEST_MCP_todo_delete"))
|
||||
result = await delete_todo(id=str(created["id"]))
|
||||
data = json.loads(result)
|
||||
assert "deleted" in data
|
||||
|
||||
|
||||
async def test_update_todo_id_invalide():
|
||||
result = await update_todo(id="pas-un-uuid", title="x")
|
||||
data = json.loads(result)
|
||||
assert "error" in data
|
||||
|
||||
|
||||
async def test_delete_todo_introuvable():
|
||||
result = await delete_todo(id="00000000-0000-0000-0000-000000000000")
|
||||
data = json.loads(result)
|
||||
assert "error" in data
|
||||
Reference in New Issue
Block a user