using NUnit.Framework; using System.IO; using System.Reflection; using TMPro; using UnityEditor; using UnityEngine; using UnityEngine.UI; using XGame; using XGame.EditorTools; using XWorld.Framework.ActorBehavior; public sealed class GameLobbyControllerLayoutTests { private const string PrefabPath = "Assets/Game/Art/UI/Prefab/UI_GameLobby.prefab"; private const string Fighter3DJsonPath = "../Doc/UIPrefabCreater/UI_Fighter3D.json"; private const string Fighter3DPrefabPath = "Assets/MiniGames/Fighter3D/res/UI/Prefab/UI_Fighter3D.prefab"; private const string Fighter3DStagePrefabPath = "Assets/MiniGames/Fighter3D/res/Prefab/Fighter3D_BattleStage.prefab"; private const string Fighter3DBehaviorConfigRoot = "Assets/MiniGames/Fighter3D/res/Config/ActorBehavior"; [Test] public void LobbyPanel_DocksToLeftMiddle() { GameObject instance = CreateLobbyInstance(); try { GameLobbyController controller = instance.GetComponent(); Assert.That(controller, Is.Not.Null); controller.BeginGames(); RectTransform panel = FindRect(instance.transform, "Panel_Lobby"); Assert.That(panel.anchorMin, Is.EqualTo(new Vector2(0f, 0.5f))); Assert.That(panel.anchorMax, Is.EqualTo(new Vector2(0f, 0.5f))); Assert.That(panel.pivot, Is.EqualTo(new Vector2(0f, 0.5f))); Assert.That(panel.anchoredPosition, Is.EqualTo(new Vector2(24f, 0f))); Assert.That(panel.sizeDelta, Is.EqualTo(new Vector2(520f, 296f))); } finally { Object.DestroyImmediate(instance); } } [Test] public void CollapseButton_StaysAttachedToLobbyPanelInLeftMiddleLayout() { GameObject instance = CreateLobbyInstance(); try { GameLobbyController controller = instance.GetComponent(); Assert.That(controller, Is.Not.Null); controller.BeginGames(); RectTransform button = FindRect(instance.transform, "Btn_Collapse"); Assert.That(button.anchorMin, Is.EqualTo(new Vector2(0f, 0.5f))); Assert.That(button.anchorMax, Is.EqualTo(new Vector2(0f, 0.5f))); Assert.That(button.pivot, Is.EqualTo(new Vector2(0f, 0.5f))); Assert.That(button.anchoredPosition, Is.EqualTo(new Vector2(544f, 0f))); Assert.That(button.sizeDelta, Is.EqualTo(new Vector2(48f, 72f))); } finally { Object.DestroyImmediate(instance); } } [Test] public void LobbyGameListPoll_WaitsForRefreshInterval() { MethodInfo method = FindGameListPollMethod(); Assert.That((bool)method.Invoke(null, new object[] { true, true, false, 4f, 5f }), Is.False); Assert.That((bool)method.Invoke(null, new object[] { true, true, false, 5f, 5f }), Is.True); } [Test] public void LobbyGameListPoll_DoesNotRunOutsideIdleConnectedLobby() { MethodInfo method = FindGameListPollMethod(); Assert.That((bool)method.Invoke(null, new object[] { false, true, false, 5f, 5f }), Is.False); Assert.That((bool)method.Invoke(null, new object[] { true, false, false, 5f, 5f }), Is.False); Assert.That((bool)method.Invoke(null, new object[] { true, true, true, 5f, 5f }), Is.False); } [Test] public void Fighter3DFallbackHud_UsesUnity2022BuiltinFont() { string source = File.ReadAllText("Assets/MiniGames/Fighter3D/scripts~/Client/FighterGameClient.cs"); Assert.That(source, Does.Contain("LegacyRuntime.ttf")); Assert.That(source, Does.Not.Contain("Arial.ttf")); } [Test] public void Fighter3DHudSource_CanBindGeneratedTmpText() { string source = File.ReadAllText("Assets/MiniGames/Fighter3D/scripts~/Client/FighterGameClient.cs"); Assert.That(source, Does.Contain("using TMPro;")); Assert.That(source, Does.Contain("TMP_Text")); } [Test] public void Fighter3DClientSource_UsesCommonActorPresentation() { string source = File.ReadAllText("Assets/MiniGames/Fighter3D/scripts~/Client/FighterGameClient.cs"); Assert.That(source, Does.Contain("MiniGameActorPresentation")); Assert.That(source, Does.Contain(Fighter3DBehaviorConfigRoot)); Assert.That(source, Does.Not.Contain(Fighter3DStagePrefabPath)); Assert.That(source, Does.Not.Contain("OnStagePrefabLoaded")); Assert.That(source, Does.Not.Contain("FighterStage")); } [Test] public void Fighter3DBehaviorConfigs_AreMiniGameScopedAndValid() { string skillJson = ReadAssetText(Fighter3DBehaviorConfigRoot + "/fighter3d_skill.json"); string flyObjectJson = ReadAssetText(Fighter3DBehaviorConfigRoot + "/fighter3d_flyobj.json"); string buffJson = ReadAssetText(Fighter3DBehaviorConfigRoot + "/fighter3d_buff.json"); BehaviorConfigCatalog catalog = BehaviorConfigCatalog.LoadFromJson("fighter3d", skillJson, flyObjectJson, buffJson); Assert.That(catalog.Type, Is.EqualTo("fighter3d")); Assert.That(catalog.Behaviors.ContainsKey("fighter3d_light"), Is.True); Assert.That(catalog.Behaviors.ContainsKey("fighter3d_heavy"), Is.True); Assert.That(catalog.FlyObjects.ContainsKey("fighter3d_blade_wave"), Is.True); } [Test] public void Fighter3DUiJson_PassesPrefabBuilderValidation() { ValidationResult result = JsonUIPrefabBuilder.Validate(Fighter3DJsonPath); Assert.That(result.Ok, Is.True, string.Join("\n", result.Errors)); } [Test] public void Fighter3DPrefab_ProvidesHudBindings() { GameObject prefab = AssetDatabase.LoadAssetAtPath(Fighter3DPrefabPath); Assert.That(prefab, Is.Not.Null); Assert.That(FindComponent(prefab.transform, "Txt_Title"), Is.Not.Null); Assert.That(FindComponent(prefab.transform, "Txt_Left"), Is.Not.Null); Assert.That(FindComponent(prefab.transform, "Txt_Right"), Is.Not.Null); Image leftHp = FindComponent(prefab.transform, "Img_LeftHpFill"); Image rightHp = FindComponent(prefab.transform, "Img_RightHpFill"); Assert.That(leftHp, Is.Not.Null); Assert.That(rightHp, Is.Not.Null); Assert.That(leftHp.type, Is.EqualTo(Image.Type.Filled)); Assert.That(leftHp.fillMethod, Is.EqualTo(Image.FillMethod.Horizontal)); Assert.That(rightHp.type, Is.EqualTo(Image.Type.Filled)); Assert.That(rightHp.fillMethod, Is.EqualTo(Image.FillMethod.Horizontal)); } private static GameObject CreateLobbyInstance() { GameObject prefab = AssetDatabase.LoadAssetAtPath(PrefabPath); Assert.That(prefab, Is.Not.Null); return Object.Instantiate(prefab); } private static RectTransform FindRect(Transform root, string name) { Transform child = root.FindTransform(name); Assert.That(child, Is.Not.Null); RectTransform rect = child.GetComponent(); Assert.That(rect, Is.Not.Null); return rect; } private static MethodInfo FindGameListPollMethod() { MethodInfo method = typeof(CSharpClientApp).GetMethod( "ShouldPollGameList", BindingFlags.Static | BindingFlags.NonPublic); Assert.That(method, Is.Not.Null); return method; } private static T FindComponent(Transform root, string name) where T : Component { Transform child = root.FindTransform(name); return child == null ? null : child.GetComponent(); } private static string ReadAssetText(string assetPath) { TextAsset asset = AssetDatabase.LoadAssetAtPath(assetPath); Assert.That(asset, Is.Not.Null, assetPath); return asset.text; } }