using System; using System.Collections.Generic; using UnitTestSharp; namespace Clave.UnitTests { public class ChordArbiterTests : TestFixture { public static readonly Chord Delete = Chord.Press(KeyCode.Delete); public static readonly Chord ShiftDelete = Delete & Chord.HoldAny(KeyState.Shift); // A repeating key is always held, so this matches every snapshot a keyboard can produce. public static readonly Chord MatchesEverythingOnA = ~Chord.Repeat(KeyCode.A) | Chord.Hold(KeyCode.A); public static readonly Chord MatchesEverythingOnNoKey = Chord.Hold(KeyCode.A) | ~Chord.Hold(KeyCode.A); public static readonly Chord LayoutUndo = Chord.Press(KeyCode.Z, KeySpace.Layout) .WithAnyHeld(KeyState.Control, KeySpace.Layout); // One key going down while the keys in `heldBefore` already are, as a host reports it. public static KeyboardSnapshot KeyEvent(KeyCode physicalKey, KeyCode layoutKey, params KeyCode[] heldBefore) { var tracker = new KeyTracker(); foreach (KeyCode held in heldBefore) { tracker.KeyDown(held, held, isRepeat: false); } return tracker.KeyDown(physicalKey, layoutKey, isRepeat: false); } public static KeyboardSnapshot Keyboard(KeyState held, KeyState pressed, KeyState released, KeyState repeated = default) { return new KeyboardSnapshot(new KeySpaceSnapshot(held, pressed, released, repeated), default); } public static KeyboardSnapshot LayoutKeyboard(KeyState held, KeyState pressed, KeyState released, KeyState repeated = default) { return new KeyboardSnapshot(default, new KeySpaceSnapshot(held, pressed, released, repeated)); } public static KeyboardSnapshot Holding(params KeyCode[] keys) { var held = default(KeyState); foreach (KeyCode key in keys) { held |= new KeyState(key); } return Keyboard(held, default, default); } public static KeyboardSnapshot Pressing(KeyCode key, KeyState alsoHeld = default) { return Keyboard(alsoHeld | new KeyState(key), new KeyState(key), default); } public class ShouldFireAnyTests : TestFixture { public static KeyboardSnapshot PressingShiftDelete() { return Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)); } public void OneChordOfTheSetFiring_ShouldFire() { Chord backspace = Chord.Press(KeyCode.Backspace); var arbiter = new ChordArbiter(); ChordSet set = ChordSet.Of(Delete, backspace); ChordMount mount = arbiter.Mount(set); Check(arbiter.ShouldFireAny(set, mount, Pressing(KeyCode.Backspace))); } public void NoChordOfTheSetMatching_ShouldNotFire() { var arbiter = new ChordArbiter(); ChordSet set = ChordSet.Of(Delete); ChordMount mount = arbiter.Mount(set); CheckFalse(arbiter.ShouldFireAny(set, mount, Pressing(KeyCode.Backspace))); } public void EveryMatchingChordHiddenByAMoreSpecificOne_ShouldNotFire() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); CheckFalse(arbiter.ShouldFireAny(ChordSet.Of(Delete), mount, PressingShiftDelete())); } public void OneChordHiddenAndAnotherFiring_ShouldFire() { var arbiter = new ChordArbiter(); ChordSet set = ChordSet.Of(Delete, ShiftDelete); ChordMount mount = arbiter.Mount(set); Check(arbiter.ShouldFireAny(set, mount, PressingShiftDelete())); } public void AnEmptySet_ShouldNotFire() { var arbiter = new ChordArbiter(); CheckFalse(arbiter.ShouldFireAny(ChordSet.Empty, arbiter.Mount(), Pressing(KeyCode.Delete))); } public void OnAMountThatOutranksTheOther_OnlyTheOutrankingMountFires() { var arbiter = new ChordArbiter(); ChordSet set = ChordSet.Of(Delete); ChordMount low = arbiter.Mount(set, priority: 1); ChordMount high = arbiter.Mount(set, priority: 2); CheckFalse(arbiter.ShouldFireAny(set, low, Pressing(KeyCode.Delete))); Check(arbiter.ShouldFireAny(set, high, Pressing(KeyCode.Delete))); } public void ASetWithAChordThatIsntOnTheMount_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); CheckThrow(typeof(ArgumentException)); arbiter.ShouldFireAny(ChordSet.Of(Delete), mount, Pressing(KeyCode.Delete)); } public void NullSet_Throws() { var arbiter = new ChordArbiter(); CheckThrow(typeof(ArgumentNullException)); arbiter.ShouldFireAny(null, arbiter.Mount(), Pressing(KeyCode.Delete)); } } public class MountTests : TestFixture { public static KeyboardSnapshot PressingShiftDelete() { return Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)); } public void Nothing_StartsAnEmptyMount() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); CheckEqual(0, arbiter.CountOn(mount)); } public void AChord_PutsItInPlayOnAMountOfItsOwn() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete, priority: 3); Check(arbiter.Contains(Delete, mount)); CheckEqual(1, arbiter.CountOn(mount)); CheckEqual(3, arbiter.PriorityOf(Delete, mount)); } public void ANullChord_Throws() { CheckThrow(typeof(ArgumentNullException)); new ChordArbiter().Mount((Chord)null); } public void ABuilder_PutsEveryChordInPlayAtThePriorityWithItsEnabledState() { var builder = new ChordSetBuilder(); builder.Add(Delete); builder.Add(ShiftDelete); builder.SetEnabled(ShiftDelete, false); var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(builder, priority: 3); CheckEqual(2, arbiter.CountOn(mount)); CheckEqual(3, arbiter.PriorityOf(Delete, mount)); CheckEqual(3, arbiter.PriorityOf(ShiftDelete, mount)); Check(arbiter.IsEnabled(Delete, mount)); CheckFalse(arbiter.IsEnabled(ShiftDelete, mount)); } public void ABuilder_KeepsTheRankingsAmongItsChords() { var builder = new ChordSetBuilder(); builder.Add(Delete); builder.Add(ShiftDelete); var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(builder); CheckFalse(arbiter.ShouldFire(Delete, mount, PressingShiftDelete())); Check(arbiter.ShouldFire(ShiftDelete, mount, PressingShiftDelete())); } public void ABuilder_IsNotReachedByLaterChangesToIt() { var builder = new ChordSetBuilder(); builder.Add(Delete); var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(builder); builder.Add(ShiftDelete); CheckFalse(arbiter.Contains(ShiftDelete, mount)); } public void ANullBuilder_Throws() { CheckThrow(typeof(ArgumentNullException)); new ChordArbiter().Mount((ChordSetBuilder)null); } public void PutsEveryChordOfTheSetInPlayOnTheMount() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); Check(arbiter.Contains(Delete, mount)); Check(arbiter.Contains(ShiftDelete, mount)); } public void TheSameSetOnTwoMounts_IsInPlayOnBoth() { var arbiter = new ChordArbiter(); ChordSet set = ChordSet.Of(Delete); ChordMount first = arbiter.Mount(set); ChordMount second = arbiter.Mount(set); Check(arbiter.Contains(Delete, first)); Check(arbiter.Contains(Delete, second)); } public void GivesEveryChordThePriorityMountedAt() { var builder = new ChordSetBuilder(); builder.Add(Delete, priority: 1); builder.Add(ShiftDelete, priority: 5); var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(builder.Build(), priority: 2); CheckEqual(2, arbiter.PriorityOf(Delete, mount)); CheckEqual(2, arbiter.PriorityOf(ShiftDelete, mount)); } public void ChordsOfTheSet_RankAgainstEachOther() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); CheckFalse(arbiter.ShouldFire(Delete, mount, PressingShiftDelete())); Check(arbiter.ShouldFire(ShiftDelete, mount, PressingShiftDelete())); } public void ChordsOfTheSet_RankAgainstTheChordsOfAnotherMount() { var arbiter = new ChordArbiter(); ChordMount weaker = arbiter.Mount(Delete); ChordMount stronger = arbiter.Mount(ShiftDelete); CheckFalse(arbiter.ShouldFire(Delete, weaker, PressingShiftDelete())); Check(arbiter.ShouldFire(ShiftDelete, stronger, PressingShiftDelete())); } public void ADisabledChordOfTheSet_StaysDisabledOnTheMount() { var builder = new ChordSetBuilder(); Chord disabled = builder.Add(Delete); builder.Add(ShiftDelete); builder.SetEnabled(disabled, false); var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(builder.Build()); CheckFalse(arbiter.IsEnabled(disabled, mount)); CheckFalse(arbiter.ShouldFire(disabled, mount, Pressing(KeyCode.Delete))); } public void MountsOfEqualPriority_BothFire() { var arbiter = new ChordArbiter(); ChordMount first = arbiter.Mount(ChordSet.Of(Delete), priority: 1); ChordMount second = arbiter.Mount(ChordSet.Of(Delete), priority: 1); Check(arbiter.ShouldFire(Delete, first, Pressing(KeyCode.Delete))); Check(arbiter.ShouldFire(Delete, second, Pressing(KeyCode.Delete))); } public void TheMountOfHigherPriority_HidesTheLowerOne() { var arbiter = new ChordArbiter(); ChordMount low = arbiter.Mount(ChordSet.Of(Delete), priority: 1); ChordMount high = arbiter.Mount(ChordSet.Of(Delete), priority: 2); Check(arbiter.ShouldFire(Delete, high, Pressing(KeyCode.Delete))); CheckFalse(arbiter.ShouldFire(Delete, low, Pressing(KeyCode.Delete))); } public void TheOrderMountsAreMade_DoesNotDecideWhoWins() { var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(Delete), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(Delete), priority: 1); Check(arbiter.ShouldFire(Delete, high, Pressing(KeyCode.Delete))); CheckFalse(arbiter.ShouldFire(Delete, low, Pressing(KeyCode.Delete))); } public void AHeldChord_IsHiddenByTheMountOfHigherPriority() { Chord held = Chord.Hold(KeyCode.A); var arbiter = new ChordArbiter(); ChordMount low = arbiter.Mount(ChordSet.Of(held), priority: 1); ChordMount high = arbiter.Mount(ChordSet.Of(held), priority: 2); Check(arbiter.ShouldFire(held, high, Holding(KeyCode.A))); CheckFalse(arbiter.ShouldFire(held, low, Holding(KeyCode.A))); } public void ASpecificChordOfLowerPriority_StillHidesALessSpecificOneOfHigherPriority() { var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(Delete), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(ShiftDelete), priority: 1); CheckFalse(arbiter.ShouldFire(Delete, high, PressingShiftDelete())); Check(arbiter.ShouldFire(ShiftDelete, low, PressingShiftDelete())); } public void AnyOfFewerKeys_HidesAnyOfMoreKeysOfHigherPriority() { Chord few = Chord.PressAny(new KeyState(KeyCode.A, KeyCode.B)); Chord many = Chord.PressAny(new KeyState(KeyCode.A, KeyCode.B, KeyCode.C)); var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(many), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(few), priority: 1); CheckFalse(arbiter.ShouldFire(many, high, Pressing(KeyCode.A))); Check(arbiter.ShouldFire(few, low, Pressing(KeyCode.A))); } public void AnyOfKeysTheOtherDoesNotRead_DoesNotHideIt() { Chord first = Chord.PressAny(new KeyState(KeyCode.A, KeyCode.B)); Chord second = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D)); var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(first), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(second), priority: 1); Check(arbiter.ShouldFire(second, low, Pressing(KeyCode.C))); } public void AnyOfKeysThatOverlapWithoutNesting_BothFireOnTheSharedKey() { Chord first = Chord.PressAny(new KeyState(KeyCode.A, KeyCode.B)); Chord second = Chord.PressAny(new KeyState(KeyCode.B, KeyCode.C)); var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(first), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(second), priority: 1); Check(arbiter.ShouldFire(first, high, Pressing(KeyCode.B))); Check(arbiter.ShouldFire(second, low, Pressing(KeyCode.B))); } public void TwoSeparatelyBuiltChordsOfTheSameKeys_AreEquivalent() { Chord first = Chord.PressAny(new KeyState(KeyCode.A, KeyCode.B)); Chord second = Chord.PressAny(new KeyState(KeyCode.B, KeyCode.A)); var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(first), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(second), priority: 1); Check(arbiter.ShouldFire(first, high, Pressing(KeyCode.A))); CheckFalse(arbiter.ShouldFire(second, low, Pressing(KeyCode.A))); } public void PinNothingEdgeChordsInDifferentSpacesOnDifferentKeys_AreRankedByPriority() { Chord layoutAny = Chord.PressAny(new KeyState(KeyCode.A, KeyCode.B), KeySpace.Layout); Chord physicalAny = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D)); var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(layoutAny), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(physicalAny), priority: 1); var keyboard = new KeyboardSnapshot( new KeySpaceSnapshot(new KeyState(KeyCode.C), new KeyState(KeyCode.C), default, default), new KeySpaceSnapshot(new KeyState(KeyCode.A), new KeyState(KeyCode.A), default, default)); Check(arbiter.ShouldFire(layoutAny, high, keyboard)); CheckFalse(arbiter.ShouldFire(physicalAny, low, keyboard)); } // Read as physical keys, Ctrl and Alt in both spaces are the same keys and the Shift branch adds nothing. // The fold of this chord reads only Ctrl and Alt. Its repeating form still forbids a press of Shift. public static Chord RepeatsWithAShiftBranchThatFoldsAway() { KeyFormula ctrlOrAlt = KeyFormulaTests.Pressed(KeyCode.ControlLeft) | KeyFormulaTests.Repeated(KeyCode.ControlLeft) | KeyFormulaTests.Pressed(KeyCode.AltLeft) | KeyFormulaTests.Repeated(KeyCode.AltLeft); KeyFormula layoutCtrlOrAlt = KeyFormulaTests.Pressed(KeyCode.ControlLeft, KeySpace.Layout) | KeyFormulaTests.Repeated(KeyCode.ControlLeft, KeySpace.Layout) | KeyFormulaTests.Pressed(KeyCode.AltLeft, KeySpace.Layout) | KeyFormulaTests.Repeated(KeyCode.AltLeft, KeySpace.Layout); KeyFormula layoutShift = KeyFormulaTests.Pressed(KeyCode.ShiftLeft, KeySpace.Layout); return Chord.FromFormula(ctrlOrAlt & (layoutShift | (~layoutShift & layoutCtrlOrAlt))); } public static KeyboardSnapshot ControlHeldInBothSpaces() { var held = new KeySpaceSnapshot(new KeyState(KeyCode.ControlLeft), default, default, default); return new KeyboardSnapshot(held, held); } public void ARepeatingChordWhoseFoldDropsAKey_StillHidesAHeldChordOnThatKey_AddedAfterIt() { Chord repeats = RepeatsWithAShiftBranchThatFoldsAway(); Chord noPressOfShift = ~Chord.Press(KeyCode.ShiftLeft); var arbiter = new ChordArbiter(); arbiter.Mount(ChordSet.Of(repeats)); ChordMount held = arbiter.Mount(ChordSet.Of(noPressOfShift)); CheckFalse(arbiter.ShouldFire(noPressOfShift, held, ControlHeldInBothSpaces())); } public void ARepeatingChordWhoseFoldDropsAKey_StillHidesAHeldChordOnThatKey_AddedBeforeIt() { Chord repeats = RepeatsWithAShiftBranchThatFoldsAway(); Chord noPressOfShift = ~Chord.Press(KeyCode.ShiftLeft); var arbiter = new ChordArbiter(); ChordMount held = arbiter.Mount(ChordSet.Of(noPressOfShift)); arbiter.Mount(ChordSet.Of(repeats)); CheckFalse(arbiter.ShouldFire(noPressOfShift, held, ControlHeldInBothSpaces())); } public void ARemovedChordsPlace_IsTakenByTheNextChordWithoutKeepingItsKeys() { Chord removed = Chord.PressAny(new KeyState(KeyCode.A, KeyCode.B)); Chord wide = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D, KeyCode.E)); Chord narrow = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D)); var arbiter = new ChordArbiter(); ChordMount first = arbiter.Mount(ChordSet.Of(removed)); arbiter.Unmount(first); ChordMount high = arbiter.Mount(ChordSet.Of(wide), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(narrow), priority: 1); CheckFalse(arbiter.ShouldFire(wide, high, Pressing(KeyCode.C))); Check(arbiter.ShouldFire(narrow, low, Pressing(KeyCode.C))); } public void ADisabledChord_NoLongerHidesTheSameChordOnAnotherMount() { var arbiter = new ChordArbiter(); ChordMount low = arbiter.Mount(ChordSet.Of(Delete), priority: 1); ChordMount high = arbiter.Mount(ChordSet.Of(Delete), priority: 2); arbiter.SetEnabled(Delete, high, false); Check(arbiter.ShouldFire(Delete, low, Pressing(KeyCode.Delete))); CheckFalse(arbiter.ShouldFire(Delete, high, Pressing(KeyCode.Delete))); } public void SetEnabled_ChangesOnlyThatMount() { var arbiter = new ChordArbiter(); ChordMount first = arbiter.Mount(ChordSet.Of(Delete)); ChordMount second = arbiter.Mount(ChordSet.Of(Delete)); arbiter.SetEnabled(Delete, first, false); CheckFalse(arbiter.IsEnabled(Delete, first)); Check(arbiter.IsEnabled(Delete, second)); } public void AChordTheMountDoesNotHave_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete)); CheckThrow(typeof(ArgumentException)); arbiter.ShouldFire(ShiftDelete, mount, PressingShiftDelete()); } public void AMountOfAnotherArbiter_Throws() { ChordMount elsewhere = new ChordArbiter().Mount(ChordSet.Of(Delete)); var arbiter = new ChordArbiter(); arbiter.Mount(ChordSet.Of(Delete)); CheckThrow(typeof(ArgumentException)); arbiter.ShouldFire(Delete, elsewhere, Pressing(KeyCode.Delete)); } public void ANullMount_Throws() { var arbiter = new ChordArbiter(); arbiter.Mount(ChordSet.Of(Delete)); CheckThrow(typeof(ArgumentNullException)); arbiter.ShouldFire(Delete, null, Pressing(KeyCode.Delete)); } public void ANullSet_Throws() { CheckThrow(typeof(ArgumentNullException)); new ChordArbiter().Mount((ChordSet)null); } public void AnEmptySet_PutsNothingInPlay() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Empty); CheckNotNull(mount); arbiter.Unmount(mount); } } public class UnmountTests : TestFixture { public void TakesEveryChordOfTheMountOut() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); arbiter.Unmount(mount); CheckEqual(0, arbiter.Count); } public void LeavesTheOtherMountsAndLiftsWhatTheOneHid() { var arbiter = new ChordArbiter(); ChordMount low = arbiter.Mount(ChordSet.Of(Delete), priority: 1); ChordMount high = arbiter.Mount(ChordSet.Of(Delete), priority: 2); CheckFalse(arbiter.ShouldFire(Delete, low, Pressing(KeyCode.Delete))); arbiter.Unmount(high); Check(arbiter.ShouldFire(Delete, low, Pressing(KeyCode.Delete))); } public void LeavesTheChordsOfOtherMounts() { var arbiter = new ChordArbiter(); ChordMount kept = arbiter.Mount(Delete); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete)); arbiter.Unmount(mount); Check(arbiter.Contains(Delete, kept)); } public void AMountThatWasUnmounted_CanBeMountedAgainAsANewOne() { var arbiter = new ChordArbiter(); ChordSet set = ChordSet.Of(Delete); arbiter.Unmount(arbiter.Mount(set)); ChordMount again = arbiter.Mount(set); Check(arbiter.ShouldFire(Delete, again, Pressing(KeyCode.Delete))); } public void TheSameMountTwice_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete)); arbiter.Unmount(mount); CheckThrow(typeof(ArgumentException)); arbiter.Unmount(mount); } public void AMountOfAnotherArbiter_Throws() { ChordMount elsewhere = new ChordArbiter().Mount(ChordSet.Of(Delete)); CheckThrow(typeof(ArgumentException)); new ChordArbiter().Unmount(elsewhere); } public void Null_Throws() { CheckThrow(typeof(ArgumentNullException)); new ChordArbiter().Unmount(null); } } public class AddTests : TestFixture { public void PutsTheChordOnTheMountAlone() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); ChordMount other = arbiter.Mount(); arbiter.Add(Delete, mount); Check(arbiter.Contains(Delete, mount)); CheckFalse(arbiter.Contains(Delete, other)); } public void TheSameChordOnTwoMounts_IsAllowed() { var arbiter = new ChordArbiter(); ChordMount first = arbiter.Mount(); ChordMount second = arbiter.Mount(); arbiter.Add(Delete, first); arbiter.Add(Delete, second); Check(arbiter.Contains(Delete, second)); } public void AnUnmountedMount_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.Unmount(mount); CheckThrow(typeof(ArgumentException)); arbiter.Add(Delete, mount); } public void ANullMount_Throws() { CheckThrow(typeof(ArgumentNullException)); new ChordArbiter().Add(Delete, null); } } public class AddAllTests : TestFixture { public void ASetAndASourceMount_CarryTheirRankings() { var source = new ChordArbiter(); ChordMount from = source.Mount(ChordSet.Of(Delete, ShiftDelete)); var arbiter = new ChordArbiter(); ChordMount into = arbiter.Mount(); arbiter.AddAll(source, from, into, priority: 4); CheckEqual(4, arbiter.PriorityOf(Delete, into)); CheckFalse(arbiter.ShouldFire(Delete, into, ChordArbiterTests.Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)))); } public void ASourceWithOtherMounts_CopiesOnlyTheNamedMount() { var source = new ChordArbiter(); ChordMount from = source.Mount(Delete); source.Mount(ShiftDelete); var arbiter = new ChordArbiter(); ChordMount into = arbiter.Mount(); arbiter.AddAll(source, from, into); Check(arbiter.Contains(Delete, into)); CheckFalse(arbiter.Contains(ShiftDelete, into)); } public void AChordAlreadyOnTheMount_ThrowsAndAddsNone() { var source = new ChordArbiter(); ChordMount from = source.Mount(ChordSet.Of(Delete, ShiftDelete)); var arbiter = new ChordArbiter(); ChordMount into = arbiter.Mount(ShiftDelete); CheckThrow(typeof(ArgumentException)); arbiter.AddAll(source, from, into); } public void ANullSource_Throws() { var arbiter = new ChordArbiter(); CheckThrow(typeof(ArgumentNullException)); arbiter.AddAll((ChordArbiter)null, arbiter.Mount(), arbiter.Mount()); } public void ABuilder_PutsItsChordsOnTheMountAtThePriorityWithTheirEnabledStates() { var builder = new ChordSetBuilder(); builder.Add(Delete); builder.Add(ShiftDelete); builder.SetEnabled(ShiftDelete, false); var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.AddAll(builder, mount, priority: 4); CheckEqual(4, arbiter.PriorityOf(Delete, mount)); CheckEqual(4, arbiter.PriorityOf(ShiftDelete, mount)); CheckFalse(arbiter.IsEnabled(ShiftDelete, mount)); } public void ABuilder_CompetesWithTheChordsAlreadyOnTheMount() { var builder = new ChordSetBuilder(); builder.Add(ShiftDelete); var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.AddAll(builder, mount); CheckFalse(arbiter.ShouldFire(Delete, mount, ChordArbiterTests.Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)))); } public void ABuilderWithAChordAlreadyOnTheMount_Throws() { var builder = new ChordSetBuilder(); builder.Add(Delete); builder.Add(ShiftDelete); var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ShiftDelete); CheckThrow(typeof(ArgumentException)); arbiter.AddAll(builder, mount); } public void ANullBuilder_Throws() { var arbiter = new ChordArbiter(); CheckThrow(typeof(ArgumentNullException)); arbiter.AddAll((ChordSetBuilder)null, arbiter.Mount()); } } public class RemoveTests : TestFixture { public void TakesTheChordOffThatMountAlone() { var arbiter = new ChordArbiter(); ChordMount first = arbiter.Mount(Delete); ChordMount second = arbiter.Mount(Delete); arbiter.Remove(Delete, first); CheckFalse(arbiter.Contains(Delete, first)); Check(arbiter.Contains(Delete, second)); } public void AChordNotOnTheMount_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); CheckThrow(typeof(ArgumentException)); arbiter.Remove(Delete, mount); } public void TheChordThatHidesAnother_LetsItFireOnceRemoved() { Chord wide = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D, KeyCode.E)); Chord narrow = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D)); var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(wide), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(narrow), priority: 1); CheckFalse(arbiter.ShouldFire(wide, high, Pressing(KeyCode.C))); arbiter.Remove(narrow, low); Check(arbiter.ShouldFire(wide, high, Pressing(KeyCode.C))); } public void TheChordThatIsHidden_IsHiddenAgainWhenAddedBack() { Chord wide = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D, KeyCode.E)); Chord narrow = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D)); var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(wide), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(narrow), priority: 1); arbiter.Remove(wide, high); arbiter.Add(wide, high); CheckFalse(arbiter.ShouldFire(wide, high, Pressing(KeyCode.C))); Check(arbiter.ShouldFire(narrow, low, Pressing(KeyCode.C))); } public void TheChordThatIsHidden_LeavesNothingBehindOnTheOneThatHidIt() { Chord wide = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D, KeyCode.E)); Chord narrow = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D)); var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(wide), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(narrow), priority: 1); arbiter.Remove(wide, high); arbiter.Remove(narrow, low); CheckEqual(0, arbiter.CountOn(high) + arbiter.CountOn(low)); } } public class RemoveAllTests : TestFixture { public void ASet_TakesItsChordsOffThatMountAlone() { var arbiter = new ChordArbiter(); ChordSet set = ChordSet.Of(Delete, ShiftDelete); ChordMount first = arbiter.Mount(set); ChordMount second = arbiter.Mount(set); arbiter.RemoveAll(set, first); CheckEqual(0, arbiter.CountOn(first)); CheckEqual(2, arbiter.CountOn(second)); } public void ABuilder_TakesItsChordsOffTheMount() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); var builder = new ChordSetBuilder(); builder.Add(Delete); arbiter.RemoveAll(builder, mount); Check(arbiter.Contains(ShiftDelete, mount)); CheckFalse(arbiter.Contains(Delete, mount)); } public void TheChordThatHidesSeveral_LetsEachFireOnceRemoved() { Chord wide = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D, KeyCode.E)); Chord narrow = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D)); Chord bystander = Chord.PressAny(new KeyState(KeyCode.C, KeyCode.D, KeyCode.F)); var arbiter = new ChordArbiter(); ChordMount high = arbiter.Mount(ChordSet.Of(wide, bystander), priority: 2); ChordMount low = arbiter.Mount(ChordSet.Of(narrow), priority: 1); CheckFalse(arbiter.ShouldFire(bystander, high, Pressing(KeyCode.C))); arbiter.RemoveAll(ChordSet.Of(narrow), low); Check(arbiter.ShouldFire(bystander, high, Pressing(KeyCode.C))); Check(arbiter.ShouldFire(wide, high, Pressing(KeyCode.C))); } public void AChordNotOnTheMount_ThrowsAndRemovesNone() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); CheckThrow(typeof(ArgumentException)); arbiter.RemoveAll(ChordSet.Of(Delete, ShiftDelete), mount); } } public class CountOnTests : TestFixture { public void CountsOnlyTheChordsOfThatMount() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); arbiter.Mount(Delete); CheckEqual(2, arbiter.CountOn(mount)); } public void AnUnmountedMount_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.Unmount(mount); CheckThrow(typeof(ArgumentException)); arbiter.CountOn(mount); } public void AChordTakenOffTheMount_IsNoLongerCounted() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); arbiter.Remove(Delete, mount); CheckEqual(1, arbiter.CountOn(mount)); } public void ChordsAddedFromAnotherArbitersMount_AreCountedOnTheirNewMount() { var source = new ChordArbiter(); ChordMount from = source.Mount(ChordSet.Of(Delete, ShiftDelete)); var arbiter = new ChordArbiter(); ChordMount into = arbiter.Mount(); arbiter.AddAll(source, from, into); CheckEqual(2, arbiter.CountOn(into)); } public void ChordsAddedFromAnotherArbitersMountThatHoldsMore_AreCountedOnTheirNewMount() { var source = new ChordArbiter(); ChordMount from = source.Mount(ChordSet.Of(Delete, ShiftDelete)); source.Mount(Chord.Press(KeyCode.A)); var arbiter = new ChordArbiter(); ChordMount into = arbiter.Mount(); arbiter.AddAll(source, from, into); CheckEqual(2, arbiter.CountOn(into)); } public void AClone_CountsTheChordsOfEachMount() { var arbiter = new ChordArbiter(); ChordMount two = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); ChordMount one = arbiter.Mount(Delete); ChordArbiter clone = arbiter.Clone(); CheckEqual(2, clone.CountOn(two)); CheckEqual(1, clone.CountOn(one)); } } public class ChordsOnTests : TestFixture { public void WalksOnlyTheChordsOfThatMount() { var arbiter = new ChordArbiter(); arbiter.Mount(Delete); ChordMount mount = arbiter.Mount(ShiftDelete); var walked = new List(); ChordArbiter.Enumerator chords = arbiter.ChordsOn(mount); while (chords.MoveNext()) { walked.Add(chords.Current); } CheckEqual(1, walked.Count); CheckEqual(ShiftDelete, walked[0]); } public void CanBeWalkedWithForeach() { var arbiter = new ChordArbiter(); arbiter.Mount(Delete); ChordMount mount = arbiter.Mount(ChordSet.Of(ShiftDelete, Delete)); var walked = new List(); foreach (Chord chord in arbiter.ChordsOn(mount)) { walked.Add(chord); } CheckEqual(2, walked.Count); Check(walked.Contains(Delete)); Check(walked.Contains(ShiftDelete)); } public void ChangingTheArbiterWhileWalking_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); ChordArbiter.Enumerator chords = arbiter.ChordsOn(mount); chords.MoveNext(); arbiter.Remove(Delete, mount); CheckThrow(typeof(InvalidOperationException)); chords.MoveNext(); } } public class CloneTests : TestFixture { public void YieldsTheMountsInTheOrderTheyWereMounted() { var arbiter = new ChordArbiter(); ChordMount first = arbiter.Mount(); ChordMount second = arbiter.Mount(); ChordMount third = arbiter.Mount(); arbiter.Unmount(first); ChordMount fourth = arbiter.Mount(); List walked = MountsTests.Walk(arbiter.Clone()); CheckEqual(3, walked.Count); CheckEqual(second, walked[0]); CheckEqual(third, walked[1]); CheckEqual(fourth, walked[2]); } public void CopiesEveryMountWithItsChordsAndRankings() { var arbiter = new ChordArbiter(); ChordMount weaker = arbiter.Mount(Delete); ChordMount stronger = arbiter.Mount(ShiftDelete); ChordArbiter clone = arbiter.Clone(); Check(clone.Contains(ShiftDelete, stronger)); CheckFalse(clone.ShouldFire(Delete, weaker, ChordArbiterTests.Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)))); } public void ChangingTheClone_DoesNotChangeTheArbiter() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.Clone().Unmount(mount); Check(arbiter.Contains(Delete, mount)); } } public class ClearTests : TestFixture { public void TakesEveryChordOffAndKeepsTheMount() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); arbiter.Clear(mount); CheckEqual(0, arbiter.CountOn(mount)); Check(arbiter.IsMounted(mount)); } public void TheMount_TakesNewChordsAfterward() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.Clear(mount); arbiter.Add(Delete, mount); Check(arbiter.ShouldFire(Delete, mount, Pressing(KeyCode.Delete))); } public void LeavesTheChordsOfOtherMounts() { var arbiter = new ChordArbiter(); ChordMount kept = arbiter.Mount(Delete); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete)); arbiter.Clear(mount); Check(arbiter.Contains(Delete, kept)); } public void LiftsWhatTheClearedChordsHid() { var arbiter = new ChordArbiter(); ChordMount weaker = arbiter.Mount(Delete); ChordMount stronger = arbiter.Mount(ShiftDelete); KeyboardSnapshot shiftDelete = Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)); CheckFalse(arbiter.ShouldFire(Delete, weaker, shiftDelete)); arbiter.Clear(stronger); Check(arbiter.ShouldFire(Delete, weaker, shiftDelete)); } public void AChordAddedAfterward_IgnoresTheClearedOnes() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ShiftDelete); arbiter.Clear(mount); arbiter.Add(Delete, mount); Check(arbiter.ShouldFire(Delete, mount, Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)))); } public void ADisabledMount_StaysDisabled() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.SetEnabled(mount, false); arbiter.Clear(mount); arbiter.Add(Delete, mount); CheckFalse(arbiter.ShouldFire(Delete, mount, Pressing(KeyCode.Delete))); } public void AnEmptyMount_StaysEmpty() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.Clear(mount); CheckEqual(0, arbiter.CountOn(mount)); } public void AnUnmountedMount_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.Unmount(mount); CheckThrow(typeof(ArgumentException)); arbiter.Clear(mount); } public void Null_Throws() { CheckThrow(typeof(ArgumentNullException)); new ChordArbiter().Clear(null); } } public class ContainsTests : TestFixture { public void AChordOnTheMount_IsTrue() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); CheckTrue(arbiter.Contains(Delete, mount)); } public void AChordNotOnTheMount_IsFalse() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); CheckFalse(arbiter.Contains(ShiftDelete, mount)); } public void AnUnmountedMount_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.Unmount(mount); CheckThrow(typeof(ArgumentException)); arbiter.Contains(Delete, mount); } public void AMountOfAnotherArbiter_Throws() { var arbiter = new ChordArbiter(); ChordMount foreign = new ChordArbiter().Mount(Delete); CheckThrow(typeof(ArgumentException)); arbiter.Contains(Delete, foreign); } } public class PriorityOfTests : TestFixture { public static ArgumentException Thrown(ChordArbiter arbiter, Chord chord, ChordMount mount) { try { arbiter.PriorityOf(chord, mount); } catch (ArgumentException exception) { return exception; } return null; } public void AChordNotInPlay_BlamesTheChord() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); CheckEqual("chord", Thrown(arbiter, ShiftDelete, mount).ParamName); } public void AnUnmountedMount_BlamesTheMount() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.Unmount(mount); CheckEqual("mount", Thrown(arbiter, Delete, mount).ParamName); } } public class IsMountedTests : TestFixture { public void AMountOfTheArbiter_IsMounted() { var arbiter = new ChordArbiter(); Check(arbiter.IsMounted(arbiter.Mount())); } public void AnUnmountedMount_IsNot() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.Unmount(mount); CheckFalse(arbiter.IsMounted(mount)); } public void AMountOfAnotherArbiter_IsNot() { ChordMount elsewhere = new ChordArbiter().Mount(); CheckFalse(new ChordArbiter().IsMounted(elsewhere)); } public void Null_Throws() { CheckThrow(typeof(ArgumentNullException)); new ChordArbiter().IsMounted(null); } } public class MountCountTests : TestFixture { public void NewArbiter_HasNone() { CheckEqual(0, new ChordArbiter().MountCount); } public void CountsEveryMountEmptyOrNot() { var arbiter = new ChordArbiter(); arbiter.Mount(); arbiter.Mount(Delete); CheckEqual(2, arbiter.MountCount); } public void DropsUnmountedMountsButNotClearedOnes() { var arbiter = new ChordArbiter(); ChordMount unmounted = arbiter.Mount(Delete); ChordMount cleared = arbiter.Mount(Delete); arbiter.Unmount(unmounted); arbiter.Clear(cleared); CheckEqual(1, arbiter.MountCount); } } public class CountTests : TestFixture { public void NewArbiter_HasNone() { CheckEqual(0, new ChordArbiter().Count); } public void AddsUpTheChordsOfEveryMount() { var arbiter = new ChordArbiter(); arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); arbiter.Mount(Chord.Press(KeyCode.A)); CheckEqual(3, arbiter.Count); } public void AChordOnTwoMounts_CountsTwice() { var arbiter = new ChordArbiter(); arbiter.Mount(Delete); arbiter.Mount(Delete); CheckEqual(2, arbiter.Count); } public void DropsRemovedAndClearedAndUnmountedChords() { var arbiter = new ChordArbiter(); ChordMount removedFrom = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); ChordMount cleared = arbiter.Mount(Delete); ChordMount unmounted = arbiter.Mount(Delete); arbiter.Remove(Delete, removedFrom); arbiter.Clear(cleared); arbiter.Unmount(unmounted); CheckEqual(1, arbiter.Count); } } public class MountsTests : TestFixture { public static List Walk(ChordArbiter arbiter) { var returnMe = new List(); foreach (ChordMount mount in arbiter.Mounts()) { returnMe.Add(mount); } return returnMe; } public void NewArbiter_YieldsNothing() { CheckEqual(0, Walk(new ChordArbiter()).Count); } public void YieldsEachMountOnce() { var arbiter = new ChordArbiter(); ChordMount first = arbiter.Mount(); ChordMount second = arbiter.Mount(Delete); List walked = Walk(arbiter); CheckEqual(2, walked.Count); Check(walked.Contains(first)); Check(walked.Contains(second)); } public void YieldsMountsInTheOrderTheyWereMounted() { var arbiter = new ChordArbiter(); ChordMount first = arbiter.Mount(); ChordMount second = arbiter.Mount(); ChordMount third = arbiter.Mount(); List walked = Walk(arbiter); CheckEqual(first, walked[0]); CheckEqual(second, walked[1]); CheckEqual(third, walked[2]); } public void AMountMadeAfterAnUnmount_ComesLast() { var arbiter = new ChordArbiter(); ChordMount first = arbiter.Mount(); ChordMount second = arbiter.Mount(); arbiter.Unmount(first); ChordMount third = arbiter.Mount(); List walked = Walk(arbiter); CheckEqual(2, walked.Count); CheckEqual(second, walked[0]); CheckEqual(third, walked[1]); } public void DoesNotYieldUnmountedMounts() { var arbiter = new ChordArbiter(); ChordMount unmounted = arbiter.Mount(); ChordMount kept = arbiter.Mount(); arbiter.Unmount(unmounted); List walked = Walk(arbiter); CheckEqual(1, walked.Count); CheckEqual(kept, walked[0]); } public void MountingWhileWalking_Throws() { var arbiter = new ChordArbiter(); arbiter.Mount(); ChordArbiter.MountEnumerator mounts = arbiter.Mounts(); mounts.MoveNext(); arbiter.Mount(); CheckThrow(typeof(InvalidOperationException)); mounts.MoveNext(); } } public class SetEnabledTests : TestFixture { public void DisablingAMount_StopsItsChordsFiring() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.SetEnabled(mount, false); CheckFalse(arbiter.ShouldFire(Delete, mount, Pressing(KeyCode.Delete))); } public void DisablingAMount_LetsWhatItsChordsHidFire() { var arbiter = new ChordArbiter(); ChordMount weaker = arbiter.Mount(Delete); ChordMount stronger = arbiter.Mount(ShiftDelete); KeyboardSnapshot shiftDelete = Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)); arbiter.SetEnabled(stronger, false); Check(arbiter.ShouldFire(Delete, weaker, shiftDelete)); } public void DisablingAMount_LeavesOtherMountsFiring() { var arbiter = new ChordArbiter(); ChordMount disabled = arbiter.Mount(Delete); ChordMount other = arbiter.Mount(Delete); arbiter.SetEnabled(disabled, false); Check(arbiter.ShouldFire(Delete, other, Pressing(KeyCode.Delete))); } public void DisablingAMount_LeavesEachChordsOwnEnabledState() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.SetEnabled(mount, false); Check(arbiter.IsEnabled(Delete, mount)); } public void EnablingAgain_RestoresTheChordsThatWereEnabled() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.SetEnabled(mount, false); arbiter.SetEnabled(mount, true); Check(arbiter.ShouldFire(Delete, mount, Pressing(KeyCode.Delete))); } public void EnablingAgain_KeepsDisabledTheChordsThatWereDisabledOnTheirOwn() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.SetEnabled(Delete, mount, false); arbiter.SetEnabled(mount, false); arbiter.SetEnabled(mount, true); CheckFalse(arbiter.ShouldFire(Delete, mount, Pressing(KeyCode.Delete))); } public void AChordAddedToADisabledMount_DoesNotFire() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.SetEnabled(mount, false); arbiter.Add(Delete, mount); CheckFalse(arbiter.ShouldFire(Delete, mount, Pressing(KeyCode.Delete))); } public void AClone_KeepsTheMountDisabled() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.SetEnabled(mount, false); ChordArbiter clone = arbiter.Clone(); CheckFalse(clone.IsEnabled(mount)); } public void DisablingAMountOfTheClone_LeavesTheArbiterAlone() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.Clone().SetEnabled(mount, false); Check(arbiter.IsEnabled(mount)); } public void AnUnmountedMount_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.Unmount(mount); CheckThrow(typeof(ArgumentException)); arbiter.SetEnabled(mount, false); } public void Null_Throws() { CheckThrow(typeof(ArgumentNullException)); new ChordArbiter().SetEnabled((ChordMount)null, false); } } public class IsEnabledTests : TestFixture { public void ANewMount_IsEnabled() { var arbiter = new ChordArbiter(); Check(arbiter.IsEnabled(arbiter.Mount())); } public void ADisabledMount_IsNot() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.SetEnabled(mount, false); CheckFalse(arbiter.IsEnabled(mount)); } public void AMountEnabledAgain_Is() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.SetEnabled(mount, false); arbiter.SetEnabled(mount, true); Check(arbiter.IsEnabled(mount)); } public void AnUnmountedMount_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.Unmount(mount); CheckThrow(typeof(ArgumentException)); arbiter.IsEnabled(mount); } public void Null_Throws() { CheckThrow(typeof(ArgumentNullException)); new ChordArbiter().IsEnabled((ChordMount)null); } } public class SetPriorityTests : TestFixture { public void AChord_TakesTheNewPriority() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete, priority: 1); arbiter.SetPriority(Delete, mount, 5); CheckEqual(5, arbiter.PriorityOf(Delete, mount)); } public void AChordRaisedAboveItsEquivalentOnAnotherMount_NowHidesIt() { var arbiter = new ChordArbiter(); ChordMount low = arbiter.Mount(Delete, priority: 1); ChordMount high = arbiter.Mount(Delete, priority: 2); arbiter.SetPriority(Delete, low, 3); Check(arbiter.ShouldFire(Delete, low, Pressing(KeyCode.Delete))); CheckFalse(arbiter.ShouldFire(Delete, high, Pressing(KeyCode.Delete))); } public void AChordLoweredBelowItsEquivalentOnAnotherMount_IsNowHiddenByIt() { var arbiter = new ChordArbiter(); ChordMount low = arbiter.Mount(Delete, priority: 1); ChordMount high = arbiter.Mount(Delete, priority: 2); arbiter.SetPriority(Delete, high, 0); Check(arbiter.ShouldFire(Delete, low, Pressing(KeyCode.Delete))); CheckFalse(arbiter.ShouldFire(Delete, high, Pressing(KeyCode.Delete))); } public void AChord_KeepsHidingTheLessSpecificChordsItAlreadyHid() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); arbiter.SetPriority(ShiftDelete, mount, 4); CheckFalse(arbiter.ShouldFire(Delete, mount, Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)))); } public void AChord_KeepsItsEnabledState() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete); arbiter.SetEnabled(Delete, mount, false); arbiter.SetPriority(Delete, mount, 2); CheckFalse(arbiter.IsEnabled(Delete, mount)); } public void AChord_LeavesTheOthersOnItsMountAndTheSameChordOnOtherMounts() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete), priority: 1); ChordMount other = arbiter.Mount(Delete, priority: 1); arbiter.SetPriority(Delete, mount, 3); CheckEqual(1, arbiter.PriorityOf(ShiftDelete, mount)); CheckEqual(1, arbiter.PriorityOf(Delete, other)); } public void TheSamePriority_ChangesNothing() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(Delete, priority: 2); arbiter.SetPriority(Delete, mount, 2); CheckEqual(2, arbiter.PriorityOf(Delete, mount)); CheckEqual(1, arbiter.CountOn(mount)); } public void AChordNotOnTheMount_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); CheckThrow(typeof(ArgumentException)); arbiter.SetPriority(Delete, mount, 1); } public void ANullChord_Throws() { var arbiter = new ChordArbiter(); CheckThrow(typeof(ArgumentNullException)); arbiter.SetPriority(null, arbiter.Mount(), 1); } public void AMount_GivesEveryChordThePriority() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.Add(Delete, mount, priority: 1); arbiter.Add(ShiftDelete, mount, priority: 5); arbiter.SetPriority(mount, 2); CheckEqual(2, arbiter.PriorityOf(Delete, mount)); CheckEqual(2, arbiter.PriorityOf(ShiftDelete, mount)); } public void AMountRaisedAboveAnother_NowHidesItsEquivalentChords() { var arbiter = new ChordArbiter(); ChordMount low = arbiter.Mount(ChordSet.Of(Delete), priority: 1); ChordMount high = arbiter.Mount(ChordSet.Of(Delete), priority: 2); arbiter.SetPriority(low, 3); Check(arbiter.ShouldFire(Delete, low, Pressing(KeyCode.Delete))); CheckFalse(arbiter.ShouldFire(Delete, high, Pressing(KeyCode.Delete))); } public void AMountAtThePriorityItAlreadyHas_KeepsItsRankings() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete), priority: 2); arbiter.SetPriority(mount, 2); CheckFalse(arbiter.ShouldFire(Delete, mount, Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)))); } public void AMount_KeepsTheRankingsAmongItsChords() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); arbiter.SetPriority(mount, 7); CheckFalse(arbiter.ShouldFire(Delete, mount, Pressing(KeyCode.Delete, alsoHeld: new KeyState(KeyCode.ShiftLeft)))); } public void AMount_KeepsEachChordsEnabledState() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(ChordSet.Of(Delete, ShiftDelete)); arbiter.SetEnabled(ShiftDelete, mount, false); arbiter.SetPriority(mount, 3); CheckFalse(arbiter.IsEnabled(ShiftDelete, mount)); Check(arbiter.IsEnabled(Delete, mount)); } public void AMount_LeavesOtherMountsAlone() { var arbiter = new ChordArbiter(); Chord pressA = Chord.Press(KeyCode.A); ChordMount mount = arbiter.Mount(Delete, priority: 1); ChordMount other = arbiter.Mount(pressA, priority: 1); arbiter.SetPriority(mount, 4); CheckEqual(1, arbiter.PriorityOf(pressA, other)); } public void AnEmptyMount_ChangesNothing() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.SetPriority(mount, 3); CheckEqual(0, arbiter.CountOn(mount)); } public void AnUnmountedMount_Throws() { var arbiter = new ChordArbiter(); ChordMount mount = arbiter.Mount(); arbiter.Unmount(mount); CheckThrow(typeof(ArgumentException)); arbiter.SetPriority(mount, 1); } public void ANullMount_Throws() { CheckThrow(typeof(ArgumentNullException)); new ChordArbiter().SetPriority((ChordMount)null, 1); } } } }