Files
Terminal.Gui/Tests/UnitTests/FileServices/FileDialogTests.cs
Copilot f3fc20306e Remove TextField.Caption property; use Title with hotkey navigation support (#4352)
* Initial plan

* Initial exploration - understanding TextField Caption and Title

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Remove TextField.Caption and use Title instead with hotkey support

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Add defensive check to ensure TitleTextFormatter.Text is set

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Final changes - all tests passing

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Fixed bugs.

* Add comprehensive tests for caption rendering with attributes validation

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Fix: Disable TextField hotkey functionality to prevent input interception

TextField's Title is used as a caption/placeholder, not for hotkey
navigation. Hotkey visual formatting (underline) is still rendered
in the caption, but hotkey functionality is disabled to prevent
keys like 'E' and 'F' from being intercepted when typing in the field.

Updated test to expect "_Find" instead of "Find" to match resource change.

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Fix: Support Alt+key hotkey navigation while allowing normal typing

Override AddKeyBindingsForHotKey to only bind Alt+key combinations
(e.g., Alt+F for "_Find"), not the bare keys. This allows:
- Alt+F to navigate to the TextField with Title="_Find"
- Normal typing of 'F', 'E', etc. without interception

Previously, both bare key and Alt+key were bound, causing typing
issues. Now TextField properly supports hotkey navigation without
interfering with text input.

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Changes before error encountered

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Refactor hotkey handling to support command context

Refactored `RaiseHandlingHotKey` to accept an `ICommandContext? ctx` parameter, enabling context-aware hotkey handling. Updated `Command.HotKey` definitions across multiple classes (`View`, `CheckBox`, `Label`, `MenuBarv2`, `RadioGroup`, `TextField`) to utilize the new context parameter.

Enhanced XML documentation for `RaiseHandlingHotKey` to clarify its usage and return values. Added a context-aware hotkey handler to `TextField` with additional logic for focus handling.

Refactored attribute initialization and improved code readability in `TextField` by aligning parameters and removing unused `HotKeySpecifier` initialization. These changes improve flexibility, maintainability, and consistency across the codebase.

* Remove TextField.Caption property; use Title with hotkey navigation support

Co-authored-by: tig <585482+tig@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tig <585482+tig@users.noreply.github.com>
Co-authored-by: Tig <tig@users.noreply.github.com>
2025-10-27 07:50:09 -06:00

813 lines
30 KiB
C#

using System.IO.Abstractions.TestingHelpers;
using System.Runtime.InteropServices;
using UnitTests;
using Xunit.Abstractions;
namespace UnitTests.FileServicesTests;
public class FileDialogTests ()
{
[Theory]
[InlineData (true)]
[InlineData (false)]
[AutoInitShutdown]
public void CancelSelection (bool cancel)
{
FileDialog dlg = GetInitializedFileDialog ();
string openIn = Path.Combine (Environment.CurrentDirectory, "zz");
Directory.CreateDirectory (openIn);
dlg.Path = openIn + Path.DirectorySeparatorChar;
dlg.FilesSelected += (s, e) => e.Cancel = cancel;
//pressing enter will complete the current selection
// unless the event cancels the confirm
Application.RaiseKeyDownEvent (Key.Enter);
Assert.Equal (cancel, dlg.Canceled);
dlg.Dispose ();
}
[Fact]
[AutoInitShutdown]
public void DirectTyping_Allowed ()
{
FileDialog dlg = GetInitializedFileDialog ();
TextField tf = dlg.SubViews.OfType<TextField> ().First (t => t.HasFocus);
tf.ClearAllSelection ();
tf.CursorPosition = tf.Text.Length;
Assert.True (tf.HasFocus);
SendSlash ();
Assert.Equal (
new DirectoryInfo (Environment.CurrentDirectory + Path.DirectorySeparatorChar).FullName,
new DirectoryInfo (dlg.Path + Path.DirectorySeparatorChar).FullName
);
// continue typing the rest of the path
Send ("Bob");
Application.RaiseKeyDownEvent ('.');
Send ("csv");
Assert.True (dlg.Canceled);
Application.RaiseKeyDownEvent (Key.Enter);
Assert.False (dlg.Canceled);
Assert.Equal ("Bob.csv", Path.GetFileName (dlg.Path));
dlg.Dispose ();
}
[Fact]
[AutoInitShutdown]
public void DirectTyping_AutoComplete ()
{
FileDialog dlg = GetInitializedFileDialog ();
string openIn = Path.Combine (Environment.CurrentDirectory, "zz");
Directory.CreateDirectory (openIn);
string expectedDest = Path.Combine (openIn, "xx");
Directory.CreateDirectory (expectedDest);
dlg.Path = openIn + Path.DirectorySeparatorChar;
Send ("x");
// nothing selected yet
Assert.True (dlg.Canceled);
Assert.Equal ("x", Path.GetFileName (dlg.Path));
// complete auto typing
Application.RaiseKeyDownEvent ('\t');
// but do not close dialog
Assert.True (dlg.Canceled);
Assert.EndsWith ("xx" + Path.DirectorySeparatorChar, dlg.Path);
// press enter again to confirm the dialog
Application.RaiseKeyDownEvent (Key.Enter);
Assert.False (dlg.Canceled);
Assert.EndsWith ("xx" + Path.DirectorySeparatorChar, dlg.Path);
dlg.Dispose ();
}
[Fact]
[AutoInitShutdown]
public void DoNotConfirmSelectionWhenFindFocused ()
{
FileDialog dlg = GetInitializedFileDialog ();
string openIn = Path.Combine (Environment.CurrentDirectory, "zz");
Directory.CreateDirectory (openIn);
dlg.Path = openIn + Path.DirectorySeparatorChar;
var tf = dlg.SubViews.First (view => view.Id == "_tableViewContainer").SubViews.First (v => v.Id == "_tbFind") as TextField;
tf.SetFocus ();
Assert.IsType<TextField> (dlg.MostFocused);
Assert.Same (tf, dlg.MostFocused);
Assert.Equal ("_Find", tf.Title);
// Dialog has not yet been confirmed with a choice
Assert.True (dlg.Canceled);
//pressing enter while search focused should not confirm path
Application.RaiseKeyDownEvent (Key.Enter);
Assert.True (dlg.Canceled);
//// tabbing out of search
//Application.RaiseKeyDownEvent ('\t');
////should allow enter to confirm path
//Application.RaiseKeyDownEvent (Key.Enter);
//// Dialog has not yet been confirmed with a choice
//Assert.False (dlg.Canceled);
dlg.Dispose ();
}
[Fact]
[AutoInitShutdown]
public void DotDot_MovesToRoot_ThenPressBack ()
{
FileDialog dlg = GetDialog ();
dlg.OpenMode = OpenMode.Directory;
dlg.AllowsMultipleSelection = true;
var selected = false;
dlg.FilesSelected += (s, e) => { selected = true; };
AssertIsTheStartingDirectory (dlg.Path);
Assert.IsType<TextField> (dlg.MostFocused);
Application.RaiseKeyDownEvent (Key.CursorDown);
var tv = GetTableView(dlg);
tv.SetFocus ();
Assert.IsType<TableView> (dlg.MostFocused);
// ".." should be the first thing selected
// ".." should not mess with the displayed path
AssertIsTheStartingDirectory (dlg.Path);
// Accept navigation up a directory
Application.RaiseKeyDownEvent (Key.Enter);
AssertIsTheRootDirectory (dlg.Path);
Assert.True (dlg.Canceled);
Assert.False (selected);
Assert.IsType<TableView> (dlg.MostFocused);
// Now press Backspace (in table view)
Application.RaiseKeyDownEvent (Key.Backspace);
// Should move us back to the root
AssertIsTheStartingDirectory (dlg.Path);
Assert.True (dlg.Canceled);
Assert.False (selected);
dlg.Dispose ();
}
[Theory]
[AutoInitShutdown]
[InlineData (true)]
[InlineData (false)]
public void MultiSelectDirectory_CannotToggleDotDot (bool acceptWithEnter)
{
FileDialog dlg = GetDialog ();
dlg.OpenMode = OpenMode.Directory;
dlg.AllowsMultipleSelection = true;
IReadOnlyCollection<string> eventMultiSelected = null;
dlg.FilesSelected += (s, e) => { eventMultiSelected = e.Dialog.MultiSelected; };
var tv = GetTableView (dlg);
tv.SetFocus ();
Assert.IsType<TableView> (dlg.MostFocused);
// Try to toggle '..'
Application.RaiseKeyDownEvent (' ');
Application.RaiseKeyDownEvent (Key.CursorDown);
// Toggle subfolder
Application.RaiseKeyDownEvent (' ');
Assert.True (dlg.Canceled);
if (acceptWithEnter)
{
Application.RaiseKeyDownEvent (Key.Enter);
}
else
{
Application.RaiseKeyDownEvent ('O');
}
Assert.False (dlg.Canceled);
Assert.Multiple (
() =>
{
// Only the subfolder should be selected
Assert.Single (dlg.MultiSelected);
AssertIsTheSubfolder (dlg.Path);
AssertIsTheSubfolder (dlg.MultiSelected.Single ());
},
() =>
{
// Event should also agree with the final state
Assert.NotNull (eventMultiSelected);
Assert.Single (eventMultiSelected);
AssertIsTheSubfolder (eventMultiSelected.Single ());
}
);
dlg.Dispose ();
}
[Theory]
[AutoInitShutdown]
[InlineData (true)]
[InlineData (false)]
public void MultiSelectDirectory_CanToggleThenAccept (bool acceptWithEnter)
{
FileDialog dlg = GetDialog ();
dlg.OpenMode = OpenMode.Directory;
dlg.AllowsMultipleSelection = true;
IReadOnlyCollection<string> eventMultiSelected = null;
dlg.FilesSelected += (s, e) => { eventMultiSelected = e.Dialog.MultiSelected; };
var tv = GetTableView (dlg);
tv.SetFocus ();
Assert.IsType<TableView> (dlg.MostFocused);
// Move selection to subfolder
Application.RaiseKeyDownEvent (Key.CursorDown);
// Toggle subfolder
Application.RaiseKeyDownEvent (' ');
Assert.True (dlg.Canceled);
if (acceptWithEnter)
{
Application.RaiseKeyDownEvent (Key.Enter);
}
else
{
Application.RaiseKeyDownEvent (Key.O.WithAlt);
}
Assert.False (dlg.Canceled);
Assert.Multiple (
() =>
{
// Only the subfolder should be selected
Assert.Single (dlg.MultiSelected);
AssertIsTheSubfolder (dlg.Path);
AssertIsTheSubfolder (dlg.MultiSelected.Single ());
},
() =>
{
// Event should also agree with the final state
Assert.NotNull (eventMultiSelected);
Assert.Single (eventMultiSelected);
AssertIsTheSubfolder (eventMultiSelected.Single ());
}
);
dlg.Dispose ();
}
[Fact]
[AutoInitShutdown]
public void MultiSelectDirectory_EnterOpensFolder ()
{
FileDialog dlg = GetDialog ();
dlg.OpenMode = OpenMode.Directory;
dlg.AllowsMultipleSelection = true;
IReadOnlyCollection<string> eventMultiSelected = null;
dlg.FilesSelected += (s, e) => { eventMultiSelected = e.Dialog.MultiSelected; };
var tv = GetTableView (dlg);
tv.SetFocus ();
Assert.IsType<TableView> (dlg.MostFocused);
// Move selection to subfolder
Application.RaiseKeyDownEvent (Key.CursorDown);
Application.RaiseKeyDownEvent (Key.Enter);
// Path should update to the newly opened folder
AssertIsTheSubfolder (dlg.Path);
// No selection will have been confirmed
Assert.True (dlg.Canceled);
Assert.Empty (dlg.MultiSelected);
Assert.Null (eventMultiSelected);
dlg.Dispose ();
}
[Fact]
[AutoInitShutdown]
public void OnLoad_TextBoxIsFocused ()
{
FileDialog dlg = GetInitializedFileDialog ();
View tf = dlg.SubViews.FirstOrDefault (t => t.HasFocus);
Assert.NotNull (tf);
Assert.IsType<TextField> (tf);
dlg.Dispose ();
}
[Theory]
[AutoInitShutdown]
[InlineData (true, true)]
[InlineData (true, false)]
[InlineData (false, true)]
[InlineData (false, false)]
public void PickDirectory_ArrowNavigation (bool openModeMixed, bool multiple)
{
FileDialog dlg = GetDialog ();
dlg.OpenMode = openModeMixed ? OpenMode.Mixed : OpenMode.Directory;
dlg.AllowsMultipleSelection = multiple;
var tv = GetTableView (dlg);
tv.SetFocus ();
Assert.IsType<TableView> (dlg.MostFocused);
// Should be selecting ..
Application.RaiseKeyDownEvent (Key.CursorDown);
// Down to the directory
Assert.True (dlg.Canceled);
// Alt+O to open (enter would just navigate into the child dir)
Application.RaiseKeyDownEvent (Key.O.WithAlt);
Assert.False (dlg.Canceled);
AssertIsTheSubfolder (dlg.Path);
dlg.Dispose ();
}
[Theory]
[AutoInitShutdown]
[InlineData (true, true)]
[InlineData (true, false)]
[InlineData (false, true)]
[InlineData (false, false)]
public void PickDirectory_DirectTyping (bool openModeMixed, bool multiple)
{
FileDialog dlg = GetDialog ();
dlg.OpenMode = openModeMixed ? OpenMode.Mixed : OpenMode.Directory;
dlg.AllowsMultipleSelection = multiple;
// whe first opening the text field will have select all on
// so to add to current path user must press End or right
Application.RaiseKeyDownEvent (Key.CursorLeft);
Application.RaiseKeyDownEvent (Key.CursorRight);
Send ("subfolder");
// Dialog has not yet been confirmed with a choice
Assert.True (dlg.Canceled);
// Now it has
Application.RaiseKeyDownEvent (Key.Enter);
Assert.False (dlg.Canceled);
AssertIsTheSubfolder (dlg.Path);
dlg.Dispose ();
}
[Theory]
[InlineData (".csv", null, false)]
[InlineData (".csv", "", false)]
[InlineData (".csv", "c:\\MyFile.csv", true)]
[InlineData (".csv", "c:\\MyFile.CSV", true)]
[InlineData (".csv", "c:\\MyFile.csv.bak", false)]
public void TestAllowedType_Basic (string allowed, string candidate, bool expected)
{
Assert.Equal (expected, new AllowedType ("Test", allowed).IsAllowed (candidate));
}
[Theory]
[InlineData (".Designer.cs", "c:\\MyView.Designer.cs", true)]
[InlineData (".Designer.cs", "c:\\temp/MyView.Designer.cs", true)]
[InlineData (".Designer.cs", "MyView.Designer.cs", true)]
[InlineData (".Designer.cs", "c:\\MyView.DESIGNER.CS", true)]
[InlineData (".Designer.cs", "MyView.cs", false)]
public void TestAllowedType_DoubleBarreled (string allowed, string candidate, bool expected)
{
Assert.Equal (expected, new AllowedType ("Test", allowed).IsAllowed (candidate));
}
[Theory]
[InlineData ("Dockerfile", "c:\\temp\\Dockerfile", true)]
[InlineData ("Dockerfile", "Dockerfile", true)]
[InlineData ("Dockerfile", "someimg.Dockerfile", true)]
public void TestAllowedType_SpecificFile (string allowed, string candidate, bool expected)
{
Assert.Equal (expected, new AllowedType ("Test", allowed).IsAllowed (candidate));
}
[Fact]
[AutoInitShutdown]
public void TestDirectoryContents_Linux ()
{
if (IsWindows ())
{
return;
}
FileDialog fd = GetLinuxDialog ();
fd.Title = string.Empty;
fd.Style.Culture = new ("en-US");
fd.Draw ();
/*
*
*
┌─────────────────────────────────────────────────────────────────────────┐
│/demo/ │
│⟦▲⟧ │
│┌────────────┬──────────┬──────────────────────────────┬────────────────┐│
││Filename (▲)│Size │Modified │Type ││
│├────────────┼──────────┼──────────────────────────────┼────────────────┤│
││.. │ │ │<Directory> ││
││/subfolder │ │2002-01-01T22:42:10 │<Directory> ││
││image.gif │4.00 B │2002-01-01T22:42:10 │.gif ││
││jQuery.js │7.00 B │2001-01-01T11:44:42 │.js ││
│ │
│ │
│ │
│⟦ ►► ⟧ Enter Search ⟦► OK ◄⟧ ⟦ Cancel ⟧ │
└─────────────────────────────────────────────────────────────────────────┘
*
*/
var path = fd.SubViews.OfType<TextField> ().ElementAt (0);
Assert.Equal ("/demo/", path.Text);
var tv = GetTableView (fd);
// Asserting the headers
Assert.Equal ("Filename (▲)", tv.Table.ColumnNames.ElementAt (0));
Assert.Equal ("Size", tv.Table.ColumnNames.ElementAt (1));
Assert.Equal ("Modified", tv.Table.ColumnNames.ElementAt (2));
Assert.Equal ("Type", tv.Table.ColumnNames.ElementAt (3));
// Asserting the table contents
Assert.Equal ("..", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [0, 0]));
Assert.Equal ("/subfolder", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [1, 0]));
Assert.Equal ("image.gif", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [2, 0]));
Assert.Equal ("jQuery.js", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [3, 0]));
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [0, 1]));
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [1, 1]));
Assert.Equal ("4.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [2, 1]));
Assert.Equal ("7.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [3, 1]));
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [0, 2]));
Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [1, 2]));
Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [2, 2]));
Assert.Equal ("2001-01-01T11:44:42", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [3, 2]));
Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [0, 3]));
Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [1, 3]));
Assert.Equal (".gif", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [2, 3]));
Assert.Equal (".js", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [3, 3]));
fd.Dispose ();
}
[Fact]
[AutoInitShutdown]
public void TestDirectoryContents_Windows ()
{
if (!IsWindows ())
{
return;
}
FileDialog fd = GetWindowsDialog ();
fd.Title = string.Empty;
fd.Style.Culture = new ("en-US");
fd.Draw ();
/*
*
*
┌─────────────────────────────────────────────────────────────────────────┐
│c:\demo\ │
│⟦▲⟧ │
│┌────────────┬──────────┬──────────────────────────────┬────────────────┐│
││Filename (▲)│Size │Modified │Type ││
│├────────────┼──────────┼──────────────────────────────┼────────────────┤│
││.. │ │ │<Directory> ││
││\subfolder │ │2002-01-01T22:42:10 │<Directory> ││
││image.gif │4.00 B │2002-01-01T22:42:10 │.gif ││
││jQuery.js │7.00 B │2001-01-01T11:44:42 │.js ││
││mybinary.exe│7.00 B │2001-01-01T11:44:42 │.exe ││
│ │
│ │
│⟦ ►► ⟧ Enter Search ⟦► OK ◄⟧ ⟦ Cancel ⟧ │
└─────────────────────────────────────────────────────────────────────────┘
*
*/
var path = fd.SubViews.OfType<TextField> ().ElementAt (0);
Assert.Equal ("c:\\demo\\",path.Text);
var tv = GetTableView (fd);
// Asserting the headers
Assert.Equal ("Filename (▲)", tv.Table.ColumnNames.ElementAt (0));
Assert.Equal ("Size", tv.Table.ColumnNames.ElementAt (1));
Assert.Equal ("Modified", tv.Table.ColumnNames.ElementAt (2));
Assert.Equal ("Type", tv.Table.ColumnNames.ElementAt (3));
// Asserting the table contents
Assert.Equal ("..", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [0, 0]));
Assert.Equal (@"\subfolder", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [1, 0]));
Assert.Equal ("image.gif", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [2, 0]));
Assert.Equal ("jQuery.js", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [3, 0]));
Assert.Equal ("mybinary.exe", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [4, 0]));
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [0, 1]));
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [1, 1]));
Assert.Equal ("4.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [2, 1]));
Assert.Equal ("7.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [3, 1]));
Assert.Equal ("7.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [4, 1]));
Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [0, 2]));
Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [1, 2]));
Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [2, 2]));
Assert.Equal ("2001-01-01T11:44:42", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [3, 2]));
Assert.Equal ("2001-01-01T11:44:42", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [4, 2]));
Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [0, 3]));
Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [1, 3]));
Assert.Equal (".gif", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [2, 3]));
Assert.Equal (".js", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [3, 3]));
Assert.Equal (".exe", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [4, 3]));
fd.Dispose ();
}
private void AssertIsTheRootDirectory (string path)
{
if (IsWindows ())
{
Assert.Equal (@"c:\", path);
}
else
{
Assert.Equal ("/", path);
}
}
private void AssertIsTheStartingDirectory (string path)
{
if (IsWindows ())
{
Assert.Equal (@"c:\demo\", path);
}
else
{
Assert.Equal ("/demo/", path);
}
}
private void AssertIsTheSubfolder (string path)
{
if (IsWindows ())
{
Assert.Equal (@"c:\demo\subfolder", path);
}
else
{
Assert.Equal ("/demo/subfolder", path);
}
}
private void Begin (FileDialog dlg)
{
dlg.BeginInit ();
dlg.EndInit ();
Application.Begin (dlg);
}
private FileDialog GetDialog () { return IsWindows () ? GetWindowsDialog () : GetLinuxDialog (); }
private FileDialog GetInitializedFileDialog ()
{
Window.DefaultBorderStyle = LineStyle.Single;
Dialog.DefaultButtonAlignment = Alignment.Center;
Dialog.DefaultBorderStyle = LineStyle.Single;
Dialog.DefaultShadow = ShadowStyle.None;
Button.DefaultShadow = ShadowStyle.None;
var dlg = new FileDialog ();
Begin (dlg);
return dlg;
}
private FileDialog GetLinuxDialog ()
{
Window.DefaultBorderStyle = LineStyle.Single;
Dialog.DefaultButtonAlignment = Alignment.Center;
Dialog.DefaultBorderStyle = LineStyle.Single;
Dialog.DefaultShadow = ShadowStyle.None;
Button.DefaultShadow = ShadowStyle.None;
// Arrange
var fileSystem = new MockFileSystem (new Dictionary<string, MockFileData> (), "/");
fileSystem.MockTime (() => new (2010, 01, 01, 11, 12, 43));
fileSystem.AddFile (
@"/myfile.txt",
new ("Testing is meh.") { LastWriteTime = new DateTime (2001, 01, 01, 11, 12, 11) }
);
fileSystem.AddFile (
@"/demo/jQuery.js",
new ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) }
);
fileSystem.AddFile (
@"/demo/image.gif",
new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
{
LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
}
);
var m = (MockDirectoryInfo)fileSystem.DirectoryInfo.New (@"/demo/subfolder");
m.Create ();
m.LastWriteTime = new (2002, 01, 01, 22, 42, 10);
fileSystem.AddFile (
@"/demo/subfolder/image2.gif",
new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
{
LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
}
);
var fd = new FileDialog (fileSystem) { Height = 15, Width = 75 };
fd.Path = @"/demo/";
Begin (fd);
return fd;
}
private FileDialog GetWindowsDialog ()
{
// Override CM
Window.DefaultBorderStyle = LineStyle.Single;
Dialog.DefaultButtonAlignment = Alignment.Center;
Dialog.DefaultBorderStyle = LineStyle.Single;
Dialog.DefaultShadow = ShadowStyle.None;
Button.DefaultShadow = ShadowStyle.None;
// Arrange
var fileSystem = new MockFileSystem (new Dictionary<string, MockFileData> (), @"c:\");
fileSystem.MockTime (() => new (2010, 01, 01, 11, 12, 43));
fileSystem.AddFile (
@"c:\myfile.txt",
new ("Testing is meh.") { LastWriteTime = new DateTime (2001, 01, 01, 11, 12, 11) }
);
fileSystem.AddFile (
@"c:\demo\jQuery.js",
new ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) }
);
fileSystem.AddFile (
@"c:\demo\mybinary.exe",
new ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) }
);
fileSystem.AddFile (
@"c:\demo\image.gif",
new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
{
LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
}
);
var m = (MockDirectoryInfo)fileSystem.DirectoryInfo.New (@"c:\demo\subfolder");
m.Create ();
m.LastWriteTime = new (2002, 01, 01, 22, 42, 10);
fileSystem.AddFile (
@"c:\demo\subfolder\image2.gif",
new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
{
LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
}
);
var fd = new FileDialog (fileSystem) { Height = 15, Width = 75 };
fd.Path = @"c:\demo\";
Begin (fd);
return fd;
}
/*
[Fact, AutoInitShutdown]
public void Autocomplete_NoSuggestion_WhenTextMatchesExactly ()
{
var tb = new TextFieldWithAppendAutocomplete ();
ForceFocus (tb);
tb.Text = "/bob/fish";
tb.CursorPosition = tb.Text.Length;
tb.GenerateSuggestions (null, "fish", "fishes");
// should not report success for autocompletion because we already have that exact
// string
Assert.False (tb.AcceptSelectionIfAny ());
}
[Fact, AutoInitShutdown]
public void Autocomplete_AcceptSuggstion ()
{
var tb = new TextFieldWithAppendAutocomplete ();
ForceFocus (tb);
tb.Text = @"/bob/fi";
tb.CursorPosition = tb.Text.Length;
tb.GenerateSuggestions (null, "fish", "fishes");
Assert.True (tb.AcceptSelectionIfAny ());
Assert.Equal (@"/bob/fish", tb.Text);
}*/
private bool IsWindows () { return RuntimeInformation.IsOSPlatform (OSPlatform.Windows); }
private void Send (string chars)
{
foreach (char ch in chars)
{
Application.RaiseKeyDownEvent (ch);
}
}
private void SendSlash ()
{
if (Path.DirectorySeparatorChar == '/')
{
Application.RaiseKeyDownEvent ('/');
}
else
{
Application.RaiseKeyDownEvent ('\\');
}
}
private TableView GetTableView (FileDialog dlg)
{
// The table view is in the _tableViewContainer which is a direct subview of the dialog
// We need to search through all subviews recursively
TableView FindTableView (View view)
{
if (view is TableView tv)
{
return tv;
}
foreach (View subview in view.SubViews)
{
TableView result = FindTableView (subview);
if (result != null)
{
return result;
}
}
return null;
}
return FindTableView (dlg);
}
}