using System.Collections; using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; using BaseGames.UI; namespace BaseGames.Tests.PlayMode { /// /// UIManager 烟雾测试:验证面板栈基本不变式。 /// /// 覆盖: /// · OpenPanel → CloseTopPanel 后栈为空; /// · 嵌套打开(A → B → CloseTop)后 A 仍处于激活态; /// · 重复 OpenPanel 同一面板不会双压栈(HashSet 去重)。 /// /// 注:测试只覆盖框架行为,不验证业务面板(CharmPanel 等)的内部逻辑。 /// public class UIManagerSmokeTest { private GameObject _hostGO; private UIManager _manager; private GameObject _panelA; private GameObject _panelB; [SetUp] public void SetUp() { _hostGO = new GameObject("UIManager_Host"); _manager = _hostGO.AddComponent(); _panelA = new GameObject("PanelA"); _panelB = new GameObject("PanelB"); _panelA.SetActive(false); _panelB.SetActive(false); // 强制 OnEnable 触发(AddComponent 同帧已触发,这里二次启用保证 ServiceLocator 状态) _hostGO.SetActive(false); _hostGO.SetActive(true); } [TearDown] public void TearDown() { Object.DestroyImmediate(_panelA); Object.DestroyImmediate(_panelB); Object.DestroyImmediate(_hostGO); } [UnityTest] public IEnumerator OpenThenCloseTop_PanelDeactivated() { _manager.OpenPanel(_panelA); yield return null; Assert.IsTrue(_panelA.activeSelf, "OpenPanel 应当激活面板"); _manager.CloseTopPanel(); yield return null; Assert.IsFalse(_panelA.activeSelf, "CloseTopPanel 应当反激活栈顶面板"); } [UnityTest] public IEnumerator NestedOpen_PreviousPanelHiddenAndRestored() { _manager.OpenPanel(_panelA); _manager.OpenPanel(_panelB); yield return null; Assert.IsFalse(_panelA.activeSelf, "嵌套打开时上一层应被隐藏"); Assert.IsTrue(_panelB.activeSelf, "新打开的面板应当激活"); _manager.CloseTopPanel(); yield return null; Assert.IsTrue(_panelA.activeSelf, "关闭栈顶后上一层应当恢复"); Assert.IsFalse(_panelB.activeSelf, "关闭后栈顶面板应当反激活"); } [UnityTest] public IEnumerator DoubleOpenSamePanel_NoStackDuplication() { _manager.OpenPanel(_panelA); _manager.OpenPanel(_panelA); yield return null; // 关闭一次后栈应为空 _manager.CloseTopPanel(); yield return null; Assert.IsFalse(_panelA.activeSelf, "重复打开应被去重;关闭一次后即应隐藏"); } } }