using Amphora; using Annulus; using Azimuth; using Clave; using Glass.Editing; using Glass.UnitTests.Typesetting; using System; using System.Collections.Generic; using UnitTestSharp; namespace Glass.UnitTests { public class TextBoxTests : TestFixture { /// /// Letters 10 wide, a space 4, and lines 10 tall. /// public static readonly SpriteFontDefinition Font = LineWrapperTests.FontWithTenPixelLines; public static readonly TextBoxMaterial FlatMaterial = new TextBoxMaterial { Text = new TextStyle { Font = Font, HorizontalMargin = 0, VerticalMargin = 0 }, Selection = new SolidColorMaterial(), Caret = new SolidColorMaterial(), CaretWidth = 1, }; public static readonly TextBoxMaterial InactiveSelectionMaterial = FlatMaterial with { Selection = new SolidColorMaterial { Color = System.Drawing.Color.Blue }, InactiveSelection = new SolidColorMaterial { Color = System.Drawing.Color.Gray }, }; public class TestCursor : Cursor { } public class FakeClipboard : IClipboard { public string Held { get; set; } public bool TryGetText(out string text) { text = Held; return Held != null; } public void SetText(string text) { Held = text; } } /// /// A 100 wide, 10 tall box at the origin with no background, so text starts at the box's left edge. /// public static TextBox NewBox(string text = "", int width = 100, TextBoxBehavior behavior = null, int maxLength = EditBuffer.NoLimit, TextBoxMaterial? material = null) { var box = new TextBox(behavior ?? new TextBoxBehavior(), maxLength) { TextBoxMaterial = material ?? FlatMaterial, }; box.Bounds = Rect.FromPositionAndSize(Vector.Zero, new Vector(width, 10)); box.Text = text; return box; } /// /// The keys' manager with in it and holding focus. /// public static KeyboardManager Focus(TextBox box, IClipboard clipboard = null) { var keys = new KeyboardManager { Clipboard = clipboard }; keys.Controls.Add(box); keys.TrySetFocus(box); return keys; } public static KeyboardSnapshot Pressing(KeyCode key, params KeyCode[] heldFirst) { var tracker = new KeyTracker(); foreach (KeyCode held in heldFirst) { tracker.KeyDown(held, KeyCode.None, isRepeat: false); } return tracker.KeyDown(key, KeyCode.None, isRepeat: false); } public static KeyboardSnapshot Repeating(KeyCode key) { var tracker = new KeyTracker(); tracker.KeyDown(key, KeyCode.None, isRepeat: false); return tracker.KeyDown(key, KeyCode.None, isRepeat: true); } public static MouseState At(Scalar x) => new MouseState { Position = new Vector(x, 5) }; public static void UpdateFocused(TextBox box, double seconds = 0) { box.Update(Duration.FromSeconds(seconds), new UpdateState { Focused = box }); } public static Scalar CaretX(TextBox box) => box.CaretPanel.Bounds.Left; public class CtorTests : TestFixture { public void IsAFocusableTabStopThatTakesFocusWhenClicked() { var box = NewBox(); Check(box.Focusable); Check(box.FocusOnClick); } public void KeepsTheBehaviorItWasGiven() { var behavior = new TextBoxBehavior(); Check(ReferenceEquals(behavior, NewBox(behavior: behavior).Behavior)); } public void NullBehavior_Throws() { CheckThrow(typeof(ArgumentNullException)); new TextBox(null); } public void MaxLength_LimitsTheBuffer() { CheckEqual(5, new TextBox(new TextBoxBehavior(), maxLength: 5).Buffer.MaxLength); } public void StartsEmpty() { CheckEqual("", new TextBox(new TextBoxBehavior()).Text); } } public class AcceptsTextTests : TestFixture { public void WhileEnabled_IsTrue() { Check(NewBox().AcceptsText); } public void WhileDisabled_IsFalse() { var box = NewBox(); box.Enabled = false; CheckFalse(box.AcceptsText); } } public class TextTests : TestFixture { public void Set_ShowsInTheLabelAndPutsTheCaretAtTheEnd() { var box = NewBox("abc"); CheckEqual("abc", box.Text); CheckEqual("abc", box.Label.Text.ToString()); CheckEqual(3, box.Buffer.Caret); CheckEqual(30, CaretX(box)); } public void Set_TurnsLineBreaksIntoSpaces() { CheckEqual("a b c d", NewBox("a\nb\r\nc\rd").Text); } public void Set_Null_Throws() { var box = NewBox(); CheckThrow(typeof(ArgumentNullException)); box.Text = null; } public void Set_PastMaxLength_Throws() { var box = NewBox(maxLength: 2); CheckThrow(typeof(ArgumentException)); box.Text = "abc"; } public void Set_RaisesOnTextChangedOnce() { var box = NewBox(); int raised = 0; box.OnTextChanged += _ => ++raised; box.Text = "abc"; CheckEqual(1, raised); } public void Set_ToTheSameText_RaisesNothing() { var box = NewBox("abc"); int raised = 0; box.OnTextChanged += _ => ++raised; box.Text = "abc"; CheckEqual(0, raised); } public void ChangedThroughTheBuffer_IsPickedUpAtTheNextUpdate() { var box = NewBox("abc"); int raised = 0; box.OnTextChanged += _ => ++raised; box.Buffer.Insert("d"); box.Update(Duration.Zero, new UpdateState()); CheckEqual("abcd", box.Label.Text.ToString()); CheckEqual(40, CaretX(box)); CheckEqual(1, raised); } public void NoFont_ShowsNothingAndDoesNotThrow() { var box = new TextBox(new TextBoxBehavior()); box.Bounds = Rect.FromPositionAndSize(Vector.Zero, new Vector(100, 10)); box.Text = "abc"; box.Buffer.SelectAll(); box.Update(Duration.Zero, new UpdateState { Focused = box }); CheckEqual("abc", box.Text); CheckFalse(box.SelectionPanel.Visible); CheckFalse(box.CaretPanel.Visible); } } public class CaretAndSelectionTests : TestFixture { public void Caret_IsABarOfTheMaterialsWidthAndTheLinesHeight() { var box = NewBox("abc"); CheckEqual(Rect.FromPositionAndSize(new Vector(30, 0), new Vector(1, 10)), box.CaretPanel.Bounds); } public void Caret_FollowsMoves() { var box = NewBox("abc"); box.Buffer.Move(TextUnit.Character, forward: false, extend: false); UpdateFocused(box); CheckEqual(20, CaretX(box)); } public void Selection_SpansTheSelectedText() { var box = NewBox("abcd"); box.Buffer.MoveTo(1, extend: false); box.Buffer.MoveTo(3, extend: true); UpdateFocused(box); Check(box.SelectionPanel.Visible); CheckEqual(Rect.FromPositionAndSize(new Vector(10, 0), new Vector(20, 10)), box.SelectionPanel.Bounds); } public void Selection_IsHiddenWithoutFocusUnlessThereIsAnInactiveLook() { var box = NewBox("abcd"); box.Buffer.SelectAll(); box.Update(Duration.Zero, new UpdateState()); CheckFalse(box.SelectionPanel.Visible); } public void Selection_ComesBackWhenFocusArrives() { var box = NewBox("abcd"); box.Buffer.SelectAll(); box.Update(Duration.Zero, new UpdateState()); UpdateFocused(box); Check(box.SelectionPanel.Visible); } public void Selection_UsesTheActiveLookWhileFocused() { var box = NewBox("abcd", material: InactiveSelectionMaterial); box.Buffer.SelectAll(); UpdateFocused(box); Check(ReferenceEquals(InactiveSelectionMaterial.Selection, box.SelectionPanel.Material)); Check(box.SelectionPanel.Visible); } public void Selection_UsesTheInactiveLookWithoutFocus() { var box = NewBox("abcd", material: InactiveSelectionMaterial); box.Buffer.SelectAll(); UpdateFocused(box); box.Update(Duration.Zero, new UpdateState()); Check(ReferenceEquals(InactiveSelectionMaterial.InactiveSelection, box.SelectionPanel.Material)); Check(box.SelectionPanel.Visible); } public void Selection_StaysHiddenWhenNothingIsSelectedWhateverTheFocus() { var box = NewBox("abcd", material: InactiveSelectionMaterial); UpdateFocused(box); CheckFalse(box.SelectionPanel.Visible); box.Update(Duration.Zero, new UpdateState()); CheckFalse(box.SelectionPanel.Visible); } public void Selection_IsHiddenWhenNothingIsSelected() { var box = NewBox("abcd"); CheckFalse(box.SelectionPanel.Visible); } public void Selection_FollowsTheCaretBackwards() { var box = NewBox("abcd"); box.Buffer.MoveTo(3, extend: false); box.Buffer.MoveTo(1, extend: true); UpdateFocused(box); CheckEqual(Rect.FromPositionAndSize(new Vector(10, 0), new Vector(20, 10)), box.SelectionPanel.Bounds); } public void Caret_IsShownOnlyWhileTheBoxHasFocus() { var box = NewBox("abc"); box.Update(Duration.Zero, new UpdateState()); CheckFalse(box.CaretPanel.Visible); UpdateFocused(box); Check(box.CaretPanel.Visible); box.Update(Duration.Zero, new UpdateState()); CheckFalse(box.CaretPanel.Visible); } public void Caret_IsHiddenWhileDisabled() { var box = NewBox("abc"); UpdateFocused(box); box.Enabled = false; UpdateFocused(box); CheckFalse(box.CaretPanel.Visible); } public void Caret_Blinks() { var box = NewBox("abc", behavior: new TextBoxBehavior { BlinkInterval = Duration.FromSeconds(1) }); UpdateFocused(box); Check(box.CaretPanel.Visible); UpdateFocused(box, 0.5); Check(box.CaretPanel.Visible); UpdateFocused(box, 0.6); CheckFalse(box.CaretPanel.Visible); UpdateFocused(box, 1); Check(box.CaretPanel.Visible); } public void Caret_StaysOnWithAZeroInterval() { var box = NewBox("abc", behavior: new TextBoxBehavior { BlinkInterval = Duration.Zero }); UpdateFocused(box, 5); UpdateFocused(box, 5); Check(box.CaretPanel.Visible); } public void Caret_ComesBackOnAtOnceAfterAnEdit() { var box = NewBox("abc", behavior: new TextBoxBehavior { BlinkInterval = Duration.FromSeconds(1) }); UpdateFocused(box); UpdateFocused(box, 1.5); CheckFalse(box.CaretPanel.Visible); box.TextInput("d"); UpdateFocused(box); Check(box.CaretPanel.Visible); } public void Caret_ComesBackOnWhenFocusArrives() { var box = NewBox("abc", behavior: new TextBoxBehavior { BlinkInterval = Duration.FromSeconds(1) }); UpdateFocused(box); UpdateFocused(box, 1.5); box.Update(Duration.Zero, new UpdateState()); UpdateFocused(box); Check(box.CaretPanel.Visible); } } public class ScrollTests : TestFixture { public void TextThatFits_ShowsFromTheStart() { var box = NewBox("abcd", width: 50); CheckEqual("abcd", box.Label.Text.ToString()); } public void CaretPastTheRightEdge_ScrollsJustEnough() { var box = NewBox("abcdef", width: 45); CheckEqual("cdef", box.Label.Text.ToString()); CheckEqual(40, CaretX(box)); } public void MovingBackToTheLeftEdge_ScrollsBack() { var box = NewBox("abcdef", width: 45); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); CheckEqual("abcdef", box.Label.Text.ToString()); CheckEqual(0, CaretX(box)); } public void MovingWithinTheView_DoesNotScroll() { var box = NewBox("abcdef", width: 45); box.Buffer.MoveTo(3, extend: false); UpdateFocused(box); CheckEqual("cdef", box.Label.Text.ToString()); CheckEqual(10, CaretX(box)); } public void TextThatShrinks_ScrollsBackToFillTheBox() { var box = NewBox("abcdef", width: 45); box.Text = "ab"; CheckEqual("ab", box.Label.Text.ToString()); CheckEqual(20, CaretX(box)); } public void TextThatShrinksButStillOverflows_ShowsTheEndOfIt() { var box = NewBox("abcdefgh", width: 45); box.Text = "abcdef"; CheckEqual("cdef", box.Label.Text.ToString()); } public void ScrollingNeverStartsInsideASurrogatePair() { string emoji = char.ConvertFromUtf32(0x20BB7); for (int width = 5; width < 60; ++width) { var box = NewBox("a" + emoji + "b" + emoji + "c" + emoji, width); string shown = box.Label.Text.ToString(); CheckFalse(shown.Length > 0 && char.IsLowSurrogate(shown[0])); } } public void SelectionPastTheRightEdge_StopsAtIt() { var box = NewBox("abcdef", width: 45); box.Buffer.MoveTo(2, extend: false); box.Buffer.MoveTo(6, extend: true); UpdateFocused(box); Check(box.SelectionPanel.Bounds.Width > 0); } } public class KeyDownTests : TestFixture { public void ArrowKeys_MoveTheCaret() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); Check(keys.KeyDown(Pressing(KeyCode.ArrowLeft))); CheckEqual(2, box.Buffer.Caret); Check(keys.KeyDown(Pressing(KeyCode.ArrowRight))); CheckEqual(3, box.Buffer.Caret); } public void ShiftWithAnArrow_Selects() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ArrowLeft, KeyCode.ShiftLeft)); CheckEqual("c", box.Buffer.SelectedText.ToString()); } public void HomeAndEnd_MoveToTheEdgesOfTheText() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.Home)); CheckEqual(0, box.Buffer.Caret); keys.KeyDown(Pressing(KeyCode.End)); CheckEqual(3, box.Buffer.Caret); } public void ControlWithAnArrow_MovesByWord() { var box = NewBox("ab cd"); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ArrowLeft, KeyCode.ControlLeft)); CheckEqual(3, box.Buffer.Caret); } public void Backspace_AndDelete_RemoveText() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.Backspace)); CheckEqual("ab", box.Text); box.Buffer.MoveTo(0, extend: false); keys.KeyDown(Pressing(KeyCode.Delete)); CheckEqual("b", box.Text); } public void ControlA_SelectsAll() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.A, KeyCode.ControlLeft)); CheckEqual("abc", box.Buffer.SelectedText.ToString()); } public void AutoRepeat_Repeats() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); keys.KeyDown(Repeating(KeyCode.ArrowLeft)); CheckEqual(2, box.Buffer.Caret); } public void Edits_RaiseOnTextChanged() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); int raised = 0; box.OnTextChanged += _ => ++raised; keys.KeyDown(Pressing(KeyCode.Backspace)); CheckEqual(1, raised); } public void Moves_RaiseNothing() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); int raised = 0; box.OnTextChanged += _ => ++raised; keys.KeyDown(Pressing(KeyCode.ArrowLeft)); CheckEqual(0, raised); } public void KeysThatTypeCharacters_AreClaimedAndLeftToTextInput() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); Check(keys.KeyDown(Pressing(KeyCode.A))); Check(keys.KeyDown(Pressing(KeyCode.Digit5))); Check(keys.KeyDown(Pressing(KeyCode.Space))); Check(keys.KeyDown(Pressing(KeyCode.Comma))); Check(keys.KeyDown(Pressing(KeyCode.Numpad3))); CheckEqual("abc", box.Text); } public void ShiftedCharacters_AreClaimed() { var box = NewBox(); KeyboardManager keys = Focus(box); Check(keys.KeyDown(Pressing(KeyCode.A, KeyCode.ShiftLeft))); } public void AltGrCharacters_AreClaimed() { var box = NewBox(); KeyboardManager keys = Focus(box); Check(keys.KeyDown(Pressing(KeyCode.Q, KeyCode.AltRight))); } public void ControlLettersWithAGameShortcut_AreLeftToTheGame() { var box = NewBox(); KeyboardManager keys = Focus(box); keys.AddShortcut(Chord.PressOrRepeat(KeyCode.S).WithAnyHeld(KeyState.Control)); CheckFalse(keys.KeyDown(Pressing(KeyCode.S, KeyCode.ControlLeft))); } public void ControlLettersWithoutOne_AreClaimed() { var box = NewBox(); KeyboardManager keys = Focus(box); Check(keys.KeyDown(Pressing(KeyCode.S, KeyCode.ControlLeft))); } public void AltLettersWithAGameShortcut_AreLeftToTheGame() { var box = NewBox(); KeyboardManager keys = Focus(box); keys.AddShortcut(Chord.PressOrRepeat(KeyCode.F).WithAnyHeld(KeyState.Alt)); CheckFalse(keys.KeyDown(Pressing(KeyCode.F, KeyCode.AltLeft))); } public void AltLettersWithoutOne_AreClaimed() { var box = NewBox(); KeyboardManager keys = Focus(box); Check(keys.KeyDown(Pressing(KeyCode.F, KeyCode.AltLeft))); } public void AGameShortcutOnATypingKeyAlone_LosesToTheBox() { var box = NewBox(); KeyboardManager keys = Focus(box); keys.AddShortcut(Chord.PressOrRepeat(KeyCode.A)); Check(keys.KeyDown(Pressing(KeyCode.A))); } public void FunctionKeys_AreLeftToTheGame() { var box = NewBox(); KeyboardManager keys = Focus(box); CheckFalse(keys.KeyDown(Pressing(KeyCode.F1))); } public void ArrowKeysThatHaveNoBinding_AreLeftAlone() { var box = NewBox(); KeyboardManager keys = Focus(box); CheckFalse(keys.KeyDown(Pressing(KeyCode.ArrowUp))); } public void Tab_StillMovesFocusAway() { var box = NewBox(); KeyboardManager keys = Focus(box); var other = new Control { Focusable = true }; keys.Controls.Add(other); keys.KeyDown(Pressing(KeyCode.Tab)); Check(ReferenceEquals(other, keys.Focused)); } public void Escape_StillBlurs() { var box = NewBox(); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.Escape)); CheckNull(keys.Focused); } public void AGameShortcutOnAnEditKey_LosesToTheBox() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); keys.AddShortcut(Chord.PressOrRepeat(KeyCode.ArrowLeft)); keys.KeyDown(Pressing(KeyCode.ArrowLeft)); CheckEqual(2, box.Buffer.Caret); } public void ADisabledBox_ClaimsNothing() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); box.Enabled = false; CheckFalse(box.KeyDown(Pressing(KeyCode.A), keys)); CheckFalse(box.KeyDown(Pressing(KeyCode.Backspace), keys)); CheckEqual("abc", box.Text); } public void KeyChords_AreTheBehaviors() { var behavior = new TextBoxBehavior(); Check(ReferenceEquals(behavior.KeyChords, NewBox(behavior: behavior).KeyChords)); } public void AnotherBinding_ReplacesTheDefault() { var behavior = new TextBoxBehavior { Bindings = EditBindings.Readline }; var box = NewBox("abc", behavior: behavior); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.A, KeyCode.ControlLeft)); CheckEqual(0, box.Buffer.Caret); CheckFalse(box.Buffer.HasSelection); } } public class SubmitTests : TestFixture { public void Enter_RaisesOnSubmitAndIsClaimed() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); TextBox submitted = null; box.OnSubmit += sender => submitted = sender; Check(keys.KeyDown(Pressing(KeyCode.MainEnter))); Check(ReferenceEquals(box, submitted)); } public void NumpadEnter_Submits() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); int raised = 0; box.OnSubmit += _ => ++raised; keys.KeyDown(Pressing(KeyCode.NumpadEnter)); CheckEqual(1, raised); } public void HeldEnter_SubmitsOnlyOnThePress() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); int raised = 0; box.OnSubmit += _ => ++raised; Check(keys.KeyDown(Repeating(KeyCode.MainEnter))); CheckEqual(0, raised); } public void Enter_ChangesNoText() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.MainEnter)); CheckEqual("abc", box.Text); } } public class TextInputTests : TestFixture { public void InsertsAtTheCaret() { var box = NewBox("ac"); box.Buffer.MoveTo(1, extend: false); box.TextInput("b"); CheckEqual("abc", box.Text); CheckEqual(2, box.Buffer.Caret); } public void ReplacesTheSelection() { var box = NewBox("abc"); box.Buffer.SelectAll(); box.TextInput("x"); CheckEqual("x", box.Text); } public void ShowsTheTextAtOnce() { var box = NewBox(); box.TextInput("ab"); CheckEqual("ab", box.Label.Text.ToString()); CheckEqual(20, CaretX(box)); } public void ALoneEnterCharacter_IsIgnored() { var box = NewBox("abc"); box.TextInput("\r"); box.TextInput("\n"); box.TextInput("\r\n"); CheckEqual("abc", box.Text); } public void LineBreaksAmongOtherText_BecomeSpaces() { var box = NewBox(); box.TextInput("a\r\nb\nc"); CheckEqual("a b c", box.Text); } public void EmptyText_ChangesNothing() { var box = NewBox("abc"); int raised = 0; box.OnTextChanged += _ => ++raised; box.TextInput(""); CheckEqual(0, raised); } public void Null_ChangesNothing() { var box = NewBox("abc"); box.TextInput(null); CheckEqual("abc", box.Text); } public void ADisabledBox_IgnoresIt() { var box = NewBox("abc"); box.Enabled = false; box.TextInput("d"); CheckEqual("abc", box.Text); } public void StopsAtMaxLength() { var box = NewBox("ab", maxLength: 3); box.TextInput("cdef"); CheckEqual("abc", box.Text); } public void RaisesOnTextChanged() { var box = NewBox(); int raised = 0; box.OnTextChanged += _ => ++raised; box.TextInput("a"); CheckEqual(1, raised); } } public class ClipboardTests : TestFixture { public void ControlC_CopiesTheSelection() { var box = NewBox("abc"); var clipboard = new FakeClipboard(); KeyboardManager keys = Focus(box, clipboard); box.Buffer.MoveTo(1, extend: false); box.Buffer.MoveTo(3, extend: true); Check(keys.KeyDown(Pressing(KeyCode.C, KeyCode.ControlLeft))); CheckEqual("bc", clipboard.Held); CheckEqual("abc", box.Text); } public void ControlC_WithNothingSelected_LeavesTheClipboardAlone() { var box = NewBox("abc"); var clipboard = new FakeClipboard { Held = "keep" }; KeyboardManager keys = Focus(box, clipboard); keys.KeyDown(Pressing(KeyCode.C, KeyCode.ControlLeft)); CheckEqual("keep", clipboard.Held); } public void ControlX_CutsTheSelection() { var box = NewBox("abc"); var clipboard = new FakeClipboard(); KeyboardManager keys = Focus(box, clipboard); box.Buffer.MoveTo(1, extend: false); box.Buffer.MoveTo(3, extend: true); keys.KeyDown(Pressing(KeyCode.X, KeyCode.ControlLeft)); CheckEqual("bc", clipboard.Held); CheckEqual("a", box.Text); } public void ControlX_WithNothingSelected_ChangesNothing() { var box = NewBox("abc"); KeyboardManager keys = Focus(box, new FakeClipboard()); keys.KeyDown(Pressing(KeyCode.X, KeyCode.ControlLeft)); CheckEqual("abc", box.Text); } public void ControlV_PastesAtTheCaret() { var box = NewBox("ad"); KeyboardManager keys = Focus(box, new FakeClipboard { Held = "bc" }); box.Buffer.MoveTo(1, extend: false); keys.KeyDown(Pressing(KeyCode.V, KeyCode.ControlLeft)); CheckEqual("abcd", box.Text); CheckEqual(3, box.Buffer.Caret); } public void Paste_TurnsLineBreaksIntoSpaces() { var box = NewBox(); KeyboardManager keys = Focus(box, new FakeClipboard { Held = "a\r\nb\nc" }); keys.KeyDown(Pressing(KeyCode.V, KeyCode.ControlLeft)); CheckEqual("a b c", box.Text); } public void Paste_OfNothingButALineBreak_BecomesASpace() { var box = NewBox("ab"); KeyboardManager keys = Focus(box, new FakeClipboard { Held = "\n" }); box.Buffer.MoveTo(1, extend: false); keys.KeyDown(Pressing(KeyCode.V, KeyCode.ControlLeft)); CheckEqual("a b", box.Text); } public void Paste_WithAnEmptyClipboard_ChangesNothing() { var box = NewBox("abc"); KeyboardManager keys = Focus(box, new FakeClipboard()); keys.KeyDown(Pressing(KeyCode.V, KeyCode.ControlLeft)); CheckEqual("abc", box.Text); } public void WithoutAClipboard_AllThreeDoNothing() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); box.Buffer.SelectAll(); keys.KeyDown(Pressing(KeyCode.C, KeyCode.ControlLeft)); keys.KeyDown(Pressing(KeyCode.X, KeyCode.ControlLeft)); keys.KeyDown(Pressing(KeyCode.V, KeyCode.ControlLeft)); CheckEqual("abc", box.Text); } public void UndoAndRedo_DoNothing() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); Check(keys.KeyDown(Pressing(KeyCode.Z, KeyCode.ControlLeft))); Check(keys.KeyDown(Pressing(KeyCode.Y, KeyCode.ControlLeft))); CheckEqual("abc", box.Text); } } public class MouseTests : TestFixture { public void Press_PutsTheCaretAtTheNearestStop() { var box = NewBox("abcdef"); Check(box.MouseDown(At(24), MouseButtonFlags.Left)); CheckEqual(2, box.Buffer.Caret); box.MouseUp(At(24), MouseButtonFlags.Left); box.MouseDown(At(26), MouseButtonFlags.Left); CheckEqual(3, box.Buffer.Caret); } public void Press_PastTheEndOfTheText_PutsTheCaretAtTheEnd() { var box = NewBox("abc"); box.Buffer.MoveTo(0, extend: false); box.MouseDown(At(90), MouseButtonFlags.Left); CheckEqual(3, box.Buffer.Caret); } public void Press_ClearsASelection() { var box = NewBox("abc"); box.Buffer.SelectAll(); box.MouseDown(At(10), MouseButtonFlags.Left); CheckFalse(box.Buffer.HasSelection); } public void Drag_SelectsFromThePressToThePointer() { var box = NewBox("abcdef"); box.MouseDown(At(10), MouseButtonFlags.Left); Check(box.MouseMove(At(40))); CheckEqual("bcd", box.Buffer.SelectedText.ToString()); } public void Drag_BackwardsSelectsToo() { var box = NewBox("abcdef"); box.MouseDown(At(40), MouseButtonFlags.Left); box.MouseMove(At(10)); CheckEqual("bcd", box.Buffer.SelectedText.ToString()); CheckEqual(1, box.Buffer.Caret); } public void MovesAfterTheRelease_SelectNothing() { var box = NewBox("abcdef"); box.MouseDown(At(10), MouseButtonFlags.Left); box.MouseUp(At(10), MouseButtonFlags.Left); CheckFalse(box.MouseMove(At(40))); CheckFalse(box.Buffer.HasSelection); } public void CancelledMouseInput_EndsTheDrag() { var box = NewBox("abcdef"); box.MouseDown(At(10), MouseButtonFlags.Left); box.CancelMouseInput(); box.MouseMove(At(40)); CheckFalse(box.Buffer.HasSelection); } public void Drag_PastTheRightEdge_SelectsToTheLastCharacterInView() { var box = NewBox("abcdefgh", width: 45); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); box.MouseMove(At(300)); CheckEqual(4, box.Buffer.Caret); CheckEqual("abcdefgh", box.Label.Text.ToString()); } public void Drag_PastTheRightEdge_ScrollsAtTheBehaviorsRateWhileTheMouseIsStill() { var box = NewBox("abcdefgh", width: 45); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); box.Update(Duration.FromSeconds(0.05), new UpdateState()); CheckEqual(5, box.Buffer.Caret); CheckEqual("bcdefgh", box.Label.Text.ToString()); CheckEqual("abcde", box.Buffer.SelectedText.ToString()); } public void Drag_PastTheLeftEdge_SelectsToTheFirstCharacterInView() { var box = NewBox("abcdefgh", width: 45); CheckEqual("efgh", box.Label.Text.ToString()); box.MouseDown(At(40), MouseButtonFlags.Left); box.MouseMove(At(-50)); CheckEqual(4, box.Buffer.Caret); CheckEqual("efgh", box.Label.Text.ToString()); } public void Drag_PastTheLeftEdge_RevealsCharactersAtTheBehaviorsRate() { var box = NewBox("abcdefgh", width: 45); box.MouseDown(At(40), MouseButtonFlags.Left); box.MouseMove(At(-50)); box.Update(Duration.FromSeconds(0.1), new UpdateState()); CheckEqual(2, box.Buffer.Caret); CheckEqual("cdefgh", box.Label.Text.ToString()); } public void Autoscroll_KeepsTheFractionOfACharacterBetweenFrames() { var box = NewBox("abcdefgh", width: 45); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); box.Update(Duration.FromSeconds(0.03), new UpdateState()); CheckEqual(4, box.Buffer.Caret); box.Update(Duration.FromSeconds(0.03), new UpdateState()); CheckEqual(5, box.Buffer.Caret); } public void Autoscroll_StopsAtTheEndOfTheText() { var box = NewBox("abcdefgh", width: 45); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); box.Update(Duration.FromSeconds(10), new UpdateState()); CheckEqual(8, box.Buffer.Caret); } public void Autoscroll_StopsAtTheStartOfTheText() { var box = NewBox("abcdefgh", width: 45); box.MouseDown(At(40), MouseButtonFlags.Left); box.MouseMove(At(-50)); box.Update(Duration.FromSeconds(10), new UpdateState()); CheckEqual(0, box.Buffer.Caret); } public void Autoscroll_NeverStopsInsideASurrogatePair() { string emoji = char.ConvertFromUtf32(0x20BB7); var box = NewBox("abcd" + emoji + emoji + "efgh", width: 45); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); for (int frame = 0; frame < 12; ++frame) { box.Update(Duration.FromSeconds(0.05), new UpdateState()); int caret = box.Buffer.Caret; CheckFalse(caret < box.Text.Length && char.IsLowSurrogate(box.Text[caret])); } } public void Autoscroll_StopsWhenThePointerComesBackInside() { var box = NewBox("abcdefgh", width: 45); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); box.MouseMove(At(20)); int caret = box.Buffer.Caret; box.Update(Duration.FromSeconds(1), new UpdateState()); CheckEqual(caret, box.Buffer.Caret); } public void Autoscroll_StopsWhenTheButtonComesUp() { var box = NewBox("abcdefgh", width: 45); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); box.MouseUp(At(200), MouseButtonFlags.Left); box.Update(Duration.FromSeconds(1), new UpdateState()); CheckEqual(4, box.Buffer.Caret); } public void Autoscroll_StopsWhenTheDragIsCancelled() { var box = NewBox("abcdefgh", width: 45); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); box.CancelMouseInput(); box.Update(Duration.FromSeconds(1), new UpdateState()); CheckEqual(4, box.Buffer.Caret); } public void Autoscroll_DoesNothingWithoutADrag() { var box = NewBox("abcdefgh", width: 45); box.Buffer.MoveTo(0, extend: false); box.Update(Duration.FromSeconds(1), new UpdateState()); CheckEqual(0, box.Buffer.Caret); } public void Autoscroll_FollowsTheBehaviorsRate() { var behavior = new TextBoxBehavior { AutoscrollCharactersPerSecond = 100 }; var box = NewBox("abcdefghijkl", width: 45, behavior: behavior); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); box.Update(Duration.FromSeconds(0.05), new UpdateState()); CheckEqual(9, box.Buffer.Caret); } public void Autoscroll_CanBeTurnedOff() { var behavior = new TextBoxBehavior { AutoscrollCharactersPerSecond = 0 }; var box = NewBox("abcdefgh", width: 45, behavior: behavior); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); box.Update(Duration.FromSeconds(5), new UpdateState()); CheckEqual(4, box.Buffer.Caret); } public void Autoscroll_ReversingDirectionDropsTheOwedFraction() { var box = NewBox("abcdefgh", width: 45); box.Buffer.MoveTo(0, extend: false); UpdateFocused(box); box.MouseDown(At(5), MouseButtonFlags.Left); box.MouseMove(At(200)); box.Update(Duration.FromSeconds(0.04), new UpdateState()); box.MouseMove(At(-50)); int caret = box.Buffer.Caret; box.Update(Duration.FromSeconds(0.01), new UpdateState()); CheckEqual(caret, box.Buffer.Caret); } public void RightButton_DoesNotMoveTheCaret() { var box = NewBox("abc"); box.MouseDown(At(10), MouseButtonFlags.Right); CheckEqual(3, box.Buffer.Caret); } public void ADisabledBox_IgnoresThePress() { var box = NewBox("abc"); box.Enabled = false; CheckFalse(box.MouseDown(At(10), MouseButtonFlags.Left)); CheckEqual(3, box.Buffer.Caret); } public void ADoubleClick_SelectsTheWord() { var box = NewBox("ab cd"); box.MouseDown(At(5), MouseButtonFlags.Left); box.Click(At(5), MouseButtonFlags.Left, 2); CheckEqual("ab", box.Buffer.SelectedText.ToString()); } public void ATripleClick_SelectsEverything() { var box = NewBox("ab cd"); box.MouseDown(At(5), MouseButtonFlags.Left); box.Click(At(5), MouseButtonFlags.Left, 3); CheckEqual("ab cd", box.Buffer.SelectedText.ToString()); } public void ASingleClick_SelectsNothing() { var box = NewBox("ab cd"); box.MouseDown(At(5), MouseButtonFlags.Left); box.Click(At(5), MouseButtonFlags.Left, 1); CheckFalse(box.Buffer.HasSelection); } public void ARightDoubleClick_SelectsNothing() { var box = NewBox("ab cd"); box.Click(At(5), MouseButtonFlags.Right, 2); CheckFalse(box.Buffer.HasSelection); } } public class ExtendingSelectionTests : TestFixture { public static TextBox BoxWithTheCaretAfterTheFirstLetter(TextBoxBehavior behavior = null) { TextBox box = NewBox("abcdef", behavior: behavior); box.Buffer.MoveTo(1, extend: false); return box; } public void StartsOff() { CheckFalse(NewBox().ExtendingSelection); } public void ShiftGoingDown_TurnsItOn() { var box = NewBox(); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ShiftLeft)); Check(box.ExtendingSelection); } public void EitherShiftKey_TurnsItOn() { var box = NewBox(); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ShiftRight)); Check(box.ExtendingSelection); } public void ShiftComingUp_TurnsItOff() { var box = NewBox(); KeyboardManager keys = Focus(box); var tracker = new KeyTracker(); keys.KeyDown(tracker.KeyDown(KeyCode.ShiftLeft, KeyCode.None, isRepeat: false)); keys.KeyUp(tracker.KeyUp(KeyCode.ShiftLeft)); CheckFalse(box.ExtendingSelection); } public void OneShiftKeyComingUpWhileTheOtherIsHeld_LeavesItOn() { var box = NewBox(); KeyboardManager keys = Focus(box); var tracker = new KeyTracker(); keys.KeyDown(tracker.KeyDown(KeyCode.ShiftLeft, KeyCode.None, isRepeat: false)); keys.KeyDown(tracker.KeyDown(KeyCode.ShiftRight, KeyCode.None, isRepeat: false)); keys.KeyUp(tracker.KeyUp(KeyCode.ShiftLeft)); Check(box.ExtendingSelection); } public void AnotherKeyWhileShiftIsHeld_LeavesItOn() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ArrowLeft, KeyCode.ShiftLeft)); Check(box.ExtendingSelection); } public void AnotherKeyWithShiftNotHeld_LeavesItOff() { var box = NewBox("abc"); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ArrowLeft)); CheckFalse(box.ExtendingSelection); } public void GainingFocusWithShiftHeld_TurnsItOn() { var box = NewBox(); KeyboardManager keys = Focus(box); box.FocusGained(Pressing(KeyCode.ShiftLeft), keys); Check(box.ExtendingSelection); } public void GainingFocusWithShiftNotHeld_TurnsItOff() { var box = NewBox(); KeyboardManager keys = Focus(box); box.ExtendingSelection = true; box.FocusGained(Pressing(KeyCode.A), keys); CheckFalse(box.ExtendingSelection); } public void GainingFocusWhileDisabled_LeavesItOff() { var box = NewBox(); KeyboardManager keys = Focus(box); box.Enabled = false; box.FocusGained(Pressing(KeyCode.ShiftLeft), keys); CheckFalse(box.ExtendingSelection); } public void AFocusingClickWithShiftHeld_ExtendsTheNextPress() { TextBox box = BoxWithTheCaretAfterTheFirstLetter(); KeyboardManager keys = Focus(box); var tracker = new KeyTracker(); tracker.KeyDown(KeyCode.ShiftLeft, KeyCode.None, isRepeat: false); box.FocusGained(tracker.KeyDown(KeyCode.F1, KeyCode.None, isRepeat: false), keys); box.MouseDown(At(40), MouseButtonFlags.Left); CheckEqual("bcd", box.Buffer.SelectedText.ToString()); } public void LosingFocus_TurnsItOff() { var box = NewBox(); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ShiftLeft)); keys.ClearFocus(); CheckFalse(box.ExtendingSelection); } public void BeingDisabled_TurnsItOff() { var box = NewBox(); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ShiftLeft)); box.Enabled = false; CheckFalse(box.ExtendingSelection); } public void ADisabledBoxIgnoresShift() { var box = NewBox(); KeyboardManager keys = Focus(box); box.Enabled = false; box.KeyDown(Pressing(KeyCode.ShiftLeft), keys); CheckFalse(box.ExtendingSelection); } public void CanBeSetDirectly() { var box = NewBox(); box.ExtendingSelection = true; Check(box.ExtendingSelection); } public void ThePressedChordIsTheBindingsExtendSelectionChord() { var behavior = new TextBoxBehavior { Bindings = EditBindings.Windows with { ExtendSelection = Chord.HoldAny(KeyState.Alt) }, }; var box = NewBox(behavior: behavior); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ShiftLeft)); CheckFalse(box.ExtendingSelection); keys.KeyDown(Pressing(KeyCode.AltLeft)); Check(box.ExtendingSelection); } public void APress_WhileExtending_KeepsTheAnchor() { TextBox box = BoxWithTheCaretAfterTheFirstLetter(); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ShiftLeft)); box.MouseDown(At(40), MouseButtonFlags.Left); CheckEqual("bcd", box.Buffer.SelectedText.ToString()); CheckEqual(1, box.Buffer.Anchor); CheckEqual(4, box.Buffer.Caret); } public void APress_WhileExtending_CanGrowTheSelectionBackwards() { TextBox box = NewBox("abcdef"); box.Buffer.MoveTo(4, extend: false); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ShiftLeft)); box.MouseDown(At(10), MouseButtonFlags.Left); CheckEqual("bcd", box.Buffer.SelectedText.ToString()); CheckEqual(1, box.Buffer.Caret); } public void APress_WhileExtending_ThenADragKeepsExtending() { TextBox box = BoxWithTheCaretAfterTheFirstLetter(); KeyboardManager keys = Focus(box); keys.KeyDown(Pressing(KeyCode.ShiftLeft)); box.MouseDown(At(40), MouseButtonFlags.Left); box.MouseMove(At(60)); CheckEqual("bcdef", box.Buffer.SelectedText.ToString()); } public void APress_WithNothingSelected_SelectsFromTheCaret() { TextBox box = BoxWithTheCaretAfterTheFirstLetter(); box.ExtendingSelection = true; box.MouseDown(At(30), MouseButtonFlags.Left); CheckEqual("bc", box.Buffer.SelectedText.ToString()); } public void APress_NotExtending_DropsTheSelection() { TextBox box = NewBox("abcdef"); box.Buffer.SelectAll(); box.MouseDown(At(30), MouseButtonFlags.Left); CheckFalse(box.Buffer.HasSelection); CheckEqual(3, box.Buffer.Caret); } public void APress_AfterShiftIsReleased_DropsTheSelection() { TextBox box = BoxWithTheCaretAfterTheFirstLetter(); KeyboardManager keys = Focus(box); var tracker = new KeyTracker(); keys.KeyDown(tracker.KeyDown(KeyCode.ShiftLeft, KeyCode.None, isRepeat: false)); keys.KeyUp(tracker.KeyUp(KeyCode.ShiftLeft)); box.MouseDown(At(40), MouseButtonFlags.Left); CheckFalse(box.Buffer.HasSelection); CheckEqual(4, box.Buffer.Caret); } public void ARightPress_WhileExtending_DoesNothing() { TextBox box = BoxWithTheCaretAfterTheFirstLetter(); box.ExtendingSelection = true; box.MouseDown(At(40), MouseButtonFlags.Right); CheckEqual(1, box.Buffer.Caret); } } public class CursorAtTests : TestFixture { public void IsTheTextCursor() { var cursor = new TestCursor(); var box = NewBox(); box.TextCursor = cursor; Check(ReferenceEquals(cursor, box.CursorAt(At(5)))); } public void WithoutOne_IsNull() { CheckNull(NewBox().CursorAt(At(5))); } public void WhileDisabled_IsNull() { var box = NewBox(); box.TextCursor = new TestCursor(); box.Enabled = false; CheckNull(box.CursorAt(At(5))); } } public class MaterialTests : TestFixture { public void RoundTrips() { var box = NewBox(); var background = new SolidColorMaterial(); var active = new SolidColorMaterial(); var inactive = new SolidColorMaterial(); box.TextBoxMaterial = new TextBoxMaterial { Background = background, Text = null, Selection = active, InactiveSelection = inactive, CaretWidth = 3, }; TextBoxMaterial back = box.TextBoxMaterial; Check(ReferenceEquals(background, back.Background)); Check(ReferenceEquals(active, back.Selection)); Check(ReferenceEquals(inactive, back.InactiveSelection)); CheckNull(back.Text); CheckEqual((Scalar)3, back.CaretWidth); } public void TheLabelAlwaysShowsOneClippedLine() { var box = NewBox(); box.TextBoxMaterial = new TextBoxMaterial { Text = new TextStyle { Font = Font, Multiline = true, OverflowBehavior = TextOverflow.Ellipsis }, }; CheckEqual(1, box.Label.Style.MaxLines); CheckEqual(TextOverflow.Clip, box.Label.Style.OverflowBehavior); } public void ANewCaretWidth_ReachesTheCaret() { var box = NewBox("abc"); box.TextBoxMaterial = new TextBoxMaterial { Text = FlatMaterial.Text, Caret = FlatMaterial.Caret, CaretWidth = 4, }; CheckEqual((Scalar)4, box.CaretPanel.Bounds.Width); } public void MarginsInsetTheText() { var box = NewBox("abc"); box.TextBoxMaterial = new TextBoxMaterial { Text = new TextStyle { Font = Font, HorizontalMargin = 5, VerticalMargin = 2 }, CaretWidth = 1, }; CheckEqual(35, CaretX(box)); CheckEqual((Scalar)2, box.CaretPanel.Bounds.Top); } public void ABackground_InsetsTheLabel() { var box = NewBox("abc"); box.Bounds = Rect.FromPositionAndSize(Vector.Zero, new Vector(110, 30)); box.TextBoxMaterial = new TextBoxMaterial { Background = new Material { }, Text = FlatMaterial.Text, CaretWidth = 1, }; CheckEqual(30, CaretX(box) - box.Label.Bounds.Left); } public void ABackgroundSetOnItsOwn_ReplacesTheBackground() { var box = NewBox("abc"); var background = new SolidColorMaterial(); box.Material = background; Check(ReferenceEquals(background, box.TextBoxMaterial.Background)); } public void NoFont_StillTakesAMaterial() { var box = new TextBox(new TextBoxBehavior()); box.TextBoxMaterial = new TextBoxMaterial(); } } public class BehaviorTests : TestFixture { public void Set_RefreshesTheBox() { var box = NewBox("abc"); box.Behavior = new TextBoxBehavior { Bindings = EditBindings.Readline }; CheckEqual("abc", box.Label.Text.ToString()); } public void Null_Throws() { var box = NewBox(); CheckThrow(typeof(ArgumentNullException)); box.Behavior = null; } public void DefaultsToTheWindowsBindingsAndAHalfSecondBlink() { var behavior = new TextBoxBehavior(); Check(ReferenceEquals(EditBindings.Windows, behavior.Bindings)); CheckEqual(Duration.FromMilliseconds(530), behavior.BlinkInterval); } public void KeyChords_HoldTheBindingsChordsAndOneForEachTypingKeyAndEnter() { var behavior = new TextBoxBehavior(); foreach (EditBinding binding in behavior.Bindings.Physical) { Check(behavior.KeyChords.Contains(binding.Chord)); } foreach (EditBinding binding in behavior.Bindings.Layout) { Check(behavior.KeyChords.Contains(binding.Chord)); } } public void ChangingTheBindings_ChangesTheKeyChords() { var behavior = new TextBoxBehavior { Bindings = EditBindings.Readline }; foreach (EditBinding binding in EditBindings.Readline.Layout) { Check(behavior.KeyChords.Contains(binding.Chord)); } CheckFalse(behavior.KeyChords.Contains(EditBindings.Windows.Layout[0].Chord)); } public void ChangingTheBlink_KeepsTheKeyChords() { var behavior = new TextBoxBehavior(); TextBoxBehavior slower = behavior with { BlinkInterval = Duration.FromSeconds(2) }; Check(ReferenceEquals(behavior.KeyChords, slower.KeyChords)); } public void Types_IsTrueForATypingKeyAndFalseForOthers() { var behavior = new TextBoxBehavior(); var box = NewBox(behavior: behavior); KeyboardManager keys = Focus(box); Check(behavior.Types(Pressing(KeyCode.A), keys)); Check(behavior.Types(Pressing(KeyCode.Numpad7), keys)); CheckFalse(behavior.Types(Pressing(KeyCode.F1), keys)); CheckFalse(behavior.Types(Pressing(KeyCode.MainEnter), keys)); CheckFalse(behavior.Types(Pressing(KeyCode.ShiftLeft), keys)); } public void Enters_IsTrueForEitherEnterKeyAndFalseForOthers() { var behavior = new TextBoxBehavior(); var box = NewBox(behavior: behavior); KeyboardManager keys = Focus(box); Check(behavior.Enters(Pressing(KeyCode.MainEnter), keys)); Check(behavior.Enters(Pressing(KeyCode.NumpadEnter), keys)); CheckFalse(behavior.Enters(Pressing(KeyCode.A), keys)); } public void Types_IsFalseForAKeyThatIsOnlyHeldOrReleased() { var behavior = new TextBoxBehavior(); var box = NewBox(behavior: behavior); KeyboardManager keys = Focus(box); var tracker = new KeyTracker(); tracker.KeyDown(KeyCode.A, KeyCode.None, isRepeat: false); CheckFalse(behavior.Types(tracker.KeyDown(KeyCode.F1, KeyCode.None, isRepeat: false), keys)); CheckFalse(behavior.Types(tracker.KeyUp(KeyCode.A), keys)); } public void NullBindings_Throws() { CheckThrow(typeof(ArgumentNullException)); new TextBoxBehavior { Bindings = null }; } public void NegativeBlinkInterval_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new TextBoxBehavior { BlinkInterval = Duration.FromSeconds(-1) }; } public void AutoscrollRateDefaultsToTwentyCharactersASecond() { CheckEqual(20.0, new TextBoxBehavior().AutoscrollCharactersPerSecond); } public void NegativeAutoscrollRate_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new TextBoxBehavior { AutoscrollCharactersPerSecond = -1 }; } public void NotANumberAutoscrollRate_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new TextBoxBehavior { AutoscrollCharactersPerSecond = double.NaN }; } public void InfiniteAutoscrollRate_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new TextBoxBehavior { AutoscrollCharactersPerSecond = double.PositiveInfinity }; } public void ZeroAutoscrollRate_IsAllowed() { var behavior = new TextBoxBehavior { AutoscrollCharactersPerSecond = 0 }; CheckEqual(0.0, behavior.AutoscrollCharactersPerSecond); } public void InfiniteBlinkInterval_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new TextBoxBehavior { BlinkInterval = Duration.Forever }; } } } }