2
0

TableViewTests.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. using System.Data;
  2. #nullable enable
  3. using JetBrains.Annotations;
  4. namespace ViewsTests;
  5. [TestSubject (typeof (TableView))]
  6. public class TableViewTests
  7. {
  8. [Fact]
  9. public void CanTabOutOfTableViewUsingCursor_Left ()
  10. {
  11. GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2);
  12. // Make the selected cell one in
  13. tableView.SelectedColumn = 1;
  14. // Pressing left should move us to the first column without changing focus
  15. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorLeft);
  16. Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
  17. Assert.True (tableView.HasFocus);
  18. // Because we are now on the leftmost cell a further left press should move focus
  19. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorLeft);
  20. Assert.NotSame (tableView, tableView.App!.TopRunnableView!.MostFocused);
  21. Assert.False (tableView.HasFocus);
  22. Assert.Same (tf1, tableView.App!.TopRunnableView.MostFocused);
  23. Assert.True (tf1.HasFocus);
  24. }
  25. [Fact]
  26. public void CanTabOutOfTableViewUsingCursor_Up ()
  27. {
  28. GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2);
  29. // Make the selected cell one in
  30. tableView.SelectedRow = 1;
  31. // First press should move us up
  32. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorUp);
  33. Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
  34. Assert.True (tableView.HasFocus);
  35. // Because we are now on the top row a further press should move focus
  36. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorUp);
  37. Assert.NotSame (tableView, tableView.App!.TopRunnableView!.MostFocused);
  38. Assert.False (tableView.HasFocus);
  39. Assert.Same (tf1, tableView.App!.TopRunnableView!.MostFocused);
  40. Assert.True (tf1.HasFocus);
  41. }
  42. [Fact]
  43. public void CanTabOutOfTableViewUsingCursor_Right ()
  44. {
  45. GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2);
  46. // Make the selected cell one in from the rightmost column
  47. tableView.SelectedColumn = tableView.Table.Columns - 2;
  48. // First press should move us to the rightmost column without changing focus
  49. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorRight);
  50. Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
  51. Assert.True (tableView.HasFocus);
  52. // Because we are now on the rightmost cell, a further right press should move focus
  53. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorRight);
  54. Assert.NotSame (tableView, tableView.App!.TopRunnableView!.MostFocused);
  55. Assert.False (tableView.HasFocus);
  56. Assert.Same (tf2, tableView.App!.TopRunnableView!.MostFocused);
  57. Assert.True (tf2.HasFocus);
  58. }
  59. [Fact]
  60. public void CanTabOutOfTableViewUsingCursor_Down ()
  61. {
  62. GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2);
  63. // Make the selected cell one in from the bottommost row
  64. tableView.SelectedRow = tableView.Table.Rows - 2;
  65. // First press should move us to the bottommost row without changing focus
  66. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorDown);
  67. Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
  68. Assert.True (tableView.HasFocus);
  69. // Because we are now on the bottommost cell, a further down press should move focus
  70. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorDown);
  71. Assert.NotSame (tableView, tableView.App!.TopRunnableView!.MostFocused);
  72. Assert.False (tableView.HasFocus);
  73. Assert.Same (tf2, tableView.App!.TopRunnableView!.MostFocused);
  74. Assert.True (tf2.HasFocus);
  75. }
  76. [Fact]
  77. public void CanTabOutOfTableViewUsingCursor_Left_ClearsSelectionFirst ()
  78. {
  79. GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2);
  80. // Make the selected cell one in
  81. tableView.SelectedColumn = 1;
  82. // Pressing shift-left should give us a multi selection
  83. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorLeft.WithShift);
  84. Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
  85. Assert.True (tableView.HasFocus);
  86. Assert.Equal (2, tableView.GetAllSelectedCells ().Count ());
  87. // Because we are now on the leftmost cell a further left press would normally move focus
  88. // However there is an ongoing selection so instead the operation clears the selection and
  89. // gets swallowed (not resulting in a focus change)
  90. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorLeft);
  91. // Selection 'clears' just to the single cell and we remain focused
  92. Assert.Single (tableView.GetAllSelectedCells ());
  93. Assert.Same (tableView, tableView.App!.TopRunnableView!.MostFocused);
  94. Assert.True (tableView.HasFocus);
  95. // A further left will switch focus
  96. tableView.App!.Keyboard.RaiseKeyDownEvent (Key.CursorLeft);
  97. Assert.NotSame (tableView, tableView.App!.TopRunnableView!.MostFocused);
  98. Assert.False (tableView.HasFocus);
  99. Assert.Same (tf1, tableView.App!.TopRunnableView!.MostFocused);
  100. Assert.True (tf1.HasFocus);
  101. }
  102. /// <summary>
  103. /// Creates 3 views on <see cref="Application.TopRunnableView"/> with the focus in the
  104. /// <see cref="TableView"/>. This is a helper method to setup tests that want to
  105. /// explore moving input focus out of a tableview.
  106. /// </summary>
  107. /// <param name="tv"></param>
  108. /// <param name="tf1"></param>
  109. /// <param name="tf2"></param>
  110. private void GetTableViewWithSiblings (out TextField tf1, out TableView tableView, out TextField tf2)
  111. {
  112. IApplication? app = Application.Create ();
  113. Runnable<bool>? runnable = new ();
  114. app.Begin (runnable);
  115. tableView = new ();
  116. tf1 = new ();
  117. tf2 = new ();
  118. runnable.Add (tf1);
  119. runnable.Add (tableView);
  120. runnable.Add (tf2);
  121. tableView.SetFocus ();
  122. Assert.Same (tableView, runnable.MostFocused);
  123. Assert.True (tableView.HasFocus);
  124. // Set big table
  125. tableView.Table = BuildTable (25, 50);
  126. }
  127. public static DataTableSource BuildTable (int cols, int rows) => BuildTable (cols, rows, out _);
  128. /// <summary>Builds a simple table of string columns with the requested number of columns and rows</summary>
  129. /// <param name="cols"></param>
  130. /// <param name="rows"></param>
  131. /// <returns></returns>
  132. public static DataTableSource BuildTable (int cols, int rows, out DataTable dt)
  133. {
  134. dt = new ();
  135. for (var c = 0; c < cols; c++)
  136. {
  137. dt.Columns.Add ("Col" + c);
  138. }
  139. for (var r = 0; r < rows; r++)
  140. {
  141. DataRow newRow = dt.NewRow ();
  142. for (var c = 0; c < cols; c++)
  143. {
  144. newRow [c] = $"R{r}C{c}";
  145. }
  146. dt.Rows.Add (newRow);
  147. }
  148. return new (dt);
  149. }
  150. [Fact]
  151. public void TableView_CollectionNavigatorMatcher_KeybindingsOverrideNavigator ()
  152. {
  153. var dt = new DataTable ();
  154. dt.Columns.Add ("blah");
  155. dt.Rows.Add ("apricot");
  156. dt.Rows.Add ("arm");
  157. dt.Rows.Add ("bat");
  158. dt.Rows.Add ("batman");
  159. dt.Rows.Add ("bates hotel");
  160. dt.Rows.Add ("candle");
  161. var tableView = new TableView ();
  162. tableView.Table = new DataTableSource (dt);
  163. tableView.HasFocus = true;
  164. tableView.KeyBindings.Add (Key.B, Command.Down);
  165. Assert.Equal (0, tableView.SelectedRow);
  166. // Keys should be consumed to move down the navigation i.e. to apricot
  167. Assert.True (tableView.NewKeyDownEvent (Key.B));
  168. Assert.Equal (1, tableView.SelectedRow);
  169. Assert.True (tableView.NewKeyDownEvent (Key.B));
  170. Assert.Equal (2, tableView.SelectedRow);
  171. // There is no keybinding for Key.C so it hits collection navigator i.e. we jump to candle
  172. Assert.True (tableView.NewKeyDownEvent (Key.C));
  173. Assert.Equal (5, tableView.SelectedRow);
  174. }
  175. }