FileDialogTests.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. using System.IO.Abstractions.TestingHelpers;
  2. using System.Runtime.InteropServices;
  3. using Xunit.Abstractions;
  4. namespace Terminal.Gui.FileServicesTests;
  5. public class FileDialogTests ()
  6. {
  7. [Theory]
  8. [InlineData (true)]
  9. [InlineData (false)]
  10. [AutoInitShutdown]
  11. public void CancelSelection (bool cancel)
  12. {
  13. FileDialog dlg = GetInitializedFileDialog ();
  14. string openIn = Path.Combine (Environment.CurrentDirectory, "zz");
  15. Directory.CreateDirectory (openIn);
  16. dlg.Path = openIn + Path.DirectorySeparatorChar;
  17. dlg.FilesSelected += (s, e) => e.Cancel = cancel;
  18. //pressing enter will complete the current selection
  19. // unless the event cancels the confirm
  20. Send ('\n', ConsoleKey.Enter);
  21. Assert.Equal (cancel, dlg.Canceled);
  22. dlg.Dispose ();
  23. }
  24. [Fact]
  25. [AutoInitShutdown]
  26. public void DirectTyping_Allowed ()
  27. {
  28. FileDialog dlg = GetInitializedFileDialog ();
  29. TextField tf = dlg.Subviews.OfType<TextField> ().First (t => t.HasFocus);
  30. tf.ClearAllSelection ();
  31. tf.CursorPosition = tf.Text.Length;
  32. Assert.True (tf.HasFocus);
  33. SendSlash ();
  34. Assert.Equal (
  35. new DirectoryInfo (Environment.CurrentDirectory + Path.DirectorySeparatorChar).FullName,
  36. new DirectoryInfo (dlg.Path + Path.DirectorySeparatorChar).FullName
  37. );
  38. // continue typing the rest of the path
  39. Send ("BOB");
  40. Send ('.', ConsoleKey.OemPeriod);
  41. Send ("CSV");
  42. Assert.True (dlg.Canceled);
  43. Send ('\n', ConsoleKey.Enter);
  44. Assert.False (dlg.Canceled);
  45. Assert.Equal ("bob.csv", Path.GetFileName (dlg.Path));
  46. dlg.Dispose ();
  47. }
  48. [Fact]
  49. [AutoInitShutdown]
  50. public void DirectTyping_AutoComplete ()
  51. {
  52. FileDialog dlg = GetInitializedFileDialog ();
  53. string openIn = Path.Combine (Environment.CurrentDirectory, "zz");
  54. Directory.CreateDirectory (openIn);
  55. string expectedDest = Path.Combine (openIn, "xx");
  56. Directory.CreateDirectory (expectedDest);
  57. dlg.Path = openIn + Path.DirectorySeparatorChar;
  58. Send ("X");
  59. // nothing selected yet
  60. Assert.True (dlg.Canceled);
  61. Assert.Equal ("x", Path.GetFileName (dlg.Path));
  62. // complete auto typing
  63. Send ('\t', ConsoleKey.Tab);
  64. // but do not close dialog
  65. Assert.True (dlg.Canceled);
  66. Assert.EndsWith ("xx" + Path.DirectorySeparatorChar, dlg.Path);
  67. // press enter again to confirm the dialog
  68. Send ('\n', ConsoleKey.Enter);
  69. Assert.False (dlg.Canceled);
  70. Assert.EndsWith ("xx" + Path.DirectorySeparatorChar, dlg.Path);
  71. dlg.Dispose ();
  72. }
  73. [Fact]
  74. [AutoInitShutdown]
  75. public void DoNotConfirmSelectionWhenFindFocused ()
  76. {
  77. FileDialog dlg = GetInitializedFileDialog ();
  78. string openIn = Path.Combine (Environment.CurrentDirectory, "zz");
  79. Directory.CreateDirectory (openIn);
  80. dlg.Path = openIn + Path.DirectorySeparatorChar;
  81. var tf = GetTextField (dlg, FileDialogPart.SearchField);
  82. tf.SetFocus ();
  83. Assert.IsType<TextField> (dlg.MostFocused);
  84. Assert.Same (tf, dlg.MostFocused);
  85. Assert.Equal ("Enter Search", tf.Caption);
  86. // Dialog has not yet been confirmed with a choice
  87. Assert.True (dlg.Canceled);
  88. //pressing enter while search focused should not confirm path
  89. Send ('\n', ConsoleKey.Enter);
  90. Assert.True (dlg.Canceled);
  91. // tabbing out of search
  92. Send ('\t', ConsoleKey.Tab);
  93. //should allow enter to confirm path
  94. Send ('\n', ConsoleKey.Enter);
  95. // Dialog has not yet been confirmed with a choice
  96. Assert.False (dlg.Canceled);
  97. dlg.Dispose ();
  98. }
  99. [Fact]
  100. [AutoInitShutdown]
  101. public void DotDot_MovesToRoot_ThenPressBack ()
  102. {
  103. FileDialog dlg = GetDialog ();
  104. dlg.OpenMode = OpenMode.Directory;
  105. dlg.AllowsMultipleSelection = true;
  106. var selected = false;
  107. dlg.FilesSelected += (s, e) => { selected = true; };
  108. AssertIsTheStartingDirectory (dlg.Path);
  109. Assert.IsType<TextField> (dlg.MostFocused);
  110. Send ('v', ConsoleKey.DownArrow);
  111. var tv = GetTableView(dlg);
  112. tv.SetFocus ();
  113. Assert.IsType<TableView> (dlg.MostFocused);
  114. // ".." should be the first thing selected
  115. // ".." should not mess with the displayed path
  116. AssertIsTheStartingDirectory (dlg.Path);
  117. // Accept navigation up a directory
  118. Send ('\n', ConsoleKey.Enter);
  119. AssertIsTheRootDirectory (dlg.Path);
  120. Assert.True (dlg.Canceled);
  121. Assert.False (selected);
  122. // Now press the back button (in table view)
  123. Send ('<', ConsoleKey.Backspace);
  124. // Should move us back to the root
  125. AssertIsTheStartingDirectory (dlg.Path);
  126. Assert.True (dlg.Canceled);
  127. Assert.False (selected);
  128. dlg.Dispose ();
  129. }
  130. [Theory]
  131. [AutoInitShutdown]
  132. [InlineData (true)]
  133. [InlineData (false)]
  134. public void MultiSelectDirectory_CannotToggleDotDot (bool acceptWithEnter)
  135. {
  136. FileDialog dlg = GetDialog ();
  137. dlg.OpenMode = OpenMode.Directory;
  138. dlg.AllowsMultipleSelection = true;
  139. IReadOnlyCollection<string> eventMultiSelected = null;
  140. dlg.FilesSelected += (s, e) => { eventMultiSelected = e.Dialog.MultiSelected; };
  141. var tv = GetTableView (dlg);
  142. tv.SetFocus ();
  143. Assert.IsType<TableView> (dlg.MostFocused);
  144. // Try to toggle '..'
  145. Send (' ', ConsoleKey.Spacebar);
  146. Send ('v', ConsoleKey.DownArrow);
  147. // Toggle subfolder
  148. Send (' ', ConsoleKey.Spacebar);
  149. Assert.True (dlg.Canceled);
  150. if (acceptWithEnter)
  151. {
  152. Send ('\n', ConsoleKey.Enter);
  153. }
  154. else
  155. {
  156. Send ('O', ConsoleKey.O, false, true);
  157. }
  158. Assert.False (dlg.Canceled);
  159. Assert.Multiple (
  160. () =>
  161. {
  162. // Only the subfolder should be selected
  163. Assert.Single (dlg.MultiSelected);
  164. AssertIsTheSubfolder (dlg.Path);
  165. AssertIsTheSubfolder (dlg.MultiSelected.Single ());
  166. },
  167. () =>
  168. {
  169. // Event should also agree with the final state
  170. Assert.NotNull (eventMultiSelected);
  171. Assert.Single (eventMultiSelected);
  172. AssertIsTheSubfolder (eventMultiSelected.Single ());
  173. }
  174. );
  175. dlg.Dispose ();
  176. }
  177. [Theory]
  178. [AutoInitShutdown]
  179. [InlineData (true)]
  180. [InlineData (false)]
  181. public void MultiSelectDirectory_CanToggleThenAccept (bool acceptWithEnter)
  182. {
  183. FileDialog dlg = GetDialog ();
  184. dlg.OpenMode = OpenMode.Directory;
  185. dlg.AllowsMultipleSelection = true;
  186. IReadOnlyCollection<string> eventMultiSelected = null;
  187. dlg.FilesSelected += (s, e) => { eventMultiSelected = e.Dialog.MultiSelected; };
  188. var tv = GetTableView (dlg);
  189. tv.SetFocus ();
  190. Assert.IsType<TableView> (dlg.MostFocused);
  191. // Move selection to subfolder
  192. Send ('v', ConsoleKey.DownArrow);
  193. // Toggle subfolder
  194. Send (' ', ConsoleKey.Spacebar);
  195. Assert.True (dlg.Canceled);
  196. if (acceptWithEnter)
  197. {
  198. Send ('\n', ConsoleKey.Enter);
  199. }
  200. else
  201. {
  202. Send ('O', ConsoleKey.O, false, true);
  203. }
  204. Assert.False (dlg.Canceled);
  205. Assert.Multiple (
  206. () =>
  207. {
  208. // Only the subfolder should be selected
  209. Assert.Single (dlg.MultiSelected);
  210. AssertIsTheSubfolder (dlg.Path);
  211. AssertIsTheSubfolder (dlg.MultiSelected.Single ());
  212. },
  213. () =>
  214. {
  215. // Event should also agree with the final state
  216. Assert.NotNull (eventMultiSelected);
  217. Assert.Single (eventMultiSelected);
  218. AssertIsTheSubfolder (eventMultiSelected.Single ());
  219. }
  220. );
  221. dlg.Dispose ();
  222. }
  223. [Fact]
  224. [AutoInitShutdown]
  225. public void MultiSelectDirectory_EnterOpensFolder ()
  226. {
  227. FileDialog dlg = GetDialog ();
  228. dlg.OpenMode = OpenMode.Directory;
  229. dlg.AllowsMultipleSelection = true;
  230. IReadOnlyCollection<string> eventMultiSelected = null;
  231. dlg.FilesSelected += (s, e) => { eventMultiSelected = e.Dialog.MultiSelected; };
  232. var tv = GetTableView (dlg);
  233. tv.SetFocus ();
  234. Assert.IsType<TableView> (dlg.MostFocused);
  235. // Move selection to subfolder
  236. Send ('v', ConsoleKey.DownArrow);
  237. Send ('\n', ConsoleKey.Enter);
  238. // Path should update to the newly opened folder
  239. AssertIsTheSubfolder (dlg.Path);
  240. // No selection will have been confirmed
  241. Assert.True (dlg.Canceled);
  242. Assert.Empty (dlg.MultiSelected);
  243. Assert.Null (eventMultiSelected);
  244. dlg.Dispose ();
  245. }
  246. [Fact]
  247. [AutoInitShutdown]
  248. public void OnLoad_TextBoxIsFocused ()
  249. {
  250. FileDialog dlg = GetInitializedFileDialog ();
  251. View tf = dlg.Subviews.FirstOrDefault (t => t.HasFocus);
  252. Assert.NotNull (tf);
  253. Assert.IsType<TextField> (tf);
  254. dlg.Dispose ();
  255. }
  256. [Theory]
  257. [AutoInitShutdown]
  258. [InlineData (true, true)]
  259. [InlineData (true, false)]
  260. [InlineData (false, true)]
  261. [InlineData (false, false)]
  262. public void PickDirectory_ArrowNavigation (bool openModeMixed, bool multiple)
  263. {
  264. FileDialog dlg = GetDialog ();
  265. dlg.OpenMode = openModeMixed ? OpenMode.Mixed : OpenMode.Directory;
  266. dlg.AllowsMultipleSelection = multiple;
  267. var tv = GetTableView (dlg);
  268. tv.SetFocus ();
  269. Assert.IsType<TableView> (dlg.MostFocused);
  270. // Should be selecting ..
  271. Send ('v', ConsoleKey.DownArrow);
  272. // Down to the directory
  273. Assert.True (dlg.Canceled);
  274. // Alt+O to open (enter would just navigate into the child dir)
  275. Send ('O', ConsoleKey.O, false, true);
  276. Assert.False (dlg.Canceled);
  277. AssertIsTheSubfolder (dlg.Path);
  278. dlg.Dispose ();
  279. }
  280. [Theory]
  281. [AutoInitShutdown]
  282. [InlineData (true, true)]
  283. [InlineData (true, false)]
  284. [InlineData (false, true)]
  285. [InlineData (false, false)]
  286. public void PickDirectory_DirectTyping (bool openModeMixed, bool multiple)
  287. {
  288. FileDialog dlg = GetDialog ();
  289. dlg.OpenMode = openModeMixed ? OpenMode.Mixed : OpenMode.Directory;
  290. dlg.AllowsMultipleSelection = multiple;
  291. // whe first opening the text field will have select all on
  292. // so to add to current path user must press End or right
  293. Send ('>', ConsoleKey.LeftArrow);
  294. Send ('>', ConsoleKey.RightArrow);
  295. Send ("SUBFOLDER");
  296. // Dialog has not yet been confirmed with a choice
  297. Assert.True (dlg.Canceled);
  298. // Now it has
  299. Send ('\n', ConsoleKey.Enter);
  300. Assert.False (dlg.Canceled);
  301. AssertIsTheSubfolder (dlg.Path);
  302. dlg.Dispose ();
  303. }
  304. [Theory]
  305. [InlineData (".csv", null, false)]
  306. [InlineData (".csv", "", false)]
  307. [InlineData (".csv", "c:\\MyFile.csv", true)]
  308. [InlineData (".csv", "c:\\MyFile.CSV", true)]
  309. [InlineData (".csv", "c:\\MyFile.csv.bak", false)]
  310. public void TestAllowedType_Basic (string allowed, string candidate, bool expected)
  311. {
  312. Assert.Equal (expected, new AllowedType ("Test", allowed).IsAllowed (candidate));
  313. }
  314. [Theory]
  315. [InlineData (".Designer.cs", "c:\\MyView.Designer.cs", true)]
  316. [InlineData (".Designer.cs", "c:\\temp/MyView.Designer.cs", true)]
  317. [InlineData (".Designer.cs", "MyView.Designer.cs", true)]
  318. [InlineData (".Designer.cs", "c:\\MyView.DESIGNER.CS", true)]
  319. [InlineData (".Designer.cs", "MyView.cs", false)]
  320. public void TestAllowedType_DoubleBarreled (string allowed, string candidate, bool expected)
  321. {
  322. Assert.Equal (expected, new AllowedType ("Test", allowed).IsAllowed (candidate));
  323. }
  324. [Theory]
  325. [InlineData ("Dockerfile", "c:\\temp\\Dockerfile", true)]
  326. [InlineData ("Dockerfile", "Dockerfile", true)]
  327. [InlineData ("Dockerfile", "someimg.Dockerfile", true)]
  328. public void TestAllowedType_SpecificFile (string allowed, string candidate, bool expected)
  329. {
  330. Assert.Equal (expected, new AllowedType ("Test", allowed).IsAllowed (candidate));
  331. }
  332. [Fact]
  333. [AutoInitShutdown]
  334. public void TestDirectoryContents_Linux ()
  335. {
  336. if (IsWindows ())
  337. {
  338. return;
  339. }
  340. FileDialog fd = GetLinuxDialog ();
  341. fd.Title = string.Empty;
  342. fd.Style.Culture = new ("en-US");
  343. fd.Draw ();
  344. /*
  345. *
  346. *
  347. ┌─────────────────────────────────────────────────────────────────────────┐
  348. │/demo/ │
  349. │⟦▲⟧ │
  350. │┌────────────┬──────────┬──────────────────────────────┬────────────────┐│
  351. ││Filename (▲)│Size │Modified │Type ││
  352. │├────────────┼──────────┼──────────────────────────────┼────────────────┤│
  353. ││.. │ │ │<Directory> ││
  354. ││/subfolder │ │2002-01-01T22:42:10 │<Directory> ││
  355. ││image.gif │4.00 B │2002-01-01T22:42:10 │.gif ││
  356. ││jQuery.js │7.00 B │2001-01-01T11:44:42 │.js ││
  357. │ │
  358. │ │
  359. │ │
  360. │⟦ ►► ⟧ Enter Search ⟦► OK ◄⟧ ⟦ Cancel ⟧ │
  361. └─────────────────────────────────────────────────────────────────────────┘
  362. *
  363. */
  364. var path = GetTextField (fd, FileDialogPart.Path);
  365. Assert.Equal ("/demo/", path.Text);
  366. var tv = GetTableView (fd);
  367. // Asserting the headers
  368. Assert.Equal ("Filename (▲)", tv.Table.ColumnNames.ElementAt (0));
  369. Assert.Equal ("Size", tv.Table.ColumnNames.ElementAt (1));
  370. Assert.Equal ("Modified", tv.Table.ColumnNames.ElementAt (2));
  371. Assert.Equal ("Type", tv.Table.ColumnNames.ElementAt (3));
  372. // Asserting the table contents
  373. Assert.Equal ("..", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [0, 0]));
  374. Assert.Equal ("/subfolder", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [1, 0]));
  375. Assert.Equal ("image.gif", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [2, 0]));
  376. Assert.Equal ("jQuery.js", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [3, 0]));
  377. Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [0, 1]));
  378. Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [1, 1]));
  379. Assert.Equal ("4.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [2, 1]));
  380. Assert.Equal ("7.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [3, 1]));
  381. Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [0, 2]));
  382. Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [1, 2]));
  383. Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [2, 2]));
  384. Assert.Equal ("2001-01-01T11:44:42", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [3, 2]));
  385. Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [0, 3]));
  386. Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [1, 3]));
  387. Assert.Equal (".gif", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [2, 3]));
  388. Assert.Equal (".js", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [3, 3]));
  389. fd.Dispose ();
  390. }
  391. [Fact]
  392. [AutoInitShutdown]
  393. public void TestDirectoryContents_Windows ()
  394. {
  395. if (!IsWindows ())
  396. {
  397. return;
  398. }
  399. FileDialog fd = GetWindowsDialog ();
  400. fd.Title = string.Empty;
  401. fd.Style.Culture = new ("en-US");
  402. fd.Draw ();
  403. /*
  404. *
  405. *
  406. ┌─────────────────────────────────────────────────────────────────────────┐
  407. │c:\demo\ │
  408. │⟦▲⟧ │
  409. │┌────────────┬──────────┬──────────────────────────────┬────────────────┐│
  410. ││Filename (▲)│Size │Modified │Type ││
  411. │├────────────┼──────────┼──────────────────────────────┼────────────────┤│
  412. ││.. │ │ │<Directory> ││
  413. ││\subfolder │ │2002-01-01T22:42:10 │<Directory> ││
  414. ││image.gif │4.00 B │2002-01-01T22:42:10 │.gif ││
  415. ││jQuery.js │7.00 B │2001-01-01T11:44:42 │.js ││
  416. ││mybinary.exe│7.00 B │2001-01-01T11:44:42 │.exe ││
  417. │ │
  418. │ │
  419. │⟦ ►► ⟧ Enter Search ⟦► OK ◄⟧ ⟦ Cancel ⟧ │
  420. └─────────────────────────────────────────────────────────────────────────┘
  421. *
  422. */
  423. var path = GetTextField (fd, FileDialogPart.Path);
  424. Assert.Equal ("c:\\demo\\",path.Text);
  425. var tv = GetTableView (fd);
  426. // Asserting the headers
  427. Assert.Equal ("Filename (▲)", tv.Table.ColumnNames.ElementAt (0));
  428. Assert.Equal ("Size", tv.Table.ColumnNames.ElementAt (1));
  429. Assert.Equal ("Modified", tv.Table.ColumnNames.ElementAt (2));
  430. Assert.Equal ("Type", tv.Table.ColumnNames.ElementAt (3));
  431. // Asserting the table contents
  432. Assert.Equal ("..", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [0, 0]));
  433. Assert.Equal (@"\subfolder", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [1, 0]));
  434. Assert.Equal ("image.gif", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [2, 0]));
  435. Assert.Equal ("jQuery.js", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [3, 0]));
  436. Assert.Equal ("mybinary.exe", tv.Style.GetOrCreateColumnStyle (0).GetRepresentation (tv.Table [4, 0]));
  437. Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [0, 1]));
  438. Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [1, 1]));
  439. Assert.Equal ("4.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [2, 1]));
  440. Assert.Equal ("7.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [3, 1]));
  441. Assert.Equal ("7.00 B", tv.Style.GetOrCreateColumnStyle (1).GetRepresentation (tv.Table [4, 1]));
  442. Assert.Equal ("", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [0, 2]));
  443. Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [1, 2]));
  444. Assert.Equal ("2002-01-01T22:42:10", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [2, 2]));
  445. Assert.Equal ("2001-01-01T11:44:42", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [3, 2]));
  446. Assert.Equal ("2001-01-01T11:44:42", tv.Style.GetOrCreateColumnStyle (2).GetRepresentation (tv.Table [4, 2]));
  447. Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [0, 3]));
  448. Assert.Equal ("<Directory>", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [1, 3]));
  449. Assert.Equal (".gif", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [2, 3]));
  450. Assert.Equal (".js", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [3, 3]));
  451. Assert.Equal (".exe", tv.Style.GetOrCreateColumnStyle (3).GetRepresentation (tv.Table [4, 3]));
  452. fd.Dispose ();
  453. }
  454. private void AssertIsTheRootDirectory (string path)
  455. {
  456. if (IsWindows ())
  457. {
  458. Assert.Equal (@"c:\", path);
  459. }
  460. else
  461. {
  462. Assert.Equal ("/", path);
  463. }
  464. }
  465. private void AssertIsTheStartingDirectory (string path)
  466. {
  467. if (IsWindows ())
  468. {
  469. Assert.Equal (@"c:\demo\", path);
  470. }
  471. else
  472. {
  473. Assert.Equal ("/demo/", path);
  474. }
  475. }
  476. private void AssertIsTheSubfolder (string path)
  477. {
  478. if (IsWindows ())
  479. {
  480. Assert.Equal (@"c:\demo\subfolder", path);
  481. }
  482. else
  483. {
  484. Assert.Equal ("/demo/subfolder", path);
  485. }
  486. }
  487. private void Begin (FileDialog dlg)
  488. {
  489. dlg.BeginInit ();
  490. dlg.EndInit ();
  491. Application.Begin (dlg);
  492. }
  493. private FileDialog GetDialog () { return IsWindows () ? GetWindowsDialog () : GetLinuxDialog (); }
  494. private FileDialog GetInitializedFileDialog ()
  495. {
  496. Window.DefaultBorderStyle = LineStyle.Single;
  497. Dialog.DefaultButtonAlignment = Alignment.Center;
  498. Dialog.DefaultBorderStyle = LineStyle.Single;
  499. var dlg = new FileDialog ();
  500. Begin (dlg);
  501. return dlg;
  502. }
  503. private FileDialog GetLinuxDialog ()
  504. {
  505. Window.DefaultBorderStyle = LineStyle.Single;
  506. Dialog.DefaultButtonAlignment = Alignment.Center;
  507. Dialog.DefaultBorderStyle = LineStyle.Single;
  508. // Arrange
  509. var fileSystem = new MockFileSystem (new Dictionary<string, MockFileData> (), "/");
  510. fileSystem.MockTime (() => new (2010, 01, 01, 11, 12, 43));
  511. fileSystem.AddFile (
  512. @"/myfile.txt",
  513. new ("Testing is meh.") { LastWriteTime = new DateTime (2001, 01, 01, 11, 12, 11) }
  514. );
  515. fileSystem.AddFile (
  516. @"/demo/jQuery.js",
  517. new ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) }
  518. );
  519. fileSystem.AddFile (
  520. @"/demo/image.gif",
  521. new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
  522. {
  523. LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
  524. }
  525. );
  526. var m = (MockDirectoryInfo)fileSystem.DirectoryInfo.New (@"/demo/subfolder");
  527. m.Create ();
  528. m.LastWriteTime = new (2002, 01, 01, 22, 42, 10);
  529. fileSystem.AddFile (
  530. @"/demo/subfolder/image2.gif",
  531. new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
  532. {
  533. LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
  534. }
  535. );
  536. var fd = new FileDialog (fileSystem) { Height = 15, Width = 75 };
  537. fd.Path = @"/demo/";
  538. Begin (fd);
  539. return fd;
  540. }
  541. private FileDialog GetWindowsDialog ()
  542. {
  543. // Override CM
  544. Window.DefaultBorderStyle = LineStyle.Single;
  545. Dialog.DefaultButtonAlignment = Alignment.Center;
  546. Dialog.DefaultBorderStyle = LineStyle.Single;
  547. // Arrange
  548. var fileSystem = new MockFileSystem (new Dictionary<string, MockFileData> (), @"c:\");
  549. fileSystem.MockTime (() => new (2010, 01, 01, 11, 12, 43));
  550. fileSystem.AddFile (
  551. @"c:\myfile.txt",
  552. new ("Testing is meh.") { LastWriteTime = new DateTime (2001, 01, 01, 11, 12, 11) }
  553. );
  554. fileSystem.AddFile (
  555. @"c:\demo\jQuery.js",
  556. new ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) }
  557. );
  558. fileSystem.AddFile (
  559. @"c:\demo\mybinary.exe",
  560. new ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) }
  561. );
  562. fileSystem.AddFile (
  563. @"c:\demo\image.gif",
  564. new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
  565. {
  566. LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
  567. }
  568. );
  569. var m = (MockDirectoryInfo)fileSystem.DirectoryInfo.New (@"c:\demo\subfolder");
  570. m.Create ();
  571. m.LastWriteTime = new (2002, 01, 01, 22, 42, 10);
  572. fileSystem.AddFile (
  573. @"c:\demo\subfolder\image2.gif",
  574. new (new byte [] { 0x12, 0x34, 0x56, 0xd2 })
  575. {
  576. LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10)
  577. }
  578. );
  579. var fd = new FileDialog (fileSystem) { Height = 15, Width = 75 };
  580. fd.Path = @"c:\demo\";
  581. Begin (fd);
  582. return fd;
  583. }
  584. /*
  585. [Fact, AutoInitShutdown]
  586. public void Autocomplete_NoSuggestion_WhenTextMatchesExactly ()
  587. {
  588. var tb = new TextFieldWithAppendAutocomplete ();
  589. ForceFocus (tb);
  590. tb.Text = "/bob/fish";
  591. tb.CursorPosition = tb.Text.Length;
  592. tb.GenerateSuggestions (null, "fish", "fishes");
  593. // should not report success for autocompletion because we already have that exact
  594. // string
  595. Assert.False (tb.AcceptSelectionIfAny ());
  596. }
  597. [Fact, AutoInitShutdown]
  598. public void Autocomplete_AcceptSuggstion ()
  599. {
  600. var tb = new TextFieldWithAppendAutocomplete ();
  601. ForceFocus (tb);
  602. tb.Text = @"/bob/fi";
  603. tb.CursorPosition = tb.Text.Length;
  604. tb.GenerateSuggestions (null, "fish", "fishes");
  605. Assert.True (tb.AcceptSelectionIfAny ());
  606. Assert.Equal (@"/bob/fish", tb.Text);
  607. }*/
  608. private bool IsWindows () { return RuntimeInformation.IsOSPlatform (OSPlatform.Windows); }
  609. private void Send (char ch, ConsoleKey ck, bool shift = false, bool alt = false, bool control = false)
  610. {
  611. Application.Driver?.SendKeys (ch, ck, shift, alt, control);
  612. }
  613. private void Send (string chars)
  614. {
  615. foreach (char ch in chars)
  616. {
  617. Application.Driver?.SendKeys (ch, ConsoleKey.NoName, false, false, false);
  618. }
  619. }
  620. private void SendSlash ()
  621. {
  622. if (Path.DirectorySeparatorChar == '/')
  623. {
  624. Send ('/', ConsoleKey.Separator);
  625. }
  626. else
  627. {
  628. Send ('\\', ConsoleKey.Separator);
  629. }
  630. }
  631. private TextField GetTextField (FileDialog dlg, FileDialogPart part)
  632. {
  633. switch (part)
  634. {
  635. case FileDialogPart.Path:
  636. return dlg.Subviews.OfType<TextField> ().ElementAt (0);
  637. case FileDialogPart.SearchField:
  638. return dlg.Subviews.OfType<TextField> ().ElementAt (1);
  639. default:
  640. throw new ArgumentOutOfRangeException (nameof (part), part, null);
  641. }
  642. }
  643. private TableView GetTableView (FileDialog dlg)
  644. {
  645. var tile = dlg.Subviews.OfType<TileView> ().Single ();
  646. return (TableView)tile.Tiles.ElementAt (1).ContentView.Subviews.ElementAt(0);
  647. }
  648. private enum FileDialogPart
  649. {
  650. Path,
  651. SearchField,
  652. }
  653. }