using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using NUnit.Framework;
using Unity.Pipeline.Commands;
using Unity.Pipeline.Editor;
using Unity.Pipeline.Editor.Commands;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
namespace Unity.Pipeline.Tests.Editor
{
///
/// Tests for the menu command (CLI-110). Uses a test-only menu item so the positive path
/// is deterministic and free of side effects, rather than relying on built-in Editor menus.
///
public class MenuCommandTests
{
const string k_TestMenuPath = "PipelineTests/Invoke Marker";
static bool s_MarkerInvoked;
[MenuItem(k_TestMenuPath)]
static void InvokeMarker() => s_MarkerInvoked = true;
[SetUp]
public void SetUp()
{
CommandRegistry.SetDiscovery(new TypeCacheCommandDiscovery());
s_MarkerInvoked = false;
}
[Test]
public void Menu_IsDiscovered_WithExpectedSchema()
{
var cmd = CommandRegistry.DiscoverCommands().FirstOrDefault(c => c.Name == "menu");
Assert.IsNotNull(cmd, "Should discover the menu command");
Assert.IsTrue(cmd.MainThreadRequired, "menu calls Editor APIs and must run on the main thread");
Assert.AreEqual(1, cmd.Parameters.Count, "menu should take a single 'path' parameter");
var p = cmd.Parameters[0];
Assert.AreEqual("path", p.Name);
Assert.IsFalse(p.Required, "path should be optional (omitting it lists available items)");
}
[Test]
public void Menu_NoPath_ListsAvailableItems()
{
var result = MenuItemCommand.ExecuteMenu("");
Assert.IsTrue(result.Success, "Listing should succeed");
Assert.IsNotNull(result.Items, "Items should be populated in list mode");
Assert.Greater(result.Items.Count, 0, "There should be at least one discovered menu item");
// Our test-only [MenuItem] is declared via attribute, so it must be discoverable.
CollectionAssert.Contains(result.Items, k_TestMenuPath,
"The test menu item should appear in the discovered list");
Assert.IsFalse(s_MarkerInvoked, "Listing must not execute any menu item");
}
[Test]
public void Menu_NoPath_IncludesNativeMenuItems()
{
// The whole point of using Menu.GetMenuItems instead of a [MenuItem] TypeCache scan is to
// also surface menus Unity defines natively in C++ — e.g. the Assets menu built by
// AssetsMenu.cpp:Build. Those entries carry no [MenuItem] attribute, so this test proves
// the listing includes a native item the attribute-only approach would have missed.
var items = MenuItemCommand.ExecuteMenu("").Items;
Assert.IsNotNull(items);
// What the old attribute-only approach saw (trailing keyboard shortcuts stripped, so the
// paths compare against the live, shortcut-free menu paths).
var attributed = new HashSet(
TypeCache.GetMethodsWithAttribute