mcp-office-tools/tests/test_server.py
Ryan Malloy 31948d6ffc
Some checks are pending
Test Dashboard / test-and-dashboard (push) Waiting to run
Rename package to mcwaddams
Named for Milton Waddams, who was relocated to the basement with
boxes of legacy documents. He handles the .doc and .xls files from
1997 that nobody else wants to touch.

- Rename package from mcp-office-tools to mcwaddams
- Update author to Ryan Malloy
- Update all imports and references
- Add Office Space themed README narrative
- All 53 tests passing
2026-01-11 11:35:35 -07:00

157 lines
6.1 KiB
Python

"""Test suite for MCP Office Tools server with mixin architecture."""
import pytest
import tempfile
import os
from pathlib import Path
from unittest.mock import patch, MagicMock
# FastMCP testing - using direct tool access
from mcwaddams.server import app
from mcwaddams.utils import OfficeFileError
class TestServerInitialization:
"""Test server initialization and basic functionality."""
def test_app_creation(self):
"""Test that FastMCP app is created correctly."""
assert app is not None
assert hasattr(app, 'get_tools')
@pytest.mark.asyncio
async def test_all_mixins_tools_registered(self):
"""Test that all mixin tools are registered correctly."""
# Get all registered tool names
tool_names = await app.get_tools()
tool_names_set = set(tool_names)
# Expected tools from all mixins
expected_universal_tools = {
"extract_text",
"extract_images",
"extract_metadata",
"detect_office_format",
"analyze_document_health",
"get_supported_formats"
}
expected_word_tools = {"convert_to_markdown", "extract_word_tables", "analyze_word_structure"}
expected_excel_tools = {"analyze_excel_data", "extract_excel_formulas", "create_excel_chart_data"}
# Verify universal tools are registered
assert expected_universal_tools.issubset(tool_names_set), f"Missing universal tools: {expected_universal_tools - tool_names_set}"
# Verify word tools are registered
assert expected_word_tools.issubset(tool_names_set), f"Missing word tools: {expected_word_tools - tool_names_set}"
# Verify excel tools are registered
assert expected_excel_tools.issubset(tool_names_set), f"Missing excel tools: {expected_excel_tools - tool_names_set}"
# Verify minimum number of tools
assert len(tool_names) >= 12 # 6 universal + 3 word + 3 excel (+ future PowerPoint tools)
def test_mixin_composition_works(self):
"""Test that mixin composition created the expected server structure."""
# Import the server module to ensure all mixins are initialized
import mcwaddams.server as server_module
# Verify the mixins were created
assert hasattr(server_module, 'universal_mixin')
assert hasattr(server_module, 'word_mixin')
assert hasattr(server_module, 'excel_mixin')
assert hasattr(server_module, 'powerpoint_mixin')
# Verify mixin instances are correct types
from mcwaddams.mixins import UniversalMixin, WordMixin, ExcelMixin, PowerPointMixin
assert isinstance(server_module.universal_mixin, UniversalMixin)
assert isinstance(server_module.word_mixin, WordMixin)
assert isinstance(server_module.excel_mixin, ExcelMixin)
assert isinstance(server_module.powerpoint_mixin, PowerPointMixin)
class TestToolAccess:
"""Test tool accessibility and metadata."""
@pytest.mark.asyncio
async def test_get_tool_metadata(self):
"""Test getting tool metadata through FastMCP API."""
# Test that we can get tool metadata
tool = await app.get_tool("get_supported_formats")
assert tool is not None
assert tool.name == "get_supported_formats"
assert "Get list of all supported Office document formats" in tool.description
assert hasattr(tool, 'fn') # Has the actual function
@pytest.mark.asyncio
async def test_all_expected_tools_accessible(self):
"""Test that all expected tools are accessible via get_tool."""
expected_tools = [
# Universal tools
"extract_text",
"extract_images",
"extract_metadata",
"detect_office_format",
"analyze_document_health",
"get_supported_formats",
# Word tools
"convert_to_markdown",
"extract_word_tables",
"analyze_word_structure",
# Excel tools
"analyze_excel_data",
"extract_excel_formulas",
"create_excel_chart_data"
]
for tool_name in expected_tools:
tool = await app.get_tool(tool_name)
assert tool is not None, f"Tool {tool_name} should be accessible"
assert tool.name == tool_name
assert hasattr(tool, 'fn'), f"Tool {tool_name} should have a function"
@pytest.mark.asyncio
async def test_tool_function_binding(self):
"""Test that tools are properly bound to mixin instances."""
# Get a universal tool
universal_tool = await app.get_tool("get_supported_formats")
assert 'UniversalMixin' in str(type(universal_tool.fn.__self__))
# Get a word tool
word_tool = await app.get_tool("convert_to_markdown")
assert 'WordMixin' in str(type(word_tool.fn.__self__))
class TestMixinIntegration:
"""Test integration between different mixins."""
@pytest.mark.asyncio
async def test_universal_and_word_tools_coexist(self):
"""Test that universal and word tools can coexist properly."""
# Verify both universal and word tools are available
# This test confirms the mixin composition works correctly
# Get tools from both mixins
universal_tool = await app.get_tool("get_supported_formats")
word_tool = await app.get_tool("convert_to_markdown")
# Verify they're bound to different mixin instances
assert universal_tool.fn.__self__ != word_tool.fn.__self__
assert 'UniversalMixin' in str(type(universal_tool.fn.__self__))
assert 'WordMixin' in str(type(word_tool.fn.__self__))
@pytest.mark.asyncio
async def test_no_tool_name_conflicts(self):
"""Test that there are no tool name conflicts between mixins."""
tool_names = await app.get_tools()
# Verify no duplicates
assert len(tool_names) == len(set(tool_names)), "Tool names should be unique"
# Verify expected count: 7 universal + 10 word + 3 excel = 20
assert len(tool_names) == 20, f"Expected 20 tools, got {len(tool_names)}: {list(tool_names.keys())}"
if __name__ == "__main__":
pytest.main([__file__, "-v"])