using System; using UnitTestSharp; namespace Clave.UnitTests { public class KeyCaptureTests : TestFixture { public static string Described(KeyCapture capture) { var names = new string[capture.Deepest.Count]; for (int i = 0; i < names.Length; ++i) { names[i] = capture.Deepest[i].ToString(); } return string.Join(" ", names); } public static KeyCapture Settled(KeySpace space, params KeyboardSnapshot[] snapshots) { var capture = new KeyCapture(space); foreach (KeyboardSnapshot snapshot in snapshots) { capture.Feed(snapshot); } return capture; } public class FeedTests : TestFixture { public void NoKeys_DoesNotSettle() { var capture = new KeyCapture(KeySpace.Physical); CheckFalse(capture.Feed(default)); CheckFalse(capture.Settled); CheckEqual("", Described(capture)); } public void KeyStillDown_DoesNotSettle() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Physical); CheckFalse(capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false))); } public void LastKeyUp_Settles() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Physical); capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false)); Check(capture.Feed(tracker.KeyUp(KeyCode.Z))); Check(capture.Settled); CheckEqual("Z", Described(capture)); } public void TapWithinOneSnapshot_Settles() { var tap = new KeyboardSnapshot( new KeySpaceSnapshot(default, new KeyState(KeyCode.Z), new KeyState(KeyCode.Z)), default); var capture = new KeyCapture(KeySpace.Physical); Check(capture.Feed(tap)); CheckEqual("Z", Described(capture)); } public void OtherKeyStillDown_DoesNotSettle() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Physical); capture.Feed(tracker.KeyDown(KeyCode.ControlLeft, KeyCode.ControlLeft, isRepeat: false)); capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false)); CheckFalse(capture.Feed(tracker.KeyUp(KeyCode.Z))); } public void ReleasingTheModifierFirst_KeepsTheDeepestKeys() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Physical); capture.Feed(tracker.KeyDown(KeyCode.ControlLeft, KeyCode.ControlLeft, isRepeat: false)); capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false)); capture.Feed(tracker.KeyUp(KeyCode.ControlLeft)); capture.Feed(tracker.KeyUp(KeyCode.Z)); Check(capture.Settled); CheckEqual("ControlLeft Z", Described(capture)); } public void Deepest_ListsKeysInTheOrderTheyWentDown() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Physical); capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false)); capture.Feed(tracker.KeyDown(KeyCode.ControlLeft, KeyCode.ControlLeft, isRepeat: false)); CheckEqual("Z ControlLeft", Described(capture)); } public void KeysPressedInOneSnapshot_AreInKeyCodeOrder() { var both = new KeyboardSnapshot( new KeySpaceSnapshot( new KeyState(KeyCode.Z, KeyCode.A), new KeyState(KeyCode.Z, KeyCode.A), default), default); var capture = new KeyCapture(KeySpace.Physical); capture.Feed(both); CheckEqual("A Z", Described(capture)); } public void AnotherSetOfTheSameSize_ReplacesTheEarlierOne() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Physical); capture.Feed(tracker.KeyDown(KeyCode.ControlLeft, KeyCode.ControlLeft, isRepeat: false)); capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false)); capture.Feed(tracker.KeyUp(KeyCode.Z)); capture.Feed(tracker.KeyDown(KeyCode.X, KeyCode.X, isRepeat: false)); capture.Feed(tracker.KeyUp(KeyCode.X)); capture.Feed(tracker.KeyUp(KeyCode.ControlLeft)); CheckEqual("ControlLeft X", Described(capture)); } public void ASmallerSetAfterwards_DoesNotReplaceTheDeepestOne() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Physical); capture.Feed(tracker.KeyDown(KeyCode.ControlLeft, KeyCode.ControlLeft, isRepeat: false)); capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false)); capture.Feed(tracker.KeyUp(KeyCode.ControlLeft)); capture.Feed(tracker.KeyUp(KeyCode.Z)); CheckEqual("ControlLeft Z", Described(capture)); } public void AutoRepeat_AddsNothing() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Physical); capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false)); capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: true)); capture.Feed(tracker.KeyUp(KeyCode.Z)); CheckEqual("Z", Described(capture)); } public void KeyHeldAtTheStart_IsLeftOut() { var tracker = new KeyTracker(); tracker.KeyDown(KeyCode.MainEnter, KeyCode.MainEnter, isRepeat: false); var capture = new KeyCapture(KeySpace.Physical, new KeyState(KeyCode.MainEnter)); capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false)); capture.Feed(tracker.KeyUp(KeyCode.Z)); Check(capture.Settled); CheckEqual("Z", Described(capture)); } public void KeyHeldAtTheStart_DoesNotSettleOnItsOwnRelease() { var tracker = new KeyTracker(); tracker.KeyDown(KeyCode.MainEnter, KeyCode.MainEnter, isRepeat: false); var capture = new KeyCapture(KeySpace.Physical, new KeyState(KeyCode.MainEnter)); CheckFalse(capture.Feed(tracker.KeyUp(KeyCode.MainEnter))); } public void KeyHeldAtTheStart_CountsWhenPressedAgain() { var tracker = new KeyTracker(); tracker.KeyDown(KeyCode.MainEnter, KeyCode.MainEnter, isRepeat: false); var capture = new KeyCapture(KeySpace.Physical, new KeyState(KeyCode.MainEnter)); capture.Feed(tracker.KeyUp(KeyCode.MainEnter)); capture.Feed(tracker.KeyDown(KeyCode.MainEnter, KeyCode.MainEnter, isRepeat: false)); capture.Feed(tracker.KeyUp(KeyCode.MainEnter)); CheckEqual("MainEnter", Described(capture)); } public void AfterSettling_LaterSnapshotsChangeNothing() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Physical); capture.Feed(tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false)); capture.Feed(tracker.KeyUp(KeyCode.Z)); Check(capture.Feed(tracker.KeyDown(KeyCode.X, KeyCode.X, isRepeat: false))); CheckEqual("Z", Described(capture)); } public void PhysicalSpace_FollowsKeyPositions() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Physical); capture.Feed(tracker.KeyDown(KeyCode.W, KeyCode.Z, isRepeat: false)); capture.Feed(tracker.KeyUp(KeyCode.W)); CheckEqual("W", Described(capture)); } public void LayoutSpace_FollowsWhatTheLayoutPrints() { var tracker = new KeyTracker(); var capture = new KeyCapture(KeySpace.Layout); capture.Feed(tracker.KeyDown(KeyCode.W, KeyCode.Z, isRepeat: false)); capture.Feed(tracker.KeyUp(KeyCode.W)); CheckEqual("Z", Described(capture)); } } public class ToChordTests : TestFixture { public static KeyCapture ControlThenZ(KeySpace space) { var tracker = new KeyTracker(); return Settled(space, tracker.KeyDown(KeyCode.ControlLeft, KeyCode.ControlLeft, isRepeat: false), tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false), tracker.KeyUp(KeyCode.ControlLeft), tracker.KeyUp(KeyCode.Z)); } public void BeforeSettling_Throws() { CheckThrow(typeof(InvalidOperationException)); new KeyCapture(KeySpace.Physical).ToChord(KeyStateKind.Pressed); } public void Pressed_FiresOnTheTriggerWithTheOthersHeld() { Chord expected = Chord.Press(KeyCode.Z).WithAllHeld(new KeyState(KeyCode.ControlLeft)); CheckEqual(expected.Formula, ControlThenZ(KeySpace.Physical).ToChord(KeyStateKind.Pressed).Formula); } public void Held_HoldsTheTrigger() { Chord expected = Chord.Hold(KeyCode.Z).WithAllHeld(new KeyState(KeyCode.ControlLeft)); CheckEqual(expected.Formula, ControlThenZ(KeySpace.Physical).ToChord(KeyStateKind.Held).Formula); } public void Released_FiresWhenTheTriggerComesUp() { Chord expected = Chord.Release(KeyCode.Z).WithAllHeld(new KeyState(KeyCode.ControlLeft)); CheckEqual(expected.Formula, ControlThenZ(KeySpace.Physical).ToChord(KeyStateKind.Released).Formula); } public void Repeated_FiresWhenTheTriggerRepeats() { Chord expected = Chord.Repeat(KeyCode.Z).WithAllHeld(new KeyState(KeyCode.ControlLeft)); CheckEqual(expected.Formula, ControlThenZ(KeySpace.Physical).ToChord(KeyStateKind.Repeated).Formula); } public void UnknownKind_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); ControlThenZ(KeySpace.Physical).ToChord((KeyStateKind)99); } public void SingleKey_HasNoHeldKeys() { var tracker = new KeyTracker(); KeyCapture capture = Settled(KeySpace.Physical, tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false), tracker.KeyUp(KeyCode.Z)); CheckEqual(Chord.Press(KeyCode.Z).Formula, capture.ToChord(KeyStateKind.Pressed).Formula); } public void ModifierPressedAfterTheKey_StillTriggersOnTheKey() { var tracker = new KeyTracker(); KeyCapture capture = Settled(KeySpace.Physical, tracker.KeyDown(KeyCode.Z, KeyCode.Z, isRepeat: false), tracker.KeyDown(KeyCode.ControlLeft, KeyCode.ControlLeft, isRepeat: false), tracker.KeyUp(KeyCode.Z), tracker.KeyUp(KeyCode.ControlLeft)); Chord expected = Chord.Press(KeyCode.Z).WithAllHeld(new KeyState(KeyCode.ControlLeft)); CheckEqual(expected.Formula, capture.ToChord(KeyStateKind.Pressed).Formula); } public void OnlyModifiers_TriggerOnTheLastOne() { var tracker = new KeyTracker(); KeyCapture capture = Settled(KeySpace.Physical, tracker.KeyDown(KeyCode.ControlLeft, KeyCode.ControlLeft, isRepeat: false), tracker.KeyDown(KeyCode.ShiftLeft, KeyCode.ShiftLeft, isRepeat: false), tracker.KeyUp(KeyCode.ShiftLeft), tracker.KeyUp(KeyCode.ControlLeft)); Chord expected = Chord.Press(KeyCode.ShiftLeft).WithAllHeld(new KeyState(KeyCode.ControlLeft)); CheckEqual(expected.Formula, capture.ToChord(KeyStateKind.Pressed).Formula); } public void TwoPlainKeys_TriggerOnTheLaterOne() { var tracker = new KeyTracker(); KeyCapture capture = Settled(KeySpace.Physical, tracker.KeyDown(KeyCode.A, KeyCode.A, isRepeat: false), tracker.KeyDown(KeyCode.B, KeyCode.B, isRepeat: false), tracker.KeyUp(KeyCode.A), tracker.KeyUp(KeyCode.B)); Chord expected = Chord.Press(KeyCode.B).WithAllHeld(new KeyState(KeyCode.A)); CheckEqual(expected.Formula, capture.ToChord(KeyStateKind.Pressed).Formula); } public void LayoutSpace_BuildsALayoutChord() { Chord expected = Chord.Press(KeyCode.Z, KeySpace.Layout) .WithAllHeld(new KeyState(KeyCode.ControlLeft), KeySpace.Layout); CheckEqual(expected.Formula, ControlThenZ(KeySpace.Layout).ToChord(KeyStateKind.Pressed).Formula); } } } }