| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- using UnitTests;
- namespace UnitTests_Parallelizable.ViewsTests;
- /// <summary>
- /// Tests for TextView navigation, tabs, and cursor positioning.
- /// These replace the old non-parallelizable tests that had hard-coded viewport dimensions.
- /// </summary>
- public class TextViewNavigationTests : FakeDriverBase
- {
- [Fact]
- public void Tab_And_BackTab_Navigation_Without_Text ()
- {
- var textView = new TextView
- {
- Width = 30,
- Height = 10,
- Text = ""
- };
- textView.BeginInit ();
- textView.EndInit ();
- // Add 100 tabs
- for (var i = 0; i < 100; i++)
- {
- textView.Text += "\t";
- }
- // Move to end
- textView.MoveEnd ();
- Assert.Equal (new Point (100, 0), textView.CursorPosition);
- // Test BackTab (Shift+Tab) navigation backwards
- for (var i = 99; i >= 0; i--)
- {
- Assert.True (textView.NewKeyDownEvent (Key.Tab.WithShift));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- // Test Tab navigation forwards
- for (var i = 1; i <= 100; i++)
- {
- Assert.True (textView.NewKeyDownEvent (Key.Tab));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- }
- [Fact]
- public void Tab_And_BackTab_Navigation_With_Text ()
- {
- var textView = new TextView
- {
- Width = 30,
- Height = 10,
- Text = "TAB to jump between text fields."
- };
- textView.BeginInit ();
- textView.EndInit ();
- Assert.Equal (new Point (0, 0), textView.CursorPosition);
- // Navigate forward with Tab
- for (var i = 1; i <= 100; i++)
- {
- Assert.True (textView.NewKeyDownEvent (Key.Tab));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- // Navigate backward with BackTab
- for (var i = 99; i >= 0; i--)
- {
- Assert.True (textView.NewKeyDownEvent (Key.Tab.WithShift));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- }
- [Fact]
- public void Tab_With_CursorLeft_And_CursorRight_Without_Text ()
- {
- var textView = new TextView
- {
- Width = 30,
- Height = 10,
- Text = ""
- };
- textView.BeginInit ();
- textView.EndInit ();
- // Navigate forward with Tab
- for (var i = 1; i <= 100; i++)
- {
- Assert.True (textView.NewKeyDownEvent (Key.Tab));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- // Navigate backward with CursorLeft
- for (var i = 99; i >= 0; i--)
- {
- Assert.True (textView.NewKeyDownEvent (Key.CursorLeft));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- // Navigate forward with CursorRight
- for (var i = 1; i <= 100; i++)
- {
- Assert.True (textView.NewKeyDownEvent (Key.CursorRight));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- }
- [Fact]
- public void Tab_With_CursorLeft_And_CursorRight_With_Text ()
- {
- var textView = new TextView
- {
- Width = 30,
- Height = 10,
- Text = "TAB to jump between text fields."
- };
- textView.BeginInit ();
- textView.EndInit ();
- Assert.Equal (32, textView.Text.Length);
- Assert.Equal (new Point (0, 0), textView.CursorPosition);
- // Navigate forward with Tab
- for (var i = 1; i <= 100; i++)
- {
- Assert.True (textView.NewKeyDownEvent (Key.Tab));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- // Navigate backward with CursorLeft
- for (var i = 99; i >= 0; i--)
- {
- Assert.True (textView.NewKeyDownEvent (Key.CursorLeft));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- // Navigate forward with CursorRight
- for (var i = 1; i <= 100; i++)
- {
- Assert.True (textView.NewKeyDownEvent (Key.CursorRight));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- }
- [Fact]
- public void Tab_With_Home_End_And_BackTab ()
- {
- var textView = new TextView
- {
- Width = 30,
- Height = 10,
- Text = "TAB to jump between text fields."
- };
- textView.BeginInit ();
- textView.EndInit ();
- Assert.Equal (32, textView.Text.Length);
- Assert.Equal (new Point (0, 0), textView.CursorPosition);
- // Navigate forward with Tab to column 100
- for (var i = 1; i <= 100; i++)
- {
- Assert.True (textView.NewKeyDownEvent (Key.Tab));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- // Test Length increased due to tabs
- Assert.Equal (132, textView.Text.Length);
- // Press Home to go to beginning
- Assert.True (textView.NewKeyDownEvent (Key.Home));
- Assert.Equal (new Point (0, 0), textView.CursorPosition);
- // Press End to go to end
- Assert.True (textView.NewKeyDownEvent (Key.End));
- Assert.Equal (132, textView.Text.Length);
- Assert.Equal (new Point (132, 0), textView.CursorPosition);
- // Find the position just before the last tab
- string txt = textView.Text;
- var col = txt.Length;
-
- // Find the last tab position
- while (col > 1 && txt [col - 1] != '\t')
- {
- col--;
-
- // Safety check to prevent infinite loop
- if (col == 0)
- {
- break;
- }
- }
-
- // Set cursor to that position
- textView.CursorPosition = new Point (col, 0);
- // Navigate backward with BackTab (removes tabs, going back to original text)
- while (col > 0)
- {
- col--;
- Assert.True (textView.NewKeyDownEvent (Key.Tab.WithShift));
- Assert.Equal (new Point (col, 0), textView.CursorPosition);
- }
-
- // Should be back at the original text
- Assert.Equal ("TAB to jump between text fields.", textView.Text);
- Assert.Equal (32, textView.Text.Length);
- }
- [Fact]
- public void BackTab_Then_Tab_Navigation ()
- {
- var textView = new TextView
- {
- Width = 30,
- Height = 10,
- Text = ""
- };
- textView.BeginInit ();
- textView.EndInit ();
- // Add 100 tabs at end
- for (var i = 0; i < 100; i++)
- {
- textView.Text += "\t";
- }
- textView.MoveEnd ();
- Assert.Equal (new Point (100, 0), textView.CursorPosition);
- // Navigate backward with BackTab
- for (var i = 99; i >= 0; i--)
- {
- Assert.True (textView.NewKeyDownEvent (Key.Tab.WithShift));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- // Navigate forward with Tab
- for (var i = 1; i <= 100; i++)
- {
- Assert.True (textView.NewKeyDownEvent (Key.Tab));
- Assert.Equal (new Point (i, 0), textView.CursorPosition);
- }
- }
- [Fact]
- public void TabWidth_Setting_To_Zero_Keeps_AllowsTab ()
- {
- var textView = new TextView
- {
- Width = 30,
- Height = 10,
- Text = "TAB to jump between text fields."
- };
- textView.BeginInit ();
- textView.EndInit ();
- // Verify initial state
- Assert.Equal (4, textView.TabWidth);
- Assert.True (textView.AllowsTab);
- Assert.True (textView.AllowsReturn);
- Assert.True (textView.Multiline);
- // Set TabWidth to -1 (should clamp to 0)
- textView.TabWidth = -1;
- Assert.Equal (0, textView.TabWidth);
- Assert.True (textView.AllowsTab);
- Assert.True (textView.AllowsReturn);
- Assert.True (textView.Multiline);
- // Insert a tab
- Assert.True (textView.NewKeyDownEvent (Key.Tab));
- Assert.Equal ("\tTAB to jump between text fields.", textView.Text);
- // Change TabWidth back to 4
- textView.TabWidth = 4;
- Assert.Equal (4, textView.TabWidth);
- // Remove the tab with BackTab
- Assert.True (textView.NewKeyDownEvent (Key.Tab.WithShift));
- Assert.Equal ("TAB to jump between text fields.", textView.Text);
- }
- [Fact]
- public void KeyBindings_Command_Navigation ()
- {
- var text = "This is the first line.\nThis is the second line.\nThis is the third line.";
- var textView = new TextView
- {
- Width = 10,
- Height = 2,
- Text = text
- };
- textView.BeginInit ();
- textView.EndInit ();
- Assert.Equal (
- $"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}This is the third line.",
- textView.Text
- );
- Assert.Equal (3, textView.Lines);
- Assert.Equal (Point.Empty, textView.CursorPosition);
- Assert.False (textView.ReadOnly);
- Assert.True (textView.CanFocus);
- Assert.False (textView.IsSelecting);
- // Test that CursorLeft doesn't move when at beginning
- textView.CanFocus = false;
- Assert.True (textView.NewKeyDownEvent (Key.CursorLeft));
- Assert.False (textView.IsSelecting);
-
- textView.CanFocus = true;
- Assert.False (textView.NewKeyDownEvent (Key.CursorLeft));
- Assert.False (textView.IsSelecting);
-
- // Move right
- Assert.True (textView.NewKeyDownEvent (Key.CursorRight));
- Assert.Equal (new Point (1, 0), textView.CursorPosition);
- Assert.False (textView.IsSelecting);
-
- // Move to end of document
- Assert.True (textView.NewKeyDownEvent (Key.End.WithCtrl));
- Assert.Equal (2, textView.CurrentRow);
- Assert.Equal (23, textView.CurrentColumn);
- Assert.Equal (textView.CurrentColumn, textView.GetCurrentLine ().Count);
- Assert.Equal (new Point (23, 2), textView.CursorPosition);
- Assert.False (textView.IsSelecting);
-
- // Try to move right (should fail, at end)
- Assert.False (textView.NewKeyDownEvent (Key.CursorRight));
- Assert.False (textView.IsSelecting);
-
- // Type a character
- Assert.True (textView.NewKeyDownEvent (Key.F.WithShift));
- Assert.Equal (
- $"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}This is the third line.F",
- textView.Text
- );
- Assert.Equal (new Point (24, 2), textView.CursorPosition);
- Assert.False (textView.IsSelecting);
-
- // Undo
- Assert.True (textView.NewKeyDownEvent (Key.Z.WithCtrl));
- Assert.Equal (
- $"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}This is the third line.",
- textView.Text
- );
- Assert.Equal (new Point (23, 2), textView.CursorPosition);
- Assert.False (textView.IsSelecting);
-
- // Redo
- Assert.True (textView.NewKeyDownEvent (Key.R.WithCtrl));
- Assert.Equal (
- $"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}This is the third line.F",
- textView.Text
- );
- Assert.Equal (new Point (24, 2), textView.CursorPosition);
- Assert.False (textView.IsSelecting);
- }
- [Fact]
- public void UnwrappedCursorPosition_Event_Fires_Correctly ()
- {
- Point unwrappedPosition = Point.Empty;
-
- var textView = new TextView
- {
- Width = 25,
- Height = 25,
- Text = "This is the first line.\nThis is the second line.\n"
- };
-
- textView.UnwrappedCursorPosition += (s, e) => { unwrappedPosition = e; };
-
- textView.BeginInit ();
- textView.EndInit ();
- // Initially no word wrap
- Assert.False (textView.WordWrap);
- Assert.Equal (Point.Empty, textView.CursorPosition);
- Assert.Equal (Point.Empty, unwrappedPosition);
- // Enable word wrap and move cursor
- textView.WordWrap = true;
- textView.CursorPosition = new Point (12, 0);
- Assert.Equal (new Point (12, 0), textView.CursorPosition);
- Assert.Equal (new Point (12, 0), unwrappedPosition);
- // Move right and verify unwrapped position updates
- var currentUnwrapped = unwrappedPosition;
- Assert.True (textView.NewKeyDownEvent (Key.CursorRight));
- // The unwrapped position should have updated
- Assert.True (unwrappedPosition.X >= currentUnwrapped.X);
-
- // Move several more times to verify tracking continues to work
- for (int i = 0; i < 5; i++)
- {
- Assert.True (textView.NewKeyDownEvent (Key.CursorRight));
- }
-
- // Unwrapped position should track the actual position in the text
- Assert.True (unwrappedPosition.X > 12);
- }
- [Fact]
- public void Horizontal_Scrolling_Adjusts_LeftColumn ()
- {
- var textView = new TextView
- {
- Width = 20,
- Height = 5,
- Text = "This is a very long line that will require horizontal scrolling to see all of it",
- WordWrap = false
- };
- textView.BeginInit ();
- textView.EndInit ();
- // Initially at the start
- Assert.Equal (0, textView.LeftColumn);
- Assert.Equal (new Point (0, 0), textView.CursorPosition);
- // Move to the end of the line
- textView.MoveEnd ();
-
- // LeftColumn should have adjusted to show the cursor
- Assert.True (textView.LeftColumn > 0);
- Assert.Equal (textView.Text.Length, textView.CurrentColumn);
- // Move back to the start
- textView.MoveHome ();
-
- // LeftColumn should be back to 0
- Assert.Equal (0, textView.LeftColumn);
- Assert.Equal (0, textView.CurrentColumn);
- }
- [Fact]
- public void Vertical_Scrolling_Adjusts_TopRow ()
- {
- var lines = string.Join ("\n", Enumerable.Range (1, 100).Select (i => $"Line {i}"));
- var textView = new TextView
- {
- Width = 20,
- Height = 5,
- Text = lines
- };
- textView.BeginInit ();
- textView.EndInit ();
- // Initially at the top
- Assert.Equal (0, textView.TopRow);
- Assert.Equal (new Point (0, 0), textView.CursorPosition);
- // Move down many lines
- for (var i = 0; i < 50; i++)
- {
- textView.NewKeyDownEvent (Key.CursorDown);
- }
- // TopRow should have adjusted to show the cursor
- Assert.True (textView.TopRow > 0);
- Assert.Equal (50, textView.CurrentRow);
- // Move back to the top
- textView.NewKeyDownEvent (Key.Home.WithCtrl);
-
- // TopRow should be back to 0
- Assert.Equal (0, textView.TopRow);
- Assert.Equal (0, textView.CurrentRow);
- }
- }
|