using System.Collections; using System.Reflection; using BumpCombat.Audio; using BumpCombat.Combat; using BumpCombat.Core; using BumpCombat.Enemies; using BumpCombat.Player; using BumpCombat.Progression; using BumpCombat.Spawning; using BumpCombat.UI; using NUnit.Framework; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.LowLevel; using UnityEngine.InputSystem.UI; using UnityEngine.SceneManagement; using UnityEngine.TestTools; using UnityEngine.EventSystems; using UnityEngine.UI; namespace BumpCombat.PlayModeTests { public sealed class PresentationAudioMenuTests { private const string SceneName = "CombatPrototype"; private float originalMaster; private float originalMusic; private float originalSfx; private bool capturedVolumes; private InputSettings.BackgroundBehavior previousBackgroundBehavior; private InputSettings.EditorInputBehaviorInPlayMode previousEditorInputBehavior; private bool previousRunInBackground; private Keyboard virtualKeyboard; private bool virtualKeyboardInputActive; [SetUp] public void SetUp() { ArtifactRewardController.GrantCatalogForTests = false; RunManager.ForceProductionModeForTests = true; Time.timeScale = 1f; capturedVolumes = false; } [TearDown] public void TearDown() { EndVirtualKeyboardInput(); BumpCombatAudioService service = Object.FindAnyObjectByType(); if (service != null && capturedVolumes) { service.SetMasterVolume(originalMaster); service.SetMusicVolume(originalMusic); service.SetSfxVolume(originalSfx); } ArtifactRewardController.GrantCatalogForTests = false; RunManager.ForceProductionModeForTests = false; Time.timeScale = 1f; } [Test] public void DevelopmentStartVisibility_RequiresEditorOrDevelopmentBuild() { MethodInfo predicate = typeof(RunMenuController).GetMethod( "IsDevelopmentStartVisible", BindingFlags.NonPublic | BindingFlags.Static); Assert.That(predicate, Is.Not.Null); Assert.That(predicate.Invoke(null, new object[] { false, false }), Is.False); Assert.That(predicate.Invoke(null, new object[] { true, false }), Is.True); Assert.That(predicate.Invoke(null, new object[] { false, true }), Is.True); } [UnityTest] public IEnumerator TitleStart_UnlocksRunAfterExplicitStart() { yield return LoadScene(); RunManager manager = Object.FindAnyObjectByType(); Assert.That(manager, Is.Not.Null); Assert.That(manager.IsTitleScreen, Is.True); Assert.That(RunManager.GameplayInputEnabled, Is.False); Assert.That(Time.timeScale, Is.Zero); Keyboard keyboard = BeginVirtualKeyboardInput(); try { yield return PressAndRelease(keyboard, Key.Space); Assert.That(manager.IsTitleScreen, Is.True, "Space opens the mode submenu without starting a run."); yield return PressAndRelease(keyboard, Key.Enter); } finally { EndVirtualKeyboardInput(); } Assert.That(manager.IsTitleScreen, Is.False); Assert.That(manager.IsProductionRun, Is.False); Assert.That(manager.UseDebugEventTimes, Is.True); Assert.That(manager.IsArtifactChargeUnlocked, Is.True); ArtifactRewardController rewards = Object.FindAnyObjectByType(); Assert.That(rewards, Is.Not.Null); yield return null; Assert.That(rewards.DebugIsSelectionVisible, Is.True); Assert.That(rewards.DebugChooseOption(0), Is.True); yield return null; Assert.That(rewards.DebugChooseOption(0), Is.True); yield return null; Assert.That(rewards.DebugChooseOption(0), Is.True); yield return null; RunTutorialController tutorials = Object.FindAnyObjectByType(); Assert.That(tutorials.DebugCurrentTutorial, Is.EqualTo(RunTutorialController.TutorialKind.Artifact)); Assert.That(tutorials.DebugContinue(), Is.True); Assert.That(tutorials.DebugCurrentTutorial, Is.EqualTo(RunTutorialController.TutorialKind.Guard)); Assert.That(tutorials.DebugContinue(), Is.True); Assert.That(tutorials.DebugCurrentTutorial, Is.EqualTo(RunTutorialController.TutorialKind.ArtifactEnhancement)); Assert.That(tutorials.DebugContinue(), Is.True); Assert.That(RunManager.GameplayInputEnabled, Is.True); Assert.That(Time.timeScale, Is.EqualTo(1f)); } [UnityTest] public IEnumerator TitleProductionStart_IsSecondKeyboardItemAndLabelsFit() { yield return LoadScene(); RunManager manager = Object.FindAnyObjectByType(); Transform menu = Object.FindAnyObjectByType() .transform.Find("Run Menu"); Text title = menu.Find("Title").GetComponent(); Assert.That(title.text, Is.EqualTo("Tiny Tackle Heroes")); float titlePreferredWidth = title.cachedTextGeneratorForLayout .GetPreferredWidth( title.text, title.GetGenerationSettings(Vector2.zero)) / title.pixelsPerUnit; Assert.That(title.cachedTextGeneratorForLayout.lineCount, Is.EqualTo(1)); Assert.That(titlePreferredWidth, Is.LessThanOrEqualTo(title.rectTransform.rect.width), "The game title must fit in its single-line title label."); string[] expectedLabels = { "게임시작", "설정", "업적", "나가기" }; for (int i = 0; i < expectedLabels.Length; i++) { Text label = menu.Find($"Button {i + 1}/Label").GetComponent(); Assert.That(label.text, Is.EqualTo(expectedLabels[i])); float preferredWidth = label.cachedTextGeneratorForLayout .GetPreferredWidth( label.text, label.GetGenerationSettings(Vector2.zero)) / label.pixelsPerUnit; Assert.That(label.cachedTextGeneratorForLayout.lineCount, Is.EqualTo(1)); float labelWidth = label.rectTransform.rect.width; Assert.That( preferredWidth, Is.LessThanOrEqualTo(labelWidth), $"{expectedLabels[i]} must fit in its single-line menu label."); } Keyboard keyboard = BeginVirtualKeyboardInput(); try { yield return PressAndRelease(keyboard, Key.Enter); Assert.That(manager.IsTitleScreen, Is.True, "Opening the mode submenu must not begin a run."); Transform submenu = menu; bool showDevelopment = Application.isEditor || Debug.isDebugBuild; var submenuLabels = new System.Collections.Generic.List(); if (showDevelopment) { submenuLabels.Add("개발용 시작"); } submenuLabels.Add("기본 모드"); submenuLabels.Add("챌린지 모드(준비 중)"); submenuLabels.Add("하드코어 모드(준비 중)"); submenuLabels.Add("뒤로"); for (int i = 0; i < submenuLabels.Count; i++) { Button button = submenu.Find($"Button {i + 1}").GetComponent