Skip to main content
Glama
test_collection_tools.py17.4 kB
""" Tests for collection management tools. """ from unittest.mock import AsyncMock, patch import pytest from mcp_outline.features.documents.collection_tools import ( _format_file_operation, ) from mcp_outline.features.documents.common import OutlineClientError # Mock FastMCP for registering tools class MockMCP: def __init__(self): self.tools = {} def tool(self, **kwargs): def decorator(func): self.tools[func.__name__] = func return func return decorator # Sample data SAMPLE_COLLECTION = { "id": "col123", "name": "Test Collection", "description": "A test collection", } SAMPLE_FILE_OPERATION_COMPLETE = { "id": "fileop123", "state": "complete", "type": "export", "name": "Test Export", } SAMPLE_FILE_OPERATION_PROCESSING = { "id": "fileop456", "state": "processing", "type": "export", "name": "Test Export", } @pytest.fixture def mcp(): """Fixture to provide mock MCP instance.""" return MockMCP() @pytest.fixture def register_collection_tools(mcp): """Fixture to register collection management tools.""" from mcp_outline.features.documents.collection_tools import register_tools register_tools(mcp) return mcp class TestFileOperationFormatter: """Tests for _format_file_operation formatter.""" def test_format_file_operation_complete(self): """Test formatting complete file operation.""" result = _format_file_operation(SAMPLE_FILE_OPERATION_COMPLETE) assert "Export Operation: Test Export" in result assert "State: complete" in result assert "Type: export" in result assert "fileop123" in result assert "export is complete" in result def test_format_file_operation_processing(self): """Test formatting processing file operation.""" result = _format_file_operation(SAMPLE_FILE_OPERATION_PROCESSING) assert "Export Operation: Test Export" in result assert "State: processing" in result assert "still in progress" in result assert "fileop456" in result def test_format_file_operation_empty(self): """Test formatting empty file operation.""" result = _format_file_operation({}) # Empty dict is falsy so should return no data message assert "No file operation data available" in result def test_format_file_operation_none(self): """Test formatting None file operation.""" result = _format_file_operation(None) assert "No file operation data available" in result class TestCreateCollection: """Tests for create_collection tool.""" @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_create_collection_success( self, mock_get_client, register_collection_tools ): """Test create_collection tool success case.""" mock_client = AsyncMock() mock_client.create_collection.return_value = SAMPLE_COLLECTION mock_get_client.return_value = mock_client result = await register_collection_tools.tools["create_collection"]( name="Test Collection", description="A test collection" ) mock_client.create_collection.assert_called_once_with( "Test Collection", "A test collection", None ) assert "Collection created successfully" in result assert "Test Collection" in result assert "col123" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_create_collection_with_color( self, mock_get_client, register_collection_tools ): """Test create_collection with color specified.""" mock_client = AsyncMock() mock_client.create_collection.return_value = SAMPLE_COLLECTION mock_get_client.return_value = mock_client result = await register_collection_tools.tools["create_collection"]( name="Test Collection", description="A test collection", color="#FF0000", ) mock_client.create_collection.assert_called_once_with( "Test Collection", "A test collection", "#FF0000" ) assert "Collection created successfully" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_create_collection_failure( self, mock_get_client, register_collection_tools ): """Test create_collection when no collection is returned.""" mock_client = AsyncMock() mock_client.create_collection.return_value = None mock_get_client.return_value = mock_client result = await register_collection_tools.tools["create_collection"]( name="Test Collection" ) assert "Failed to create collection" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_create_collection_client_error( self, mock_get_client, register_collection_tools ): """Test create_collection with client error.""" mock_client = AsyncMock() mock_client.create_collection.side_effect = OutlineClientError( "API error" ) mock_get_client.return_value = mock_client result = await register_collection_tools.tools["create_collection"]( name="Test Collection" ) assert "Error creating collection" in result assert "API error" in result class TestUpdateCollection: """Tests for update_collection tool.""" @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_update_collection_success( self, mock_get_client, register_collection_tools ): """Test update_collection tool success case.""" mock_client = AsyncMock() mock_client.update_collection.return_value = SAMPLE_COLLECTION mock_get_client.return_value = mock_client result = await register_collection_tools.tools["update_collection"]( collection_id="col123", name="Updated Collection" ) mock_client.update_collection.assert_called_once_with( "col123", "Updated Collection", None, None ) assert "Collection updated successfully" in result assert "Test Collection" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_update_collection_all_fields( self, mock_get_client, register_collection_tools ): """Test update_collection with all fields.""" mock_client = AsyncMock() mock_client.update_collection.return_value = SAMPLE_COLLECTION mock_get_client.return_value = mock_client result = await register_collection_tools.tools["update_collection"]( collection_id="col123", name="New Name", description="New Description", color="#00FF00", ) mock_client.update_collection.assert_called_once_with( "col123", "New Name", "New Description", "#00FF00" ) assert "Collection updated successfully" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_update_collection_no_fields( self, mock_get_client, register_collection_tools ): """Test update_collection with no fields to update.""" mock_client = AsyncMock() mock_get_client.return_value = mock_client result = await register_collection_tools.tools["update_collection"]( collection_id="col123" ) # Should not call the client mock_client.update_collection.assert_not_called() assert "Error" in result assert "at least one field to update" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_update_collection_failure( self, mock_get_client, register_collection_tools ): """Test update_collection when no collection is returned.""" mock_client = AsyncMock() mock_client.update_collection.return_value = None mock_get_client.return_value = mock_client result = await register_collection_tools.tools["update_collection"]( collection_id="col123", name="Updated Name" ) assert "Failed to update collection" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_update_collection_client_error( self, mock_get_client, register_collection_tools ): """Test update_collection with client error.""" mock_client = AsyncMock() mock_client.update_collection.side_effect = OutlineClientError( "API error" ) mock_get_client.return_value = mock_client result = await register_collection_tools.tools["update_collection"]( collection_id="col123", name="Updated Name" ) assert "Error updating collection" in result assert "API error" in result class TestDeleteCollection: """Tests for delete_collection tool.""" @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_delete_collection_success( self, mock_get_client, register_collection_tools ): """Test delete_collection tool success case.""" mock_client = AsyncMock() mock_client.delete_collection.return_value = True mock_get_client.return_value = mock_client result = await register_collection_tools.tools["delete_collection"]( "col123" ) mock_client.delete_collection.assert_called_once_with("col123") assert ( "Collection and all its documents deleted successfully" in result ) @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_delete_collection_failure( self, mock_get_client, register_collection_tools ): """Test delete_collection when deletion fails.""" mock_client = AsyncMock() mock_client.delete_collection.return_value = False mock_get_client.return_value = mock_client result = await register_collection_tools.tools["delete_collection"]( "col123" ) assert "Failed to delete collection" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_delete_collection_client_error( self, mock_get_client, register_collection_tools ): """Test delete_collection with client error.""" mock_client = AsyncMock() mock_client.delete_collection.side_effect = OutlineClientError( "API error" ) mock_get_client.return_value = mock_client result = await register_collection_tools.tools["delete_collection"]( "col123" ) assert "Error deleting collection" in result assert "API error" in result class TestExportCollection: """Tests for export_collection tool.""" @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_export_collection_success( self, mock_get_client, register_collection_tools ): """Test export_collection tool success case.""" mock_client = AsyncMock() mock_client.export_collection.return_value = ( SAMPLE_FILE_OPERATION_COMPLETE ) mock_get_client.return_value = mock_client result = await register_collection_tools.tools["export_collection"]( "col123" ) mock_client.export_collection.assert_called_once_with( "col123", "outline-markdown" ) assert "Export Operation" in result assert "complete" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_export_collection_custom_format( self, mock_get_client, register_collection_tools ): """Test export_collection with custom format.""" mock_client = AsyncMock() mock_client.export_collection.return_value = ( SAMPLE_FILE_OPERATION_PROCESSING ) mock_get_client.return_value = mock_client result = await register_collection_tools.tools["export_collection"]( "col123", format="json" ) mock_client.export_collection.assert_called_once_with("col123", "json") assert "Export Operation" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_export_collection_failure( self, mock_get_client, register_collection_tools ): """Test export_collection when no file operation is returned.""" mock_client = AsyncMock() mock_client.export_collection.return_value = None mock_get_client.return_value = mock_client result = await register_collection_tools.tools["export_collection"]( "col123" ) assert "Failed to start export operation" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_export_collection_client_error( self, mock_get_client, register_collection_tools ): """Test export_collection with client error.""" mock_client = AsyncMock() mock_client.export_collection.side_effect = OutlineClientError( "API error" ) mock_get_client.return_value = mock_client result = await register_collection_tools.tools["export_collection"]( "col123" ) assert "Error exporting collection" in result assert "API error" in result class TestExportAllCollections: """Tests for export_all_collections tool.""" @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_export_all_collections_success( self, mock_get_client, register_collection_tools ): """Test export_all_collections tool success case.""" mock_client = AsyncMock() mock_client.export_all_collections.return_value = ( SAMPLE_FILE_OPERATION_COMPLETE ) mock_get_client.return_value = mock_client result = await register_collection_tools.tools[ "export_all_collections" ]() mock_client.export_all_collections.assert_called_once_with( "outline-markdown" ) assert "Export Operation" in result assert "complete" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_export_all_collections_custom_format( self, mock_get_client, register_collection_tools ): """Test export_all_collections with custom format.""" mock_client = AsyncMock() mock_client.export_all_collections.return_value = ( SAMPLE_FILE_OPERATION_PROCESSING ) mock_get_client.return_value = mock_client result = await register_collection_tools.tools[ "export_all_collections" ](format="html") mock_client.export_all_collections.assert_called_once_with("html") assert "Export Operation" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_export_all_collections_failure( self, mock_get_client, register_collection_tools ): """Test export_all_collections when no file operation is returned.""" mock_client = AsyncMock() mock_client.export_all_collections.return_value = None mock_get_client.return_value = mock_client result = await register_collection_tools.tools[ "export_all_collections" ]() assert "Failed to start export operation" in result @pytest.mark.asyncio @patch( "mcp_outline.features.documents.collection_tools.get_outline_client" ) async def test_export_all_collections_client_error( self, mock_get_client, register_collection_tools ): """Test export_all_collections with client error.""" mock_client = AsyncMock() mock_client.export_all_collections.side_effect = OutlineClientError( "API error" ) mock_get_client.return_value = mock_client result = await register_collection_tools.tools[ "export_all_collections" ]() assert "Error exporting collections" in result assert "API error" in result

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Vortiago/mcp-outline'

If you have feedback or need assistance with the MCP directory API, please join our Discord server