Skip to main content
Glama
test_graph.py8.88 kB
"""Tests for Microsoft Graph API client.""" import base64 from datetime import datetime import httpx import pytest import respx from sharepoint_mcp.graph import GraphAPIError, GraphClient from sharepoint_mcp.models import ( FileContent, FileListResult, FileMetadata, Library, Site, ) @pytest.mark.asyncio @respx.mock async def test_get_sites( mock_graph_client: GraphClient, sample_site_response: dict, ): """Test getting list of sites.""" respx.get("https://graph.microsoft.com/v1.0/sites?search=*").mock( return_value=httpx.Response(200, json=sample_site_response) ) sites = await mock_graph_client.get_sites() assert len(sites) == 2 assert isinstance(sites[0], Site) assert sites[0].id == "site-1" assert sites[0].name == "Marketing Site" assert sites[0].url == "https://contoso.sharepoint.com/sites/marketing" assert sites[0].description == "Marketing team site" @pytest.mark.asyncio @respx.mock async def test_get_sites_with_search( mock_graph_client: GraphClient, sample_site_response: dict, ): """Test searching for sites.""" respx.get("https://graph.microsoft.com/v1.0/sites?search=Marketing").mock( return_value=httpx.Response(200, json=sample_site_response) ) sites = await mock_graph_client.get_sites(search="Marketing") assert len(sites) == 2 @pytest.mark.asyncio @respx.mock async def test_get_libraries( mock_graph_client: GraphClient, sample_library_response: dict, ): """Test getting libraries for a site.""" respx.get("https://graph.microsoft.com/v1.0/sites/site-1/drives").mock( return_value=httpx.Response(200, json=sample_library_response) ) libraries = await mock_graph_client.get_libraries("site-1") assert len(libraries) == 2 assert isinstance(libraries[0], Library) assert libraries[0].id == "drive-1" assert libraries[0].name == "Documents" assert libraries[0].item_count == 42 @pytest.mark.asyncio @respx.mock async def test_list_files( mock_graph_client: GraphClient, sample_file_response: dict, ): """Test listing files in a library.""" respx.get("https://graph.microsoft.com/v1.0/sites/site-1/drives/drive-1/root/children?$top=50").mock( return_value=httpx.Response(200, json=sample_file_response) ) result = await mock_graph_client.list_files("site-1", "drive-1") assert isinstance(result, FileListResult) assert len(result.files) == 2 assert isinstance(result.files[0], FileMetadata) assert result.files[0].id == "file-1" assert result.files[0].name == "report.pdf" assert result.files[0].size == 1024000 assert result.next_cursor is not None @pytest.mark.asyncio @respx.mock async def test_list_files_with_folder_path( mock_graph_client: GraphClient, sample_file_response: dict, ): """Test listing files in a specific folder.""" respx.get( "https://graph.microsoft.com/v1.0/sites/site-1/drives/drive-1/root:/Projects:/children?$top=50" ).mock(return_value=httpx.Response(200, json=sample_file_response)) result = await mock_graph_client.list_files("site-1", "drive-1", folder_path="Projects") assert len(result.files) == 2 @pytest.mark.asyncio @respx.mock async def test_get_file_metadata( mock_graph_client: GraphClient, ): """Test getting file metadata.""" file_data = { "id": "file-1", "name": "document.docx", "size": 50000, "webUrl": "https://contoso.sharepoint.com/sites/site/doc.docx", "createdDateTime": "2025-01-01T10:00:00Z", "lastModifiedDateTime": "2025-01-05T14:30:00Z", "file": {"mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, "createdBy": {"user": {"displayName": "John Doe"}}, "lastModifiedBy": {"user": {"displayName": "Jane Smith"}}, } respx.get("https://graph.microsoft.com/v1.0/sites/site-1/drive/items/file-1").mock( return_value=httpx.Response(200, json=file_data) ) metadata = await mock_graph_client.get_file_metadata("site-1", "file-1") assert isinstance(metadata, FileMetadata) assert metadata.id == "file-1" assert metadata.name == "document.docx" assert metadata.size == 50000 assert metadata.created_by == "John Doe" assert metadata.modified_by == "Jane Smith" @pytest.mark.asyncio @respx.mock async def test_download_text_file( mock_graph_client: GraphClient, ): """Test downloading a text file.""" # Mock metadata request file_data = { "id": "file-1", "name": "readme.txt", "size": 100, "webUrl": "https://contoso.sharepoint.com/readme.txt", "createdDateTime": "2025-01-01T10:00:00Z", "lastModifiedDateTime": "2025-01-01T10:00:00Z", "file": {"mimeType": "text/plain"}, "createdBy": {"user": {"displayName": "Test User"}}, "lastModifiedBy": {"user": {"displayName": "Test User"}}, } respx.get("https://graph.microsoft.com/v1.0/sites/site-1/drive/items/file-1").mock( return_value=httpx.Response(200, json=file_data) ) # Mock content download file_content = b"Hello, World!\nThis is a test file." respx.get("https://graph.microsoft.com/v1.0/sites/site-1/drive/items/file-1/content").mock( return_value=httpx.Response(200, content=file_content) ) result = await mock_graph_client.download_file("site-1", "file-1") assert isinstance(result, FileContent) assert result.name == "readme.txt" assert result.mime_type == "text/plain" assert result.is_text is True assert result.content == "Hello, World!\nThis is a test file." @pytest.mark.asyncio @respx.mock async def test_download_binary_file( mock_graph_client: GraphClient, ): """Test downloading a binary file (returns base64).""" # Mock metadata request file_data = { "id": "file-2", "name": "image.png", "size": 1000, "webUrl": "https://contoso.sharepoint.com/image.png", "createdDateTime": "2025-01-01T10:00:00Z", "lastModifiedDateTime": "2025-01-01T10:00:00Z", "file": {"mimeType": "image/png"}, "createdBy": {"user": {"displayName": "Test User"}}, "lastModifiedBy": {"user": {"displayName": "Test User"}}, } respx.get("https://graph.microsoft.com/v1.0/sites/site-1/drive/items/file-2").mock( return_value=httpx.Response(200, json=file_data) ) # Mock content download file_content = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR" respx.get("https://graph.microsoft.com/v1.0/sites/site-1/drive/items/file-2/content").mock( return_value=httpx.Response(200, content=file_content) ) result = await mock_graph_client.download_file("site-1", "file-2") assert isinstance(result, FileContent) assert result.name == "image.png" assert result.mime_type == "image/png" assert result.is_text is False # Verify content is base64 encoded decoded = base64.b64decode(result.content) assert decoded == file_content @pytest.mark.asyncio @respx.mock async def test_download_file_too_large( mock_graph_client: GraphClient, ): """Test that downloading a file > 10MB raises an error.""" file_data = { "id": "file-3", "name": "large.zip", "size": 20 * 1024 * 1024, # 20MB "webUrl": "https://contoso.sharepoint.com/large.zip", "createdDateTime": "2025-01-01T10:00:00Z", "lastModifiedDateTime": "2025-01-01T10:00:00Z", "file": {"mimeType": "application/zip"}, "createdBy": {"user": {"displayName": "Test User"}}, "lastModifiedBy": {"user": {"displayName": "Test User"}}, } respx.get("https://graph.microsoft.com/v1.0/sites/site-1/drive/items/file-3").mock( return_value=httpx.Response(200, json=file_data) ) with pytest.raises(GraphAPIError, match="File too large"): await mock_graph_client.download_file("site-1", "file-3") @pytest.mark.asyncio @respx.mock async def test_get_current_user( mock_graph_client: GraphClient, sample_user_response: dict, ): """Test getting current user information.""" respx.get("https://graph.microsoft.com/v1.0/me").mock( return_value=httpx.Response(200, json=sample_user_response) ) user = await mock_graph_client.get_current_user() assert user["id"] == "user-1" assert user["displayName"] == "Test User" assert user["mail"] == "test.user@contoso.com" @pytest.mark.asyncio async def test_close_client(mock_graph_client: GraphClient): """Test closing the HTTP client.""" # Initialize client by making a request await mock_graph_client._get_client() assert mock_graph_client._client is not None # Close it await mock_graph_client.close() assert mock_graph_client._client is None

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/ezemriv/sharepoint-mcp'

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