unity-mcp/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageSceneHierarchyPagingT...

106 lines
4.1 KiB
C#
Raw Normal View History

Payload-safe paging for hierarchy/components + safer asset search + docs (#490) * Fix test teardown to avoid dropping MCP bridge CodexConfigHelperTests was calling MCPServiceLocator.Reset() in TearDown, which disposes the active bridge/transport during MCP-driven test runs. Replace with restoring only the mutated service (IPlatformService). * Avoid leaking PlatformService in CodexConfigHelperTests Capture the original IPlatformService before this fixture runs and restore it in TearDown. This preserves the MCP connection safety fix (no MCPServiceLocator.Reset()) while avoiding global state leakage to subsequent tests. * Fix SO MCP tooling: validate folder roots, normalize paths, expand tests; remove vestigial SO tools * Remove UnityMCPTests stress artifacts and ignore Assets/Temp * Ignore UnityMCPTests Assets/Temp only * Clarify array_resize fallback logic comments * Refactor: simplify action set and reuse slash sanitization * Enhance: preserve GUID on overwrite & support Vector/Color types in ScriptableObject tools * Fix: ensure asset name matches filename to suppress Unity warnings * Fix: resolve Unity warnings by ensuring asset name match and removing redundant import * Refactor: Validate assetName, strict object parsing for vectors, remove broken SO logic from ManageAsset * Hardening: reject Windows drive paths; clarify supported asset types * Delete FixscriptableobjecPlan.md * Paginate get_hierarchy and get_components to prevent large payload crashes * dev: add uvx dev-mode refresh + safer HTTP stop; fix server typing eval * Payload-safe paging defaults + docs; harden asset search; stabilize Codex tests * chore: align uvx args + coercion helpers; tighten safety guidance * chore: minor cleanup + stabilize EditMode SO tests
2025-12-29 12:57:57 +08:00
using NUnit.Framework;
using UnityEngine;
using Newtonsoft.Json.Linq;
using MCPForUnity.Editor.Tools;
namespace MCPForUnityTests.Editor.Tools
{
public class ManageSceneHierarchyPagingTests
{
private GameObject _root;
private readonly System.Collections.Generic.List<GameObject> _created = new System.Collections.Generic.List<GameObject>();
[TearDown]
public void TearDown()
{
for (int i = 0; i < _created.Count; i++)
{
if (_created[i] != null) Object.DestroyImmediate(_created[i]);
}
_created.Clear();
if (_root != null)
{
Object.DestroyImmediate(_root);
_root = null;
}
}
[Test]
public void GetHierarchy_PaginatesRoots_AndSupportsChildrenPaging()
{
// Arrange: create many roots so paging must occur.
// Note: Keep counts modest to avoid slowing EditMode tests.
const int rootCount = 40;
for (int i = 0; i < rootCount; i++)
{
_created.Add(new GameObject($"HS_Root_{i:D2}"));
}
_root = new GameObject("HS_Parent");
for (int i = 0; i < 15; i++)
{
var child = new GameObject($"HS_Child_{i:D2}");
child.transform.SetParent(_root.transform);
}
// Act: request a small page to force truncation
var p1 = new JObject
{
["action"] = "get_hierarchy",
["pageSize"] = 10,
};
var raw1 = ManageScene.HandleCommand(p1);
var res1 = raw1 as JObject ?? JObject.FromObject(raw1);
// Assert: envelope success + payload shape
Assert.IsTrue(res1.Value<bool>("success"), res1.ToString());
var data1 = res1["data"] as JObject;
Assert.IsNotNull(data1, "Expected data payload to be an object.");
Assert.AreEqual("roots", data1.Value<string>("scope"));
Assert.AreEqual(true, data1.Value<bool>("truncated"), "Expected truncation when pageSize < root count.");
Assert.IsNotNull(data1["next_cursor"], "Expected next_cursor when truncated.");
var items1 = data1["items"] as JArray;
Assert.IsNotNull(items1, "Expected items array.");
Assert.AreEqual(10, items1.Count, "Expected exactly pageSize items returned.");
// Act: fetch next page of roots using next_cursor
var cursor = data1.Value<string>("next_cursor");
var p2 = new JObject
{
["action"] = "get_hierarchy",
["pageSize"] = 10,
["cursor"] = cursor,
};
var raw2 = ManageScene.HandleCommand(p2);
var res2 = raw2 as JObject ?? JObject.FromObject(raw2);
Assert.IsTrue(res2.Value<bool>("success"), res2.ToString());
var data2 = res2["data"] as JObject;
Assert.IsNotNull(data2);
var items2 = data2["items"] as JArray;
Assert.IsNotNull(items2);
Assert.AreEqual(10, items2.Count);
// Act: page children of a specific parent via 'parent' param (instance ID)
var pChildren = new JObject
{
["action"] = "get_hierarchy",
["parent"] = _root.GetInstanceID(),
["pageSize"] = 7,
};
var rawChildren = ManageScene.HandleCommand(pChildren);
var resChildren = rawChildren as JObject ?? JObject.FromObject(rawChildren);
Assert.IsTrue(resChildren.Value<bool>("success"), resChildren.ToString());
var dataChildren = resChildren["data"] as JObject;
Assert.IsNotNull(dataChildren);
Assert.AreEqual("children", dataChildren.Value<string>("scope"));
Assert.AreEqual(true, dataChildren.Value<bool>("truncated"));
Assert.IsNotNull(dataChildren["next_cursor"]);
var childItems = dataChildren["items"] as JArray;
Assert.IsNotNull(childItems);
Assert.AreEqual(7, childItems.Count);
}
}
}