- Add MCP server with real Unreal Remote Execution Protocol (UDP 6766 + TCP 6776) - Implement 12 MCP tools: project intelligence, scene manipulation, debug/profiling, blueprint ops - Add enhanced .uasset parser with UE4/UE5 support - Create /blueprint-workflow skill (analyze, bp-to-cpp, cpp-to-bp, transform, optimize) - Include 21 passing tests - Add complete user documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
101 lines
2.9 KiB
Python
101 lines
2.9 KiB
Python
"""Tests for project intelligence tools."""
|
|
|
|
import pytest
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock
|
|
|
|
from unreal_mcp.tools.project import (
|
|
get_spawnable_classes,
|
|
get_project_assets,
|
|
scan_cpp_classes,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_spawnable_classes_offline(
|
|
mock_connection_with_project: MagicMock,
|
|
) -> None:
|
|
"""Test get_spawnable_classes in offline mode."""
|
|
result = await get_spawnable_classes(mock_connection_with_project)
|
|
|
|
assert result["success"] is True
|
|
assert "data" in result
|
|
assert "blueprint_actors" in result["data"]
|
|
# Should find the BP_Enemy and BP_Player from sample project
|
|
bp_names = [bp["name"] for bp in result["data"]["blueprint_actors"]]
|
|
assert "BP_Enemy" in bp_names
|
|
assert "BP_Player" in bp_names
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_spawnable_classes_filter_blueprint(
|
|
mock_connection_with_project: MagicMock,
|
|
) -> None:
|
|
"""Test get_spawnable_classes with blueprint filter."""
|
|
result = await get_spawnable_classes(
|
|
mock_connection_with_project,
|
|
filter_type="blueprint",
|
|
)
|
|
|
|
assert result["success"] is True
|
|
assert result["data"]["native_actors"] == []
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_project_assets(
|
|
mock_connection_with_project: MagicMock,
|
|
) -> None:
|
|
"""Test get_project_assets."""
|
|
result = await get_project_assets(mock_connection_with_project)
|
|
|
|
assert result["success"] is True
|
|
assert "data" in result
|
|
assert result["data"]["total"] >= 2
|
|
assert "Blueprint" in result["data"]["by_type"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_project_assets_no_path(
|
|
mock_connection: MagicMock,
|
|
) -> None:
|
|
"""Test get_project_assets without project path."""
|
|
result = await get_project_assets(mock_connection)
|
|
|
|
assert result["success"] is False
|
|
assert result["code"] == "NO_PROJECT_PATH"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_scan_cpp_classes(
|
|
mock_connection_with_project: MagicMock,
|
|
) -> None:
|
|
"""Test scan_cpp_classes."""
|
|
result = await scan_cpp_classes(mock_connection_with_project)
|
|
|
|
assert result["success"] is True
|
|
assert "data" in result
|
|
classes = result["data"]
|
|
assert len(classes) >= 1
|
|
|
|
# Find our test actor
|
|
test_actor = next((c for c in classes if c["name"] == "ATestActor"), None)
|
|
assert test_actor is not None
|
|
assert test_actor["parent"] == "AActor"
|
|
assert test_actor["is_blueprintable"] is True
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_scan_cpp_classes_filter_blueprintable(
|
|
mock_connection_with_project: MagicMock,
|
|
) -> None:
|
|
"""Test scan_cpp_classes with blueprintable filter."""
|
|
result = await scan_cpp_classes(
|
|
mock_connection_with_project,
|
|
filter_blueprintable=True,
|
|
)
|
|
|
|
assert result["success"] is True
|
|
# All returned classes should be blueprintable
|
|
for cls in result["data"]:
|
|
assert cls["is_blueprintable"] is True
|