test_document_organization.py•6.21 kB
"""
Tests for document organization tools.
"""
from unittest.mock import AsyncMock, patch
import pytest
from mcp_outline.features.documents.common import OutlineClientError
# Mock FastMCP for registering tools
class MockMCP:
def __init__(self):
self.tools = {}
def tool(self, annotations=None):
def decorator(func):
self.tools[func.__name__] = func
return func
return decorator
# Sample response data
SAMPLE_MOVE_RESPONSE = {
"data": {
"id": "doc123",
"title": "Moved Document",
"collectionId": "col456",
}
}
@pytest.fixture
def mcp():
"""Fixture to provide mock MCP instance."""
return MockMCP()
@pytest.fixture
def register_organization_tools(mcp):
"""Fixture to register document organization tools."""
from mcp_outline.features.documents.document_organization import (
register_tools,
)
register_tools(mcp)
return mcp
class TestMoveDocument:
"""Tests for move_document tool."""
@pytest.mark.asyncio
@patch(
"mcp_outline.features.documents.document_organization.get_outline_client"
)
async def test_move_document_to_collection_success(
self, mock_get_client, register_organization_tools
):
"""Test move_document to a different collection."""
mock_client = AsyncMock()
mock_client.post.return_value = SAMPLE_MOVE_RESPONSE
mock_get_client.return_value = mock_client
result = await register_organization_tools.tools["move_document"](
document_id="doc123", collection_id="col456"
)
mock_client.post.assert_called_once_with(
"documents.move", {"id": "doc123", "collectionId": "col456"}
)
assert "Document moved successfully" in result
@pytest.mark.asyncio
@patch(
"mcp_outline.features.documents.document_organization.get_outline_client"
)
async def test_move_document_to_parent_success(
self, mock_get_client, register_organization_tools
):
"""Test move_document to a different parent."""
mock_client = AsyncMock()
mock_client.post.return_value = SAMPLE_MOVE_RESPONSE
mock_get_client.return_value = mock_client
result = await register_organization_tools.tools["move_document"](
document_id="doc123", parent_document_id="parent456"
)
mock_client.post.assert_called_once_with(
"documents.move", {"id": "doc123", "parentDocumentId": "parent456"}
)
assert "Document moved successfully" in result
@pytest.mark.asyncio
@patch(
"mcp_outline.features.documents.document_organization.get_outline_client"
)
async def test_move_document_collection_and_parent(
self, mock_get_client, register_organization_tools
):
"""Test move_document with both collection and parent specified."""
mock_client = AsyncMock()
mock_client.post.return_value = SAMPLE_MOVE_RESPONSE
mock_get_client.return_value = mock_client
result = await register_organization_tools.tools["move_document"](
document_id="doc123",
collection_id="col456",
parent_document_id="parent789",
)
mock_client.post.assert_called_once_with(
"documents.move",
{
"id": "doc123",
"collectionId": "col456",
"parentDocumentId": "parent789",
},
)
assert "Document moved successfully" in result
@pytest.mark.asyncio
@patch(
"mcp_outline.features.documents.document_organization.get_outline_client"
)
async def test_move_document_no_destination(
self, mock_get_client, register_organization_tools
):
"""Test move_document without collection_id or parent_document_id."""
mock_client = AsyncMock()
mock_get_client.return_value = mock_client
result = await register_organization_tools.tools["move_document"](
document_id="doc123"
)
# Should not call the client
mock_client.post.assert_not_called()
assert "Error" in result
assert "collection_id or parent_document_id" in result
@pytest.mark.asyncio
@patch(
"mcp_outline.features.documents.document_organization.get_outline_client"
)
async def test_move_document_failure(
self, mock_get_client, register_organization_tools
):
"""Test move_document when API returns no data."""
mock_client = AsyncMock()
mock_client.post.return_value = {}
mock_get_client.return_value = mock_client
result = await register_organization_tools.tools["move_document"](
document_id="doc123", collection_id="col456"
)
assert "Failed to move document" in result
@pytest.mark.asyncio
@patch(
"mcp_outline.features.documents.document_organization.get_outline_client"
)
async def test_move_document_client_error(
self, mock_get_client, register_organization_tools
):
"""Test move_document with client error."""
mock_client = AsyncMock()
mock_client.post.side_effect = OutlineClientError("API error")
mock_get_client.return_value = mock_client
result = await register_organization_tools.tools["move_document"](
document_id="doc123", collection_id="col456"
)
assert "Error moving document" in result
assert "API error" in result
@pytest.mark.asyncio
@patch(
"mcp_outline.features.documents.document_organization.get_outline_client"
)
async def test_move_document_unexpected_error(
self, mock_get_client, register_organization_tools
):
"""Test move_document with unexpected error."""
mock_client = AsyncMock()
mock_client.post.side_effect = ValueError("Unexpected error")
mock_get_client.return_value = mock_client
result = await register_organization_tools.tools["move_document"](
document_id="doc123", collection_id="col456"
)
assert "Unexpected error" in result