using AcDream.App.Combat; using AcDream.App.Diagnostics; using AcDream.App.Input; using AcDream.UI.Abstractions.Input; namespace AcDream.App.Tests.Input; public sealed class GameplayInputCommandControllerTests { [Theory] [InlineData(InputAction.ToggleInventoryPanel, "inventory")] [InlineData(InputAction.AcdreamToggleDebugPanel, "debug")] [InlineData(InputAction.AcdreamToggleFlyMode, "fly-or-chase")] [InlineData(InputAction.AcdreamTogglePlayerMode, "player-mode")] [InlineData(InputAction.ToggleChatEntry, "chat")] [InlineData(InputAction.ToggleOptionsPanel, "settings")] [InlineData(InputAction.CombatToggleCombat, "combat")] public void RecognizedCommand_RoutesToTypedOwner( InputAction action, string expected) { var harness = new Harness(); bool handled = harness.Controller.Handle(action); Assert.True(handled); Assert.Equal([expected], harness.Calls); } [Fact] public void DiagnosticCommand_PrecedesRemainingCommandSwitch() { var harness = new Harness(); harness.Diagnostics.HandledAction = InputAction.AcdreamToggleDebugPanel; bool handled = harness.Controller.Handle( InputAction.AcdreamToggleDebugPanel); Assert.True(handled); Assert.Equal(["diagnostic"], harness.Calls); } [Fact] public void UnknownCommand_IsNotClaimed() { var harness = new Harness(); bool handled = harness.Controller.Handle(InputAction.MovementForward); Assert.False(handled); Assert.Empty(harness.Calls); } [Theory] [InlineData(true, true, true, "cancel-target")] [InlineData(false, true, true, "exit-fly")] [InlineData(false, false, true, "exit-player")] [InlineData(false, false, false, "close")] public void Escape_PreservesTargetFlyPlayerWindowPriority( bool targetMode, bool flyMode, bool playerMode, string expected) { var harness = new Harness { TargetMode = { IsActive = targetMode }, Camera = { IsFly = flyMode }, Player = { IsPlayer = playerMode }, }; bool handled = harness.Controller.Handle(InputAction.EscapeKey); Assert.True(handled); Assert.Equal([expected], harness.Calls); } private sealed class Harness { public Harness() { Retained = new FakeRetained(Calls); DevTools = new FakeDevTools(Calls); Diagnostics = new FakeDiagnostics(Calls); Player = new FakePlayerMode(Calls); TargetMode = new FakeTargetMode(Calls); Camera = new FakeCamera(Calls); Combat = new FakeCombat(Calls); Window = new FakeWindow(Calls); Controller = new GameplayInputCommandController( Retained, DevTools, Diagnostics, Player, TargetMode, Camera, Combat, Window); } public List Calls { get; } = []; public FakeRetained Retained { get; } public FakeDevTools DevTools { get; } public FakeDiagnostics Diagnostics { get; } public FakePlayerMode Player { get; } public FakeTargetMode TargetMode { get; } public FakeCamera Camera { get; } public FakeCombat Combat { get; } public FakeWindow Window { get; } public GameplayInputCommandController Controller { get; } } private sealed class FakeRetained(List calls) : IRetainedGameplayWindowCommands { public void ToggleInventory() => calls.Add("inventory"); } private sealed class FakeDevTools(List calls) : IDevToolsGameplayCommands { public void ToggleDebugPanel() => calls.Add("debug"); public void FocusChatInput() => calls.Add("chat"); public void ToggleSettingsPanel() => calls.Add("settings"); } private sealed class FakeDiagnostics(List calls) : IRuntimeDiagnosticCommands { public InputAction? HandledAction { get; set; } public bool Handle(InputAction action) { if (action != HandledAction) return false; calls.Add("diagnostic"); return true; } public void CycleTimeOfDay() => calls.Add("time"); public void CycleWeather() => calls.Add("weather"); public void ToggleCollisionWireframes() => calls.Add("collision"); } private sealed class FakePlayerMode(List calls) : IPlayerModeGameplayCommands { public bool IsPlayer { get; set; } public bool IsPlayerMode => IsPlayer; public void ToggleFlyOrChase() => calls.Add("fly-or-chase"); public void TogglePlayerMode() => calls.Add("player-mode"); public void ExitPlayerMode() => calls.Add("exit-player"); } private sealed class FakeTargetMode(List calls) : IItemTargetModeCommands { public bool IsActive { get; set; } public bool IsAnyTargetModeActive => IsActive; public void CancelTargetMode() => calls.Add("cancel-target"); } private sealed class FakeCamera(List calls) : IGameplayCameraModeCommands { public bool IsFly { get; set; } public bool IsFlyMode => IsFly; public void ExitFlyMode() => calls.Add("exit-fly"); } private sealed class FakeCombat(List calls) : ILiveCombatModeCommand { public void Toggle() => calls.Add("combat"); } private sealed class FakeWindow(List calls) : IGameplayWindowCommands { public void Close() => calls.Add("close"); } }