ListViewTests.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Xunit;
  8. using Xunit.Abstractions;
  9. namespace Terminal.Gui.ViewTests {
  10. public class ListViewTests {
  11. readonly ITestOutputHelper output;
  12. public ListViewTests (ITestOutputHelper output)
  13. {
  14. this.output = output;
  15. }
  16. [Fact]
  17. public void Constructors_Defaults ()
  18. {
  19. var lv = new ListView ();
  20. Assert.Null (lv.Source);
  21. Assert.True (lv.CanFocus);
  22. lv = new ListView (new List<string> () { "One", "Two", "Three" });
  23. Assert.NotNull (lv.Source);
  24. lv = new ListView (new NewListDataSource ());
  25. Assert.NotNull (lv.Source);
  26. lv = new ListView (new Rect (0, 1, 10, 20), new List<string> () { "One", "Two", "Three" });
  27. Assert.NotNull (lv.Source);
  28. Assert.Equal (new Rect (0, 1, 10, 20), lv.Frame);
  29. lv = new ListView (new Rect (0, 1, 10, 20), new NewListDataSource ());
  30. Assert.NotNull (lv.Source);
  31. Assert.Equal (new Rect (0, 1, 10, 20), lv.Frame);
  32. }
  33. [Fact]
  34. public void ListViewSelectThenDown ()
  35. {
  36. var lv = new ListView (new List<string> () { "One", "Two", "Three" });
  37. lv.AllowsMarking = true;
  38. Assert.NotNull (lv.Source);
  39. // first item should be selected by default
  40. Assert.Equal (0, lv.SelectedItem);
  41. // nothing is ticked
  42. Assert.False (lv.Source.IsMarked (0));
  43. Assert.False (lv.Source.IsMarked (1));
  44. Assert.False (lv.Source.IsMarked (2));
  45. lv.AddKeyBinding (Key.Space | Key.ShiftMask, Command.ToggleChecked, Command.LineDown);
  46. var ev = new KeyEvent (Key.Space | Key.ShiftMask, new KeyModifiers () { Shift = true });
  47. // view should indicate that it has accepted and consumed the event
  48. Assert.True (lv.ProcessKey (ev));
  49. // second item should now be selected
  50. Assert.Equal (1, lv.SelectedItem);
  51. // first item only should be ticked
  52. Assert.True (lv.Source.IsMarked (0));
  53. Assert.False (lv.Source.IsMarked (1));
  54. Assert.False (lv.Source.IsMarked (2));
  55. // Press key combo again
  56. Assert.True (lv.ProcessKey (ev));
  57. Assert.Equal (2, lv.SelectedItem);
  58. Assert.True (lv.Source.IsMarked (0));
  59. Assert.True (lv.Source.IsMarked (1));
  60. Assert.False (lv.Source.IsMarked (2));
  61. // Press key combo again
  62. Assert.True (lv.ProcessKey (ev));
  63. Assert.Equal (2, lv.SelectedItem); // cannot move down any further
  64. Assert.True (lv.Source.IsMarked (0));
  65. Assert.True (lv.Source.IsMarked (1));
  66. Assert.True (lv.Source.IsMarked (2)); // but can toggle marked
  67. // Press key combo again
  68. Assert.True (lv.ProcessKey (ev));
  69. Assert.Equal (2, lv.SelectedItem); // cannot move down any further
  70. Assert.True (lv.Source.IsMarked (0));
  71. Assert.True (lv.Source.IsMarked (1));
  72. Assert.False (lv.Source.IsMarked (2)); // untoggle toggle marked
  73. }
  74. [Fact]
  75. public void SettingEmptyKeybindingThrows ()
  76. {
  77. var lv = new ListView (new List<string> () { "One", "Two", "Three" });
  78. Assert.Throws<ArgumentException> (() => lv.AddKeyBinding (Key.Space));
  79. }
  80. /// <summary>
  81. /// Tests that when none of the Commands in a chained keybinding are possible
  82. /// the <see cref="View.ProcessKey(KeyEvent)"/> returns the appropriate result
  83. /// </summary>
  84. [Fact]
  85. public void ListViewProcessKeyReturnValue_WithMultipleCommands ()
  86. {
  87. var lv = new ListView (new List<string> () { "One", "Two", "Three", "Four" });
  88. Assert.NotNull (lv.Source);
  89. // first item should be selected by default
  90. Assert.Equal (0, lv.SelectedItem);
  91. // bind shift down to move down twice in control
  92. lv.AddKeyBinding (Key.CursorDown | Key.ShiftMask, Command.LineDown, Command.LineDown);
  93. var ev = new KeyEvent (Key.CursorDown | Key.ShiftMask, new KeyModifiers () { Shift = true });
  94. Assert.True (lv.ProcessKey (ev), "The first time we move down 2 it should be possible");
  95. // After moving down twice from One we should be at 'Three'
  96. Assert.Equal (2, lv.SelectedItem);
  97. // clear the items
  98. lv.SetSource (null);
  99. // Press key combo again - return should be false this time as none of the Commands are allowable
  100. Assert.False (lv.ProcessKey (ev), "We cannot move down so will not respond to this");
  101. }
  102. private class NewListDataSource : IListDataSource {
  103. public int Count => throw new NotImplementedException ();
  104. public int Length => throw new NotImplementedException ();
  105. public bool IsMarked (int item)
  106. {
  107. throw new NotImplementedException ();
  108. }
  109. public void Render (ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width, int start = 0)
  110. {
  111. throw new NotImplementedException ();
  112. }
  113. public void SetMark (int item, bool value)
  114. {
  115. throw new NotImplementedException ();
  116. }
  117. public IList ToList ()
  118. {
  119. return new List<string> () { "One", "Two", "Three" };
  120. }
  121. }
  122. [Fact]
  123. public void KeyBindings_Command ()
  124. {
  125. List<string> source = new List<string> () { "One", "Two", "Three" };
  126. ListView lv = new ListView (source) { Height = 2, AllowsMarking = true };
  127. Assert.Equal (0, lv.SelectedItem);
  128. Assert.True (lv.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())));
  129. Assert.Equal (1, lv.SelectedItem);
  130. Assert.True (lv.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())));
  131. Assert.Equal (0, lv.SelectedItem);
  132. Assert.True (lv.ProcessKey (new KeyEvent (Key.PageDown, new KeyModifiers ())));
  133. Assert.Equal (2, lv.SelectedItem);
  134. Assert.Equal (2, lv.TopItem);
  135. Assert.True (lv.ProcessKey (new KeyEvent (Key.PageUp, new KeyModifiers ())));
  136. Assert.Equal (0, lv.SelectedItem);
  137. Assert.Equal (0, lv.TopItem);
  138. Assert.False (lv.Source.IsMarked (lv.SelectedItem));
  139. Assert.True (lv.ProcessKey (new KeyEvent (Key.Space, new KeyModifiers ())));
  140. Assert.True (lv.Source.IsMarked (lv.SelectedItem));
  141. var opened = false;
  142. lv.OpenSelectedItem += (_) => opened = true;
  143. Assert.True (lv.ProcessKey (new KeyEvent (Key.Enter, new KeyModifiers ())));
  144. Assert.True (opened);
  145. Assert.True (lv.ProcessKey (new KeyEvent (Key.End, new KeyModifiers ())));
  146. Assert.Equal (2, lv.SelectedItem);
  147. Assert.True (lv.ProcessKey (new KeyEvent (Key.Home, new KeyModifiers ())));
  148. Assert.Equal (0, lv.SelectedItem);
  149. }
  150. [Fact]
  151. [AutoInitShutdown]
  152. public void RowRender_Event ()
  153. {
  154. var rendered = false;
  155. var source = new List<string> () { "one", "two", "three" };
  156. var lv = new ListView () { Width = Dim.Fill (), Height = Dim.Fill () };
  157. lv.RowRender += _ => rendered = true;
  158. Application.Top.Add (lv);
  159. Application.Begin (Application.Top);
  160. Assert.False (rendered);
  161. lv.SetSource (source);
  162. lv.Redraw (lv.Bounds);
  163. Assert.True (rendered);
  164. }
  165. [Fact]
  166. [AutoInitShutdown]
  167. public void EnsureSelectedItemVisible_Top ()
  168. {
  169. var source = new List<string> () { "First", "Second" };
  170. ListView lv = new ListView (source) { Width = Dim.Fill (), Height = 1 };
  171. lv.SelectedItem = 1;
  172. Application.Top.Add (lv);
  173. Application.Begin (Application.Top);
  174. Assert.Equal ("Second ", GetContents (0));
  175. Assert.Equal (new (' ', 7), GetContents (1));
  176. lv.MoveUp ();
  177. lv.Redraw (lv.Bounds);
  178. Assert.Equal ("First ", GetContents (0));
  179. Assert.Equal (new (' ', 7), GetContents (1));
  180. string GetContents (int line)
  181. {
  182. var item = "";
  183. for (int i = 0; i < 7; i++) {
  184. item += (char)Application.Driver.Contents [line, i, 0];
  185. }
  186. return item;
  187. }
  188. }
  189. [Fact]
  190. [AutoInitShutdown]
  191. public void Ensures_Visibility_SelectedItem_On_MoveDown_And_MoveUp ()
  192. {
  193. var source = new List<string> ();
  194. for (int i = 0; i < 20; i++) {
  195. source.Add ($"Line{i}");
  196. }
  197. var lv = new ListView (source) { Width = Dim.Fill (), Height = Dim.Fill () };
  198. var win = new Window ();
  199. win.Add (lv);
  200. Application.Top.Add (win);
  201. Application.Begin (Application.Top);
  202. ((FakeDriver)Application.Driver).SetBufferSize (12, 12);
  203. Application.Refresh ();
  204. Assert.Equal (0, lv.SelectedItem);
  205. TestHelpers.AssertDriverContentsWithFrameAre (@"
  206. ┌──────────┐
  207. │Line0 │
  208. │Line1 │
  209. │Line2 │
  210. │Line3 │
  211. │Line4 │
  212. │Line5 │
  213. │Line6 │
  214. │Line7 │
  215. │Line8 │
  216. │Line9 │
  217. └──────────┘", output);
  218. Assert.True (lv.ScrollDown (10));
  219. lv.Redraw (lv.Bounds);
  220. Assert.Equal (0, lv.SelectedItem);
  221. TestHelpers.AssertDriverContentsWithFrameAre (@"
  222. ┌──────────┐
  223. │Line10 │
  224. │Line11 │
  225. │Line12 │
  226. │Line13 │
  227. │Line14 │
  228. │Line15 │
  229. │Line16 │
  230. │Line17 │
  231. │Line18 │
  232. │Line19 │
  233. └──────────┘", output);
  234. Assert.True (lv.MoveDown ());
  235. lv.Redraw (lv.Bounds);
  236. Assert.Equal (1, lv.SelectedItem);
  237. TestHelpers.AssertDriverContentsWithFrameAre (@"
  238. ┌──────────┐
  239. │Line1 │
  240. │Line2 │
  241. │Line3 │
  242. │Line4 │
  243. │Line5 │
  244. │Line6 │
  245. │Line7 │
  246. │Line8 │
  247. │Line9 │
  248. │Line10 │
  249. └──────────┘", output);
  250. Assert.True (lv.MoveEnd ());
  251. lv.Redraw (lv.Bounds);
  252. Assert.Equal (19, lv.SelectedItem);
  253. TestHelpers.AssertDriverContentsWithFrameAre (@"
  254. ┌──────────┐
  255. │Line19 │
  256. │ │
  257. │ │
  258. │ │
  259. │ │
  260. │ │
  261. │ │
  262. │ │
  263. │ │
  264. │ │
  265. └──────────┘", output);
  266. Assert.True (lv.ScrollUp (20));
  267. lv.Redraw (lv.Bounds);
  268. Assert.Equal (19, lv.SelectedItem);
  269. TestHelpers.AssertDriverContentsWithFrameAre (@"
  270. ┌──────────┐
  271. │Line0 │
  272. │Line1 │
  273. │Line2 │
  274. │Line3 │
  275. │Line4 │
  276. │Line5 │
  277. │Line6 │
  278. │Line7 │
  279. │Line8 │
  280. │Line9 │
  281. └──────────┘", output);
  282. Assert.True (lv.MoveDown ());
  283. lv.Redraw (lv.Bounds);
  284. Assert.Equal (19, lv.SelectedItem);
  285. TestHelpers.AssertDriverContentsWithFrameAre (@"
  286. ┌──────────┐
  287. │Line10 │
  288. │Line11 │
  289. │Line12 │
  290. │Line13 │
  291. │Line14 │
  292. │Line15 │
  293. │Line16 │
  294. │Line17 │
  295. │Line18 │
  296. │Line19 │
  297. └──────────┘", output);
  298. Assert.True (lv.ScrollUp (20));
  299. lv.Redraw (lv.Bounds);
  300. Assert.Equal (19, lv.SelectedItem);
  301. TestHelpers.AssertDriverContentsWithFrameAre (@"
  302. ┌──────────┐
  303. │Line0 │
  304. │Line1 │
  305. │Line2 │
  306. │Line3 │
  307. │Line4 │
  308. │Line5 │
  309. │Line6 │
  310. │Line7 │
  311. │Line8 │
  312. │Line9 │
  313. └──────────┘", output);
  314. Assert.True (lv.MoveDown ());
  315. lv.Redraw (lv.Bounds);
  316. Assert.Equal (19, lv.SelectedItem);
  317. TestHelpers.AssertDriverContentsWithFrameAre (@"
  318. ┌──────────┐
  319. │Line10 │
  320. │Line11 │
  321. │Line12 │
  322. │Line13 │
  323. │Line14 │
  324. │Line15 │
  325. │Line16 │
  326. │Line17 │
  327. │Line18 │
  328. │Line19 │
  329. └──────────┘", output);
  330. Assert.True (lv.MoveHome ());
  331. lv.Redraw (lv.Bounds);
  332. Assert.Equal (0, lv.SelectedItem);
  333. TestHelpers.AssertDriverContentsWithFrameAre (@"
  334. ┌──────────┐
  335. │Line0 │
  336. │Line1 │
  337. │Line2 │
  338. │Line3 │
  339. │Line4 │
  340. │Line5 │
  341. │Line6 │
  342. │Line7 │
  343. │Line8 │
  344. │Line9 │
  345. └──────────┘", output);
  346. Assert.True (lv.ScrollDown (20));
  347. lv.Redraw (lv.Bounds);
  348. Assert.Equal (0, lv.SelectedItem);
  349. TestHelpers.AssertDriverContentsWithFrameAre (@"
  350. ┌──────────┐
  351. │Line19 │
  352. │ │
  353. │ │
  354. │ │
  355. │ │
  356. │ │
  357. │ │
  358. │ │
  359. │ │
  360. │ │
  361. └──────────┘", output);
  362. Assert.True (lv.MoveUp ());
  363. lv.Redraw (lv.Bounds);
  364. Assert.Equal (0, lv.SelectedItem);
  365. TestHelpers.AssertDriverContentsWithFrameAre (@"
  366. ┌──────────┐
  367. │Line0 │
  368. │Line1 │
  369. │Line2 │
  370. │Line3 │
  371. │Line4 │
  372. │Line5 │
  373. │Line6 │
  374. │Line7 │
  375. │Line8 │
  376. │Line9 │
  377. └──────────┘", output);
  378. }
  379. [Fact]
  380. public void SetSource_Preserves_ListWrapper_Instance_If_Not_Null ()
  381. {
  382. var lv = new ListView (new List<string> { "One", "Two" });
  383. Assert.NotNull (lv.Source);
  384. lv.SetSource (null);
  385. Assert.NotNull (lv.Source);
  386. lv.Source = null;
  387. Assert.Null (lv.Source);
  388. lv = new ListView (new List<string> { "One", "Two" });
  389. Assert.NotNull (lv.Source);
  390. lv.SetSourceAsync (null);
  391. Assert.NotNull (lv.Source);
  392. }
  393. [Fact]
  394. public void ListWrapper_StartsWith ()
  395. {
  396. var lw = new ListWrapper (new List<string> { "One", "Two", "Three" });
  397. Assert.Equal (1, lw.StartsWith ("t"));
  398. Assert.Equal (1, lw.StartsWith ("tw"));
  399. Assert.Equal (2, lw.StartsWith ("th"));
  400. Assert.Equal (1, lw.StartsWith ("T"));
  401. Assert.Equal (1, lw.StartsWith ("TW"));
  402. Assert.Equal (2, lw.StartsWith ("TH"));
  403. lw = new ListWrapper (new List<NStack.ustring> { "One", "Two", "Three" });
  404. Assert.Equal (1, lw.StartsWith ("t"));
  405. Assert.Equal (1, lw.StartsWith ("tw"));
  406. Assert.Equal (2, lw.StartsWith ("th"));
  407. Assert.Equal (1, lw.StartsWith ("T"));
  408. Assert.Equal (1, lw.StartsWith ("TW"));
  409. Assert.Equal (2, lw.StartsWith ("TH"));
  410. }
  411. [Fact, AutoInitShutdown]
  412. public void EnsureSelectedItemVisible_SelectedItem ()
  413. {
  414. var source = new List<string> ();
  415. for (int i = 0; i < 10; i++) {
  416. source.Add ($"Item {i}");
  417. }
  418. var lv = new ListView (source) {
  419. Width = 10,
  420. Height = 5
  421. };
  422. Application.Top.Add (lv);
  423. Application.Begin (Application.Top);
  424. TestHelpers.AssertDriverContentsWithFrameAre (@"
  425. Item 0
  426. Item 1
  427. Item 2
  428. Item 3
  429. Item 4", output);
  430. lv.SelectedItem = 6;
  431. Application.Refresh ();
  432. TestHelpers.AssertDriverContentsWithFrameAre (@"
  433. Item 0
  434. Item 1
  435. Item 2
  436. Item 3
  437. Item 4", output);
  438. lv.EnsureSelectedItemVisible ();
  439. Application.Refresh ();
  440. TestHelpers.AssertDriverContentsWithFrameAre (@"
  441. Item 2
  442. Item 3
  443. Item 4
  444. Item 5
  445. Item 6", output);
  446. }
  447. }
  448. }