From b200763a3f73a89e0d4eba606170ffccb11f8af1 Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 23 Jul 2021 23:02:22 +0100 Subject: [PATCH] Fixes #1387. Allowing the UnitTests project to test internal keywords. --- Terminal.Gui/Terminal.Gui.csproj | 3 ++ Terminal.Gui/Views/ScrollBarView.cs | 4 +- Terminal.Gui/Views/TextField.cs | 2 +- Terminal.Gui/Views/TextView.cs | 51 +++++++++++++------ UnitTests/ApplicationTests.cs | 15 ++++++ UnitTests/ConsoleDriverTests.cs | 7 +++ UnitTests/DimTests.cs | 25 ++++++++- UnitTests/MainLoopTests.cs | 39 ++++++++++++++- UnitTests/PosTests.cs | 33 +++++++++++- UnitTests/ScrollBarViewTests.cs | 45 +++++++++++++++++ UnitTests/TextFieldTests.cs | 12 +++++ UnitTests/TextFormatterTests.cs | 10 ++++ UnitTests/TextViewTests.cs | 78 +++++++++++++++++++++++++++++ UnitTests/ViewTests.cs | 42 ++++++++++++++++ 14 files changed, 344 insertions(+), 22 deletions(-) diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index 41a679076..7eecf711c 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -15,6 +15,9 @@ runtime; build; native; contentfiles; analyzers + + <_Parameter1>UnitTests + true diff --git a/Terminal.Gui/Views/ScrollBarView.cs b/Terminal.Gui/Views/ScrollBarView.cs index c89070783..ed08c607a 100644 --- a/Terminal.Gui/Views/ScrollBarView.cs +++ b/Terminal.Gui/Views/ScrollBarView.cs @@ -645,7 +645,7 @@ namespace Terminal.Gui { internal bool CanScroll (int n, out int max, bool isVertical = false) { - if (Host == null) { + if (Host?.Bounds.IsEmpty != false) { max = 0; return false; } @@ -660,7 +660,7 @@ namespace Terminal.Gui { int GetBarsize (bool isVertical) { - if (Host == null) { + if (Host?.Bounds.IsEmpty != false) { return 0; } return isVertical ? diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs index 4b7e78b56..fb6d5a7ab 100644 --- a/Terminal.Gui/Views/TextField.cs +++ b/Terminal.Gui/Views/TextField.cs @@ -141,7 +141,7 @@ namespace Terminal.Gui { if (oldText == value) return; - var newText = OnTextChanging (value.Split ("\n") [0]); + var newText = OnTextChanging (value.Replace ("\t", "").Split ("\n") [0]); if (newText.Cancel) { if (point > text.Count) { point = text.Count; diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs index 74b1b3a83..b6084e4b9 100644 --- a/Terminal.Gui/Views/TextView.cs +++ b/Terminal.Gui/Views/TextView.cs @@ -348,7 +348,8 @@ namespace Terminal.Gui { if (toFind.found) { toFind.currentPointToFind.X++; } - var foundPos = GetFoundPreviousTextPoint (text, toFind.currentPointToFind.Y, matchCase, matchWholeWord, toFind.currentPointToFind); + var linesCount = toFind.currentPointToFind.IsEmpty ? lines.Count - 1 : toFind.currentPointToFind.Y; + var foundPos = GetFoundPreviousTextPoint (text, linesCount, matchCase, matchWholeWord, toFind.currentPointToFind); if (!foundPos.found && toFind.currentPointToFind != toFind.startPointToFind) { foundPos = GetFoundPreviousTextPoint (text, lines.Count - 1, matchCase, matchWholeWord, new Point (lines [lines.Count - 1].Count, lines.Count)); @@ -365,23 +366,41 @@ namespace Terminal.Gui { for (int i = 0; i < lines.Count; i++) { var x = lines [i]; + var txt = GetText (x); + var matchText = !matchCase ? text.ToUpper ().ToString () : text.ToString (); + var col = txt.IndexOf (matchText); + while (col > -1) { + if (matchWholeWord && !MatchWholeWord (txt, matchText, col)) { + if (col + 1 > txt.Length) { + break; + } + col = txt.IndexOf (matchText, col + 1); + continue; + } + if (col > -1) { + if (!found) { + found = true; + } + lines [i] = ReplaceText (x, textToReplace, matchText, col).ToRuneList (); + x = lines [i]; + txt = GetText (x); + pos = new Point (col, i); + col += (textToReplace.Length - matchText.Length); + } + if (col + 1 > txt.Length) { + break; + } + col = txt.IndexOf (matchText, col + 1); + } + } + + string GetText (List x) + { var txt = ustring.Make (x).ToString (); if (!matchCase) { txt = txt.ToUpper (); } - var matchText = !matchCase ? text.ToUpper ().ToString () : text.ToString (); - var col = txt.IndexOf (matchText); - if (col > -1 && matchWholeWord && !MatchWholeWord (txt, matchText, col)) { - continue; - } - if (col > -1) { - if (!found) { - found = true; - } - pos = new Point (col, i); - lines [i] = ReplaceText (x, textToReplace, matchText, col).ToRuneList (); - i--; - } + return txt; } return (pos, found); @@ -453,11 +472,11 @@ namespace Terminal.Gui { start.X = Math.Max (x.Count - 1, 0); } var matchText = !matchCase ? text.ToUpper ().ToString () : text.ToString (); - var col = txt.LastIndexOf (matchText, start.X); + var col = txt.LastIndexOf (matchText, toFind.found ? start.X - 1 : start.X); if (col > -1 && matchWholeWord && !MatchWholeWord (txt, matchText, col)) { continue; } - if (col > -1 && ((i == linesCount && col <= start.X) + if (col > -1 && ((i <= linesCount && col <= start.X) || i < start.Y) && txt.Contains (matchText)) { return (new Point (col, i), true); diff --git a/UnitTests/ApplicationTests.cs b/UnitTests/ApplicationTests.cs index 59406f0f1..4f8d99caf 100644 --- a/UnitTests/ApplicationTests.cs +++ b/UnitTests/ApplicationTests.cs @@ -1127,5 +1127,20 @@ namespace Terminal.Gui.Core { Assert.Null (Application.Top); } + + [Fact] + [AutoInitShutdown] + public void Internal_Tests () + { + Assert.True (Application._initialized); + Assert.NotNull (Application.Top); + var rs = Application.Begin (Application.Top); + Assert.Equal (Application.Top, rs.Toplevel); + Assert.Null (Application.mouseGrabView); + Assert.Null (Application.wantContinuousButtonPressedView); + Assert.False (Application.DebugDrawBounds); + Assert.False (Application.ShowChild (Application.Top)); + Application.End (Application.Top); + } } } diff --git a/UnitTests/ConsoleDriverTests.cs b/UnitTests/ConsoleDriverTests.cs index f2429e11a..cf03f98cb 100644 --- a/UnitTests/ConsoleDriverTests.cs +++ b/UnitTests/ConsoleDriverTests.cs @@ -413,5 +413,12 @@ namespace Terminal.Gui.ConsoleDrivers { Application.Shutdown (); } + + [Fact] + public void Internal_Tests () + { + var cs = new ColorScheme (); + Assert.Equal ("", cs.caller); + } } } diff --git a/UnitTests/DimTests.cs b/UnitTests/DimTests.cs index e14354c39..e0a81d550 100644 --- a/UnitTests/DimTests.cs +++ b/UnitTests/DimTests.cs @@ -8,7 +8,7 @@ using System.Threading; using Terminal.Gui; using Xunit; -// Alais Console to MockConsole so we don't accidentally use Console +// Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; namespace Terminal.Gui.Core { @@ -699,7 +699,30 @@ namespace Terminal.Gui.Core { // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); + } + [Fact] + public void Internal_Tests () + { + var dimFactor = new Dim.DimFactor (0.10F); + Assert.Equal (10, dimFactor.Anchor (100)); + + var dimAbsolute = new Dim.DimAbsolute (10); + Assert.Equal (10, dimAbsolute.Anchor (0)); + + var dimFill = new Dim.DimFill (1); + Assert.Equal (99, dimFill.Anchor (100)); + + var dimCombine = new Dim.DimCombine (true, dimFactor, dimAbsolute); + Assert.Equal (dimCombine.left, dimFactor); + Assert.Equal (dimCombine.right, dimAbsolute); + Assert.Equal (20, dimCombine.Anchor (100)); + + var view = new View (new Rect (20, 10, 20, 1)); + var dimViewHeight = new Dim.DimView (view, 0); + Assert.Equal (1, dimViewHeight.Anchor (0)); + var dimViewWidth = new Dim.DimView (view, 1); + Assert.Equal (20, dimViewWidth.Anchor (0)); } } } diff --git a/UnitTests/MainLoopTests.cs b/UnitTests/MainLoopTests.cs index c85409021..8d4330d11 100644 --- a/UnitTests/MainLoopTests.cs +++ b/UnitTests/MainLoopTests.cs @@ -10,7 +10,7 @@ using Terminal.Gui; using Xunit; using Xunit.Sdk; -// Alais Console to MockConsole so we don't accidentally use Console +// Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; namespace Terminal.Gui.Core { @@ -463,6 +463,43 @@ namespace Terminal.Gui.Core { Assert.Equal (1, actionCalled); } + [Fact] + public void Internal_Tests () + { + var testMainloop = new TestMainloop (); + var mainloop = new MainLoop (testMainloop); + Assert.Empty (mainloop.timeouts); + Assert.Empty (mainloop.idleHandlers); + Assert.NotNull (new MainLoop.Timeout () { + Span = new TimeSpan (), + Callback = (_) => true + }); + } + + private class TestMainloop : IMainLoopDriver { + private MainLoop mainLoop; + + public bool EventsPending (bool wait) + { + throw new NotImplementedException (); + } + + public void MainIteration () + { + throw new NotImplementedException (); + } + + public void Setup (MainLoop mainLoop) + { + this.mainLoop = mainLoop; + } + + public void Wakeup () + { + throw new NotImplementedException (); + } + } + // TODO: EventsPending tests // - wait = true // - wait = false diff --git a/UnitTests/PosTests.cs b/UnitTests/PosTests.cs index 77e1b382e..aca856084 100644 --- a/UnitTests/PosTests.cs +++ b/UnitTests/PosTests.cs @@ -7,7 +7,7 @@ using System.Linq; using Terminal.Gui; using Xunit; -// Alais Console to MockConsole so we don't accidentally use Console +// Alias Console to MockConsole so we don't accidentally use Console using Console = Terminal.Gui.FakeConsole; namespace Terminal.Gui.Core { @@ -652,5 +652,36 @@ namespace Terminal.Gui.Core { // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } + + [Fact] + public void Internal_Tests () + { + var posFactor = new Pos.PosFactor (0.10F); + Assert.Equal (10, posFactor.Anchor (100)); + + var posAnchorEnd = new Pos.PosAnchorEnd (1); + Assert.Equal (99, posAnchorEnd.Anchor (100)); + + var posCenter = new Pos.PosCenter (); + Assert.Equal (50, posCenter.Anchor (100)); + + var posAbsolute = new Pos.PosAbsolute (10); + Assert.Equal (10, posAbsolute.Anchor (0)); + + var posCombine = new Pos.PosCombine (true, posFactor, posAbsolute); + Assert.Equal (posCombine.left, posFactor); + Assert.Equal (posCombine.right, posAbsolute); + Assert.Equal (20, posCombine.Anchor (100)); + + var view = new View (new Rect (20, 10, 20, 1)); + var posViewX = new Pos.PosView (view, 0); + Assert.Equal (20, posViewX.Anchor (0)); + var posViewY = new Pos.PosView (view, 1); + Assert.Equal (10, posViewY.Anchor (0)); + var posRight = new Pos.PosView (view, 2); + Assert.Equal (40, posRight.Anchor (0)); + var posViewBottom = new Pos.PosView (view, 3); + Assert.Equal (11, posViewBottom.Anchor (0)); + } } } diff --git a/UnitTests/ScrollBarViewTests.cs b/UnitTests/ScrollBarViewTests.cs index 382847a04..388f5de88 100644 --- a/UnitTests/ScrollBarViewTests.cs +++ b/UnitTests/ScrollBarViewTests.cs @@ -590,5 +590,50 @@ namespace Terminal.Gui.Views { Assert.Null (exception); } + + [Fact] + [AutoInitShutdown] + public void Internal_Tests () + { + var top = Application.Top; + Assert.Equal (new Rect (0, 0, 80, 25), top.Bounds); + var view = new View () { Width = Dim.Fill (), Height = Dim.Fill () }; + top.Add (view); + var sbv = new ScrollBarView (view, true); + top.Add (sbv); + Assert.Equal (view, sbv.Host); + sbv.Size = 40; + sbv.Position = 0; + sbv.OtherScrollBarView.Size = 100; + sbv.OtherScrollBarView.Position = 0; + // Host bounds is empty. + Assert.False (sbv.CanScroll (10, out int max, sbv.IsVertical)); + Assert.Equal (0, max); + Assert.False (sbv.OtherScrollBarView.CanScroll (10, out max, sbv.OtherScrollBarView.IsVertical)); + Assert.Equal (0, max); + // They are visible but are not drawn. + Assert.True (sbv.Visible); + Assert.True (sbv.OtherScrollBarView.Visible); + top.LayoutSubviews (); + // Now the host bounds is not empty. + Assert.True (sbv.CanScroll (10, out max, sbv.IsVertical)); + Assert.Equal (10, max); + Assert.True (sbv.OtherScrollBarView.CanScroll (10, out max, sbv.OtherScrollBarView.IsVertical)); + Assert.Equal (10, max); + Assert.True (sbv.CanScroll (50, out max, sbv.IsVertical)); + Assert.Equal (17, max); // 17+23=40 + Assert.True (sbv.OtherScrollBarView.CanScroll (150, out max, sbv.OtherScrollBarView.IsVertical)); + Assert.Equal (22, max); // 22+78=100 + Assert.True (sbv.Visible); + Assert.True (sbv.OtherScrollBarView.Visible); + sbv.KeepContentAlwaysInViewport = false; + sbv.OtherScrollBarView.KeepContentAlwaysInViewport = false; + Assert.True (sbv.CanScroll (50, out max, sbv.IsVertical)); + Assert.Equal (40, max); + Assert.True (sbv.OtherScrollBarView.CanScroll (150, out max, sbv.OtherScrollBarView.IsVertical)); + Assert.Equal (100, max); + Assert.True (sbv.Visible); + Assert.True (sbv.OtherScrollBarView.Visible); + } } } diff --git a/UnitTests/TextFieldTests.cs b/UnitTests/TextFieldTests.cs index 9b0453411..95054eb2f 100644 --- a/UnitTests/TextFieldTests.cs +++ b/UnitTests/TextFieldTests.cs @@ -773,5 +773,17 @@ namespace Terminal.Gui.Views { Assert.Equal ("", tf.Text); } + + [Fact] + [InitShutdown] + public void Text_Replaces_Tabs_With_Empty_String () + { + _textField.Text = "\t\tTAB to jump between text fields."; + Assert.Equal ("TAB to jump between text fields.", _textField.Text); + _textField.Text = ""; + Clipboard.Contents = "\t\tTAB to jump between text fields."; + _textField.Paste (); + Assert.Equal ("TAB to jump between text fields.", _textField.Text); + } } } diff --git a/UnitTests/TextFormatterTests.cs b/UnitTests/TextFormatterTests.cs index 3ec3b14d0..a06cd3b1c 100644 --- a/UnitTests/TextFormatterTests.cs +++ b/UnitTests/TextFormatterTests.cs @@ -2568,5 +2568,15 @@ namespace Terminal.Gui.Core { // Shutdown must be called to safely clean up Application if Init has been called Application.Shutdown (); } + + [Fact] + public void Internal_Tests () + { + var tf = new TextFormatter (); + Assert.Equal (Key.Null, tf.HotKey); + tf.HotKey = Key.CtrlMask | Key.Q; + Assert.Equal (Key.CtrlMask | Key.Q, tf.HotKey); + + } } } \ No newline at end of file diff --git a/UnitTests/TextViewTests.cs b/UnitTests/TextViewTests.cs index 2aa6b97f6..359338791 100644 --- a/UnitTests/TextViewTests.cs +++ b/UnitTests/TextViewTests.cs @@ -1942,5 +1942,83 @@ line. GraphViewTests.AssertDriverContentsAre (expected, output); } + + [Fact] + public void Internal_Tests () + { + var txt = "This is a text."; + var txtRunes = TextModel.ToRunes (txt); + Assert.Equal (txt.Length, txtRunes.Count); + Assert.Equal ('T', txtRunes [0]); + Assert.Equal ('h', txtRunes [1]); + Assert.Equal ('i', txtRunes [2]); + Assert.Equal ('s', txtRunes [3]); + Assert.Equal (' ', txtRunes [4]); + Assert.Equal ('i', txtRunes [5]); + Assert.Equal ('s', txtRunes [6]); + Assert.Equal (' ', txtRunes [7]); + Assert.Equal ('a', txtRunes [8]); + Assert.Equal (' ', txtRunes [9]); + Assert.Equal ('t', txtRunes [10]); + Assert.Equal ('e', txtRunes [11]); + Assert.Equal ('x', txtRunes [12]); + Assert.Equal ('t', txtRunes [13]); + Assert.Equal ('.', txtRunes [^1]); + + int col = 0; + Assert.True (TextModel.SetCol (ref col, 80, 79)); + Assert.False (TextModel.SetCol (ref col, 80, 80)); + + var start = 0; + var x = 8; + Assert.Equal (8, TextModel.GetColFromX (txtRunes, start, x)); + Assert.Equal ('a', txtRunes [start + x]); + start = 1; + x = 7; + Assert.Equal (7, TextModel.GetColFromX (txtRunes, start, x)); + Assert.Equal ('a', txtRunes [start + x]); + + Assert.Equal ((15, 15), TextModel.DisplaySize (txtRunes)); + Assert.Equal ((6, 6), TextModel.DisplaySize (txtRunes, 1, 7)); + + Assert.Equal (0, TextModel.CalculateLeftColumn (txtRunes, 0, 7, 8)); + Assert.Equal (1, TextModel.CalculateLeftColumn (txtRunes, 0, 8, 8)); + Assert.Equal (2, TextModel.CalculateLeftColumn (txtRunes, 0, 9, 8)); + + var tm = new TextModel (); + tm.AddLine (0, TextModel.ToRunes ("This is first line.")); + tm.AddLine (1, TextModel.ToRunes ("This is last line.")); + Assert.Equal ((new Point (2, 0), true), tm.FindNextText ("is", out bool gaveFullTurn)); + Assert.False (gaveFullTurn); + Assert.Equal ((new Point (5, 0), true), tm.FindNextText ("is", out gaveFullTurn)); + Assert.False (gaveFullTurn); + Assert.Equal ((new Point (2, 1), true), tm.FindNextText ("is", out gaveFullTurn)); + Assert.False (gaveFullTurn); + Assert.Equal ((new Point (5, 1), true), tm.FindNextText ("is", out gaveFullTurn)); + Assert.False (gaveFullTurn); + Assert.Equal ((new Point (2, 0), true), tm.FindNextText ("is", out gaveFullTurn)); + Assert.True (gaveFullTurn); + tm.ResetContinuousFind (new Point (0, 0)); + Assert.Equal ((new Point (5, 1), true), tm.FindPreviousText ("is", out gaveFullTurn)); + Assert.False (gaveFullTurn); + Assert.Equal ((new Point (2, 1), true), tm.FindPreviousText ("is", out gaveFullTurn)); + Assert.False (gaveFullTurn); + Assert.Equal ((new Point (5, 0), true), tm.FindPreviousText ("is", out gaveFullTurn)); + Assert.False (gaveFullTurn); + Assert.Equal ((new Point (2, 0), true), tm.FindPreviousText ("is", out gaveFullTurn)); + Assert.False (gaveFullTurn); + Assert.Equal ((new Point (5, 1), true), tm.FindPreviousText ("is", out gaveFullTurn)); + Assert.True (gaveFullTurn); + + Assert.Equal ((new Point (9, 1), true), tm.ReplaceAllText ("is", false, false, "really")); + Assert.Equal (TextModel.ToRunes ("Threally really first line."), tm.GetLine (0)); + Assert.Equal (TextModel.ToRunes ("Threally really last line."), tm.GetLine (1)); + tm = new TextModel (); + tm.AddLine (0, TextModel.ToRunes ("This is first line.")); + tm.AddLine (1, TextModel.ToRunes ("This is last line.")); + Assert.Equal ((new Point (5, 1), true), tm.ReplaceAllText ("is", false, true, "really")); + Assert.Equal (TextModel.ToRunes ("This really first line."), tm.GetLine (0)); + Assert.Equal (TextModel.ToRunes ("This really last line."), tm.GetLine (1)); + } } } diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs index cd4b6a52f..7b73705f8 100644 --- a/UnitTests/ViewTests.cs +++ b/UnitTests/ViewTests.cs @@ -1370,5 +1370,47 @@ namespace Terminal.Gui.Views { Application.Shutdown (); } } + + [Fact] + [AutoInitShutdown] + public void Internal_Tests () + { + Assert.Equal (new [] { View.Direction.Forward, View.Direction.Backward }, + Enum.GetValues (typeof (View.Direction))); + + var rect = new Rect (1, 1, 10, 1); + var view = new View (rect); + var top = Application.Top; + top.Add (view); + Assert.Equal (View.Direction.Forward, view.FocusDirection); + view.FocusDirection = View.Direction.Backward; + Assert.Equal (View.Direction.Backward, view.FocusDirection); + Assert.Empty (view.InternalSubviews); + Assert.Equal (new Rect (new Point (0, 0), rect.Size), view.NeedDisplay); + Assert.True (view.LayoutNeeded); + Assert.False (view.ChildNeedsDisplay); + Assert.False (view.addingView); + view.addingView = true; + Assert.True (view.addingView); + view.ViewToScreen (0, 0, out int rcol, out int rrow); + Assert.Equal (1, rcol); + Assert.Equal (1, rrow); + Assert.Equal (rect, view.ViewToScreen (view.Bounds)); + Assert.Equal (top.Bounds, view.ScreenClip (top.Bounds)); + view.Width = Dim.Fill (); + view.Height = Dim.Fill (); + Assert.Equal (10, view.Bounds.Width); + Assert.Equal (1, view.Bounds.Height); + view.SetRelativeLayout (top.Bounds); + Assert.Equal (79, view.Bounds.Width); + Assert.Equal (24, view.Bounds.Height); + bool layoutStarted = false; + view.LayoutStarted += (_) => { layoutStarted = true; }; + view.OnLayoutStarted (null); + Assert.True (layoutStarted); + view.LayoutComplete += (_) => { layoutStarted = false; }; + view.OnLayoutComplete (null); + Assert.False (layoutStarted); + } } }