acdream/tests/AcDream.App.Tests/Input/DispatcherMovementInputSourceTests.cs

152 lines
4.9 KiB
C#

using AcDream.App.Input;
using AcDream.UI.Abstractions.Input;
using Silk.NET.Input;
namespace AcDream.App.Tests.Input;
public sealed class DispatcherMovementInputSourceTests
{
[Fact]
public void UnboundSourceCapturesNeutralInput()
{
var source = new DispatcherMovementInputSource();
Assert.Equal(default, source.Capture());
}
[Fact]
public void CapturesDispatcherHeldStateAndRetailWalkModifier()
{
var (dispatcher, _, _) = CreateDispatcher();
var source = new DispatcherMovementInputSource();
source.Bind(dispatcher);
Assert.True(dispatcher.TrySetAutomationActionHeld(
InputAction.MovementForward,
held: true));
Assert.True(dispatcher.TrySetAutomationActionHeld(
InputAction.MovementWalkMode,
held: true));
MovementInput captured = source.Capture();
Assert.True(captured.Forward);
Assert.False(captured.Run);
}
[Fact]
public void RetainedKeyboardCaptureSilencesHeldKeysButDoesNotCancelAutorun()
{
var (dispatcher, _, mouse) = CreateDispatcher();
var source = new DispatcherMovementInputSource();
source.Bind(dispatcher);
dispatcher.TrySetAutomationActionHeld(InputAction.MovementForward, held: true);
Assert.True(source.HandlePressedAction(InputAction.MovementRunLock));
mouse.WantCaptureKeyboard = true;
MovementInput captured = source.Capture();
Assert.True(captured.Forward);
Assert.True(source.AutoRunActive);
source.HandlePressedAction(InputAction.MovementRunLock);
captured = source.Capture();
Assert.False(captured.Forward);
}
[Fact]
public void DevToolsKeyboardCapturePausesAutorunWithoutClearingItsLatch()
{
var capture = new FakeCapture();
var (dispatcher, _, _) = CreateDispatcher();
var source = new DispatcherMovementInputSource(capture);
source.Bind(dispatcher);
source.HandlePressedAction(InputAction.MovementRunLock);
capture.DevToolsWantCaptureKeyboard = true;
Assert.Equal(default, source.Capture());
Assert.True(source.AutoRunActive);
capture.DevToolsWantCaptureKeyboard = false;
Assert.True(source.Capture().Forward);
}
[Theory]
[InlineData(InputAction.MovementBackup)]
[InlineData(InputAction.MovementStop)]
[InlineData(InputAction.MovementStrafeLeft)]
[InlineData(InputAction.MovementStrafeRight)]
public void RetailCancelActionsClearAutorun(InputAction action)
{
var source = new DispatcherMovementInputSource();
source.HandlePressedAction(InputAction.MovementRunLock);
Assert.False(source.HandlePressedAction(action));
Assert.False(source.AutoRunActive);
}
[Fact]
public void ForwardDoesNotCancelAutorunAndResetDoes()
{
var source = new DispatcherMovementInputSource();
source.HandlePressedAction(InputAction.MovementRunLock);
Assert.False(source.HandlePressedAction(InputAction.MovementForward));
Assert.True(source.AutoRunActive);
source.ResetSession();
Assert.False(source.AutoRunActive);
}
[Fact]
public void BindingIsIdempotentOnlyForTheSameDispatcher()
{
var source = new DispatcherMovementInputSource();
var (first, _, _) = CreateDispatcher();
var (second, _, _) = CreateDispatcher();
source.Bind(first);
source.Bind(first);
Assert.Throws<InvalidOperationException>(() => source.Bind(second));
}
private static (InputDispatcher Dispatcher, FakeKeyboard Keyboard, FakeMouse Mouse)
CreateDispatcher()
{
var keyboard = new FakeKeyboard();
var mouse = new FakeMouse();
return (new InputDispatcher(keyboard, mouse, new KeyBindings()), keyboard, mouse);
}
private sealed class FakeKeyboard : IKeyboardSource
{
#pragma warning disable CS0067
public event Action<Key, ModifierMask>? KeyDown;
public event Action<Key, ModifierMask>? KeyUp;
#pragma warning restore CS0067
public bool IsHeld(Key key) => false;
public ModifierMask CurrentModifiers => ModifierMask.None;
}
private sealed class FakeMouse : IMouseSource
{
#pragma warning disable CS0067
public event Action<MouseButton, ModifierMask>? MouseDown;
public event Action<MouseButton, ModifierMask>? MouseUp;
public event Action<float, float>? MouseMove;
public event Action<float>? Scroll;
#pragma warning restore CS0067
public bool WantCaptureKeyboard { get; set; }
public bool WantCaptureMouse { get; set; }
public bool IsHeld(MouseButton button) => false;
}
private sealed class FakeCapture : IInputCaptureSource
{
public bool WantCaptureMouse { get; set; }
public bool WantCaptureKeyboard { get; set; }
public bool DevToolsWantCaptureKeyboard { get; set; }
}
}