| """Unit tests for version 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.version_tools import register_version_tools |
|
|
|
|
| @pytest.fixture |
| def mock_mcp(): |
| """Create a mock MCP server for testing.""" |
| mock = MagicMock() |
| |
| 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_version_success(mock_mcp, mock_context): |
| """Test successful version creation.""" |
| register_version_tools(mock_mcp) |
|
|
| |
| manage_version = mock_mcp._tools.get("manage_version") |
|
|
| assert manage_version is not None, "manage_version tool not registered" |
|
|
| |
| mock_response = MagicMock() |
| mock_response.status_code = 200 |
| mock_response.json.return_value = { |
| "version": {"version_number": 3, "field_name": "docs"}, |
| "message": "Version created successfully", |
| } |
|
|
| with patch("src.mcp_server.features.documents.version_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 |
|
|
| result = await manage_version( |
| mock_context, |
| action="create", |
| project_id="project-123", |
| field_name="docs", |
| content=[{"id": "doc-1", "title": "Test Doc"}], |
| change_summary="Added test document", |
| ) |
|
|
| result_data = json.loads(result) |
| assert result_data["success"] is True |
| assert result_data["version"]["version_number"] == 3 |
| assert "Version created successfully" in result_data["message"] |
|
|
|
|
| @pytest.mark.asyncio |
| async def test_create_version_invalid_field(mock_mcp, mock_context): |
| """Test version creation with invalid field name.""" |
| register_version_tools(mock_mcp) |
|
|
| manage_version = mock_mcp._tools.get("manage_version") |
|
|
| |
| mock_response = MagicMock() |
| mock_response.status_code = 400 |
| mock_response.text = "invalid field_name" |
|
|
| with patch("src.mcp_server.features.documents.version_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 |
|
|
| result = await manage_version( |
| mock_context, action="create", project_id="project-123", field_name="invalid", content={"test": "data"} |
| ) |
|
|
| result_data = json.loads(result) |
| assert result_data["success"] is False |
| |
| 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" |
|
|
|
|
| @pytest.mark.asyncio |
| async def test_restore_version_success(mock_mcp, mock_context): |
| """Test successful version restoration.""" |
| register_version_tools(mock_mcp) |
|
|
| |
| manage_version = mock_mcp._tools.get("manage_version") |
|
|
| assert manage_version is not None, "manage_version tool not registered" |
|
|
| |
| mock_response = MagicMock() |
| mock_response.status_code = 200 |
| mock_response.json.return_value = {"message": "Version 2 restored successfully"} |
|
|
| with patch("src.mcp_server.features.documents.version_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 |
|
|
| result = await manage_version( |
| mock_context, |
| action="restore", |
| project_id="project-123", |
| field_name="docs", |
| version_number=2, |
| ) |
|
|
| result_data = json.loads(result) |
| assert result_data["success"] is True |
| assert "restored successfully" in result_data["message"] |
|
|
|
|
| @pytest.mark.asyncio |
| async def test_find_versions_with_filter(mock_mcp, mock_context): |
| """Test listing versions with field name filter.""" |
| register_version_tools(mock_mcp) |
|
|
| |
| find_versions = mock_mcp._tools.get("find_versions") |
|
|
| assert find_versions is not None, "find_versions tool not registered" |
|
|
| |
| mock_response = MagicMock() |
| mock_response.status_code = 200 |
| mock_response.json.return_value = { |
| "versions": [ |
| {"version_number": 1, "field_name": "docs", "change_summary": "Initial"}, |
| {"version_number": 2, "field_name": "docs", "change_summary": "Updated"}, |
| ] |
| } |
|
|
| with patch("src.mcp_server.features.documents.version_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_versions(mock_context, project_id="project-123", field_name="docs") |
|
|
| result_data = json.loads(result) |
| assert result_data["success"] is True |
| assert result_data["count"] == 2 |
| assert len(result_data["versions"]) == 2 |
|
|
| |
| call_args = mock_async_client.get.call_args |
| assert call_args[1]["params"]["field_name"] == "docs" |
|
|