Skip to content

Commit ee8f9a8

Browse files
tznindBDisp
andauthored
Fixes #4076 cursor text field (#4077)
* Add test for TextField cursor position * Add comment and one more assert * Fix cursor position at the end * Remove unused local field --------- Co-authored-by: BDisp <bd.bdisp@gmail.com>
1 parent e0de73a commit ee8f9a8

File tree

6 files changed

+97
-5
lines changed

6 files changed

+97
-5
lines changed

Terminal.Gui/FileServices/FileDialogStyle.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ namespace Terminal.Gui;
1010
public class FileDialogStyle
1111
{
1212
private readonly IFileSystem _fileSystem;
13-
private bool _preserveFilenameOnDirectoryChanges;
1413

1514
/// <summary>Creates a new instance of the <see cref="FileDialogStyle"/> class.</summary>
1615
public FileDialogStyle (IFileSystem fileSystem)

Terminal.Gui/Views/TextField.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ public virtual void Paste ()
11101110
TextModel.SetCol (ref col, Viewport.Width - 1, cols);
11111111
}
11121112

1113-
int pos = col - ScrollOffset + Math.Min (Viewport.X, 0);
1113+
int pos = col + Math.Min (Viewport.X, 0);
11141114
Move (pos, 0);
11151115

11161116
return new Point (pos, 0);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Drawing;
4+
using System.IO.Abstractions;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using Terminal.Gui;
9+
using TerminalGuiFluentTesting;
10+
using TerminalGuiFluentTestingXunit;
11+
using Xunit.Abstractions;
12+
13+
namespace IntegrationTests.FluentTests;
14+
public class TextFieldFluentTests
15+
{
16+
private readonly TextWriter _out;
17+
18+
public TextFieldFluentTests (ITestOutputHelper outputHelper)
19+
{
20+
_out = new TestOutputWriter (outputHelper);
21+
}
22+
23+
[Theory]
24+
[ClassData (typeof (V2TestDrivers))]
25+
public void TextField_Cursor_AtEnd_WhenTyping (V2TestDriver d)
26+
{
27+
// Simulates typing abcd into a TextField with width 3 (wide enough to render 2 characters only)
28+
using var c = With.A<Window> (100, 20, d)
29+
.Add (new TextField () { Width = 3 })
30+
.Focus<TextField> ()
31+
.WaitIteration ()
32+
.AssertCursorPosition (new Point (1, 1)) // Initial cursor position (because Window has border)
33+
.RaiseKeyDownEvent (Key.A)
34+
.WaitIteration ()
35+
.ScreenShot ("After typing first letter", _out)
36+
.AssertCursorPosition (new Point (2, 1)) // Cursor moves along as letter is pressed
37+
.RaiseKeyDownEvent (Key.B)
38+
.WaitIteration ()
39+
.AssertCursorPosition (new Point (3, 1)) // Cursor moves along as letter is pressed
40+
.RaiseKeyDownEvent (Key.C)
41+
.WaitIteration ()
42+
.ScreenShot ("After typing all letters",_out)
43+
.AssertCursorPosition (new Point (3, 1)) // Cursor stays where it is because we are at end of TextField
44+
.RaiseKeyDownEvent (Key.D)
45+
.WaitIteration ()
46+
.ScreenShot ("Typing one more letter", _out)
47+
.AssertCursorPosition (new Point (3, 1)) // Cursor still stays at end of TextField
48+
.WriteOutLogs (_out)
49+
.Stop ();
50+
}
51+
}

Tests/TerminalGuiFluentTesting/FakeOutput.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,10 @@ public void Write (ReadOnlySpan<char> text) { }
2424
public void SetCursorVisibility (CursorVisibility visibility) { }
2525

2626
/// <inheritdoc/>
27-
public void SetCursorPosition (int col, int row) { }
27+
public void SetCursorPosition (int col, int row) { CursorPosition = new Point (col, row); }
28+
29+
/// <summary>
30+
/// The last value set by calling <see cref="SetCursorPosition"/>
31+
/// </summary>
32+
public Point CursorPosition { get; private set; }
2833
}

Tests/TerminalGuiFluentTesting/GuiTestContext.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,10 +706,14 @@ public GuiTestContext Focus (View toFocus)
706706
/// is found (of Type T) or all views are looped through (back to the beginning)
707707
/// in which case triggers hard stop and Exception
708708
/// </summary>
709+
/// <param name="evaluator">Delegate that returns true if the passed View is the one
710+
/// you are trying to focus. Leave <see langword="null"/> to focus the first view of type
711+
/// <typeparamref name="T"/></param>
709712
/// <returns></returns>
710713
/// <exception cref="ArgumentException"></exception>
711-
public GuiTestContext Focus<T> (Func<T, bool> evaluator) where T : View
714+
public GuiTestContext Focus<T> (Func<T, bool>? evaluator = null) where T : View
712715
{
716+
evaluator ??= _ => true;
713717
Toplevel? t = Application.Top;
714718

715719
HashSet<View> seen = new ();
@@ -816,4 +820,13 @@ public GuiTestContext Send (Key key)
816820

817821
return this;
818822
}
823+
824+
/// <summary>
825+
/// Returns the last set position of the cursor.
826+
/// </summary>
827+
/// <returns></returns>
828+
public Point GetCursorPosition ()
829+
{
830+
return _output.CursorPosition;
831+
}
819832
}
Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,33 @@
1-
using TerminalGuiFluentTesting;
1+
using System.Drawing;
2+
using TerminalGuiFluentTesting;
23
using Xunit;
34

45
namespace TerminalGuiFluentTestingXunit;
56

67
public static partial class XunitContextExtensions
78
{
89
// Placeholder
10+
11+
12+
/// <summary>
13+
/// Asserts that the last set cursor position matches <paramref name="expected"/>
14+
/// </summary>
15+
/// <param name="context"></param>
16+
/// <param name="expected"></param>
17+
/// <returns></returns>
18+
public static GuiTestContext AssertCursorPosition (this GuiTestContext context, Point expected)
19+
{
20+
try
21+
{
22+
Assert.Equal (expected, context.GetCursorPosition ());
23+
}
24+
catch (Exception)
25+
{
26+
context.HardStop ();
27+
28+
throw;
29+
}
30+
31+
return context;
32+
}
933
}

0 commit comments

Comments
 (0)