myrmidon / python /tests /mcp_server /features /documents /test_document_tools.py
tek Atrust
chore(deploy): build monolithic server for Hugging Face
d5ef46f
Raw
History Blame Contribute Delete
6.19 kB
"""Unit tests for document management tools."""
import json
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from mcp.server.fastmcp import Context
from src.mcp_server.features.documents.document_tools import register_document_tools
@pytest.fixture
def mock_mcp():
"""Create a mock MCP server for testing."""
mock = MagicMock()
# Store registered tools
mock._tools = {}
def tool_decorator():
def decorator(func):
mock._tools[func.__name__] = func
return func
return decorator
mock.tool = tool_decorator
return mock
@pytest.fixture
def mock_context():
"""Create a mock context for testing."""
return MagicMock(spec=Context)
@pytest.mark.asyncio
async def test_create_document_success(mock_mcp, mock_context):
"""Test successful document creation."""
# Register tools with mock MCP
register_document_tools(mock_mcp)
# Get the manage_document function from registered tools
manage_document = mock_mcp._tools.get("manage_document")
assert manage_document is not None, "manage_document tool not registered"
# Mock HTTP response
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"document": {"id": "doc-123", "title": "Test Doc"},
"message": "Document created successfully",
}
with patch("src.mcp_server.features.documents.document_tools.httpx.AsyncClient") as mock_client:
mock_async_client = AsyncMock()
mock_async_client.post.return_value = mock_response
mock_client.return_value.__aenter__.return_value = mock_async_client
# Test the function
result = await manage_document(
mock_context,
action="create",
project_id="project-123",
title="Test Document",
document_type="spec",
content={"test": "content"},
)
result_data = json.loads(result)
assert result_data["success"] is True
assert result_data["document_id"] == "doc-123"
assert "Document created successfully" in result_data["message"]
@pytest.mark.asyncio
async def test_find_documents_success(mock_mcp, mock_context):
"""Test successful document listing."""
register_document_tools(mock_mcp)
# Get the find_documents function from registered tools
find_documents = mock_mcp._tools.get("find_documents")
assert find_documents is not None, "find_documents tool not registered"
# Mock HTTP response
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"documents": [
{"id": "doc-1", "title": "Doc 1", "document_type": "spec"},
{"id": "doc-2", "title": "Doc 2", "document_type": "design"},
]
}
with patch("src.mcp_server.features.documents.document_tools.httpx.AsyncClient") as mock_client:
mock_async_client = AsyncMock()
mock_async_client.get.return_value = mock_response
mock_client.return_value.__aenter__.return_value = mock_async_client
result = await find_documents(mock_context, project_id="project-123")
result_data = json.loads(result)
assert result_data["success"] is True
assert len(result_data["documents"]) == 2
assert result_data["count"] == 2
@pytest.mark.asyncio
async def test_update_document_partial_update(mock_mcp, mock_context):
"""Test partial document update."""
register_document_tools(mock_mcp)
# Get the manage_document function from registered tools
manage_document = mock_mcp._tools.get("manage_document")
assert manage_document is not None, "manage_document tool not registered"
# Mock HTTP response
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"doc": {"id": "doc-123", "title": "Updated Title"},
"message": "Document updated successfully",
}
with patch("src.mcp_server.features.documents.document_tools.httpx.AsyncClient") as mock_client:
mock_async_client = AsyncMock()
mock_async_client.put.return_value = mock_response
mock_client.return_value.__aenter__.return_value = mock_async_client
# Update only title
result = await manage_document(
mock_context, action="update", project_id="project-123", document_id="doc-123", title="Updated Title"
)
result_data = json.loads(result)
assert result_data["success"] is True
assert "Document updated successfully" in result_data["message"]
# Verify only title was sent in update
call_args = mock_async_client.put.call_args
sent_data = call_args[1]["json"]
assert sent_data == {"title": "Updated Title"}
@pytest.mark.asyncio
async def test_delete_document_not_found(mock_mcp, mock_context):
"""Test deleting a non-existent document."""
register_document_tools(mock_mcp)
# Get the manage_document function from registered tools
manage_document = mock_mcp._tools.get("manage_document")
assert manage_document is not None, "manage_document tool not registered"
# Mock 404 response
mock_response = MagicMock()
mock_response.status_code = 404
mock_response.text = "Document not found"
with patch("src.mcp_server.features.documents.document_tools.httpx.AsyncClient") as mock_client:
mock_async_client = AsyncMock()
mock_async_client.delete.return_value = mock_response
mock_client.return_value.__aenter__.return_value = mock_async_client
result = await manage_document(
mock_context, action="delete", project_id="project-123", document_id="non-existent"
)
result_data = json.loads(result)
assert result_data["success"] is False
# Error must be structured format (dict), not string
assert "error" in result_data
assert isinstance(result_data["error"], dict), "Error should be structured format, not string"
assert result_data["error"]["type"] == "http_error"
assert "404" in result_data["error"]["message"].lower()