using System.Collections.Generic;
using NUnit.Framework;
using Unity.Pipeline.Editor.Commands.Navigation;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
using Unity.Pipeline;
namespace Unity.Pipeline.Tests.Editor.Navigation
{
///
/// Tests for the navigation/targeting commands (CLI-200): get_selection, set_selection, and
/// search, exercised directly and via PipelineClient. Mirrors FolderCommandsTests for the
/// ViaClient style. Project contents are unknown, so search assertions check structural success
/// rather than a specific count.
///
public class NavigationCommandsTests
{
private readonly List m_Temp = new List();
[TearDown]
public void TearDown()
{
Selection.objects = new Object[0];
foreach (var go in m_Temp)
{
if (go != null)
Object.DestroyImmediate(go);
}
m_Temp.Clear();
}
private GameObject NewTempObject(string name)
{
var go = new GameObject(name);
m_Temp.Add(go);
return go;
}
#region Direct
[Test]
public void GetSelection_ReflectsActiveObject()
{
var go = NewTempObject("CLI200_GetSelection");
Selection.activeObject = go;
var result = NavigationCommands.GetSelection();
Assert.IsNotNull(result);
Assert.GreaterOrEqual(result.Count, 1);
Assert.IsNotNull(result.Active, "Active object should be described");
Assert.AreEqual(PipelineUtils.GetObjectId(go), result.Active.InstanceId);
}
[Test]
public void SetSelection_ByInstanceId_SelectsObject()
{
var go = NewTempObject("CLI200_SetSelection");
var result = NavigationCommands.SetSelection(instanceIds: new[] { PipelineUtils.GetObjectId(go) });
Assert.AreSame(go, Selection.activeObject, "Selection.activeObject should be the requested object");
Assert.AreEqual(1, result.Count);
Assert.AreEqual(PipelineUtils.GetObjectId(go), result.Active.InstanceId);
}
[Test]
public void SetSelection_ByPath_SelectsAsset()
{
// "Assets" is always present and loads as a DefaultAsset, so this needs no project content.
var result = NavigationCommands.SetSelection(paths: new[] { "Assets" });
Assert.AreSame(
AssetDatabase.LoadMainAssetAtPath("Assets"),
Selection.activeObject,
"Selection.activeObject should be the asset loaded from the requested path");
Assert.AreEqual(1, result.Count);
}
[Test]
public void SetSelection_NoInputs_ClearsSelection()
{
var go = NewTempObject("CLI200_ClearSelection");
Selection.activeObject = go;
var result = NavigationCommands.SetSelection();
Assert.AreEqual(0, result.Count);
Assert.IsNull(Selection.activeObject, "Empty inputs should clear the selection");
}
[Test]
public void SetSelection_UnresolvedInput_Throws()
{
// 0 is never a valid instance id, and an empty list of resolved objects with inputs
// present is a hard error rather than a silent clear.
Assert.Throws(
() => NavigationCommands.SetSelection(instanceIds: new[] { ObjectId.FromRaw(0) }));
}
[Test]
public void Search_DefaultAsset_ReturnsStructuredResult()
{
// "t:DefaultAsset" is guaranteed not to throw regardless of project contents.
var result = NavigationCommands.Search("t:DefaultAsset", 10);
Assert.IsNotNull(result);
Assert.AreEqual("t:DefaultAsset", result.Query);
Assert.GreaterOrEqual(result.Count, 0);
Assert.IsNotNull(result.Results);
Assert.LessOrEqual(result.Count, 10, "Result count should respect the limit");
}
#endregion
#region ViaClient
[Test]
public void GetSelection_ViaClient_Succeeds()
{
using (var server = new PipelineTestServer())
{
var response = server.Execute("get_selection");
Assert.IsTrue(response.IsSuccess, $"get_selection should succeed: {response.Error}");
Assert.IsTrue(response.HasValidJson, "Response should have valid JSON");
Assert.IsTrue(response.JsonResponse.ContainsKey("result"), "Should have result field");
}
}
[Test]
public void Search_ViaClient_Succeeds()
{
using (var server = new PipelineTestServer())
{
var response = server.Execute("search", new { query = "t:DefaultAsset", limit = 5 });
Assert.IsTrue(response.IsSuccess, $"search should succeed: {response.Error}");
Assert.IsTrue(response.HasValidJson, "Response should have valid JSON");
Assert.IsTrue(response.JsonResponse.ContainsKey("result"), "Should have result field");
}
}
#endregion
}
}