AppendAutocompleteTests.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. using Xunit.Abstractions;
  2. namespace Terminal.Gui.TextTests;
  3. public class AppendAutocompleteTests (ITestOutputHelper output)
  4. {
  5. [Fact]
  6. [AutoInitShutdown]
  7. public void TestAutoAppend_AfterCloseKey_NoAutocomplete ()
  8. {
  9. TextField tf = GetTextFieldsInViewSuggesting ("fish");
  10. View.SetClipToScreen ();
  11. // f is typed and suggestion is "fish"
  12. Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
  13. tf.Draw ();
  14. tf.PositionCursor ();
  15. TestHelpers.AssertDriverContentsAre ("fish", output);
  16. Assert.Equal ("f", tf.Text);
  17. // When cancelling autocomplete
  18. Application.Driver?.SendKeys ('e', ConsoleKey.Escape, false, false, false);
  19. // Suggestion should disappear
  20. View.SetClipToScreen ();
  21. tf.Draw ();
  22. TestHelpers.AssertDriverContentsAre ("f", output);
  23. Assert.Equal ("f", tf.Text);
  24. // Still has focus though
  25. Assert.Same (tf, Application.Top.Focused);
  26. // But can tab away
  27. Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
  28. Assert.NotSame (tf, Application.Top.Focused);
  29. Application.Top.Dispose ();
  30. }
  31. [Fact]
  32. [AutoInitShutdown]
  33. public void TestAutoAppend_AfterCloseKey_ReappearsOnLetter ()
  34. {
  35. TextField tf = GetTextFieldsInViewSuggesting ("fish");
  36. // f is typed and suggestion is "fish"
  37. Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
  38. View.SetClipToScreen ();
  39. tf.Draw ();
  40. tf.PositionCursor ();
  41. TestHelpers.AssertDriverContentsAre ("fish", output);
  42. Assert.Equal ("f", tf.Text);
  43. // When cancelling autocomplete
  44. Application.Driver?.SendKeys ('\0', ConsoleKey.Escape, false, false, false);
  45. // Suggestion should disappear
  46. View.SetClipToScreen ();
  47. tf.Draw ();
  48. TestHelpers.AssertDriverContentsAre ("f", output);
  49. Assert.Equal ("f", tf.Text);
  50. // Should reappear when you press next letter
  51. Application.Driver?.SendKeys ('i', ConsoleKey.I, false, false, false);
  52. tf.PositionCursor ();
  53. View.SetClipToScreen ();
  54. tf.Draw ();
  55. TestHelpers.AssertDriverContentsAre ("fish", output);
  56. Assert.Equal ("fi", tf.Text);
  57. Application.Top.Dispose ();
  58. }
  59. [Theory]
  60. [AutoInitShutdown]
  61. [InlineData (ConsoleKey.UpArrow)]
  62. [InlineData (ConsoleKey.DownArrow)]
  63. public void TestAutoAppend_CycleSelections (ConsoleKey cycleKey)
  64. {
  65. TextField tf = GetTextFieldsInViewSuggesting ("fish", "friend");
  66. // f is typed and suggestion is "fish"
  67. Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
  68. View.SetClipToScreen ();
  69. tf.Draw ();
  70. tf.PositionCursor ();
  71. TestHelpers.AssertDriverContentsAre ("fish", output);
  72. Assert.Equal ("f", tf.Text);
  73. // When cycling autocomplete
  74. Application.Driver?.SendKeys (' ', cycleKey, false, false, false);
  75. View.SetClipToScreen ();
  76. tf.Draw ();
  77. tf.PositionCursor ();
  78. TestHelpers.AssertDriverContentsAre ("friend", output);
  79. Assert.Equal ("f", tf.Text);
  80. // Should be able to cycle in circles endlessly
  81. Application.Driver?.SendKeys (' ', cycleKey, false, false, false);
  82. View.SetClipToScreen ();
  83. tf.Draw ();
  84. tf.PositionCursor ();
  85. TestHelpers.AssertDriverContentsAre ("fish", output);
  86. Assert.Equal ("f", tf.Text);
  87. Application.Top.Dispose ();
  88. }
  89. [Fact]
  90. [AutoInitShutdown]
  91. public void TestAutoAppend_NoRender_WhenCursorNotAtEnd ()
  92. {
  93. TextField tf = GetTextFieldsInViewSuggesting ("fish");
  94. // f is typed and suggestion is "fish"
  95. Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
  96. View.SetClipToScreen ();
  97. tf.Draw ();
  98. tf.PositionCursor ();
  99. TestHelpers.AssertDriverContentsAre ("fish", output);
  100. Assert.Equal ("f", tf.Text);
  101. // add a space then go back 1
  102. Application.Driver?.SendKeys (' ', ConsoleKey.Spacebar, false, false, false);
  103. Application.Driver?.SendKeys ('<', ConsoleKey.LeftArrow, false, false, false);
  104. View.SetClipToScreen ();
  105. tf.Draw ();
  106. TestHelpers.AssertDriverContentsAre ("f", output);
  107. Assert.Equal ("f ", tf.Text);
  108. Application.Top.Dispose ();
  109. }
  110. [Fact]
  111. [AutoInitShutdown]
  112. public void TestAutoAppend_NoRender_WhenNoMatch ()
  113. {
  114. TextField tf = GetTextFieldsInViewSuggesting ("fish");
  115. // f is typed and suggestion is "fish"
  116. Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
  117. View.SetClipToScreen ();
  118. tf.Draw ();
  119. tf.PositionCursor ();
  120. TestHelpers.AssertDriverContentsAre ("fish", output);
  121. Assert.Equal ("f", tf.Text);
  122. // x is typed and suggestion should disappear
  123. Application.Driver?.SendKeys ('x', ConsoleKey.X, false, false, false);
  124. View.SetClipToScreen ();
  125. tf.Draw ();
  126. TestHelpers.AssertDriverContentsAre ("fx", output);
  127. Assert.Equal ("fx", tf.Text);
  128. Application.Top.Dispose ();
  129. }
  130. [Fact]
  131. [AutoInitShutdown]
  132. public void TestAutoAppend_ShowThenAccept_CasesDiffer ()
  133. {
  134. TextField tf = GetTextFieldsInView ();
  135. tf.Autocomplete = new AppendAutocomplete (tf);
  136. var generator = (SingleWordSuggestionGenerator)tf.Autocomplete.SuggestionGenerator;
  137. generator.AllSuggestions = new List<string> { "FISH" };
  138. View.SetClipToScreen ();
  139. tf.Draw ();
  140. tf.PositionCursor ();
  141. TestHelpers.AssertDriverContentsAre ("", output);
  142. tf.NewKeyDownEvent (Key.M);
  143. tf.NewKeyDownEvent (Key.Y);
  144. tf.NewKeyDownEvent (Key.Space);
  145. tf.NewKeyDownEvent (Key.F);
  146. Assert.Equal ("my f", tf.Text);
  147. // Even though there is no match on case we should still get the suggestion
  148. View.SetClipToScreen ();
  149. tf.Draw ();
  150. tf.PositionCursor ();
  151. TestHelpers.AssertDriverContentsAre ("my fISH", output);
  152. Assert.Equal ("my f", tf.Text);
  153. // When tab completing the case of the whole suggestion should be applied
  154. Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
  155. View.SetClipToScreen ();
  156. tf.Draw ();
  157. TestHelpers.AssertDriverContentsAre ("my FISH", output);
  158. Assert.Equal ("my FISH", tf.Text);
  159. Application.Top.Dispose ();
  160. }
  161. [Fact]
  162. [AutoInitShutdown]
  163. public void TestAutoAppend_ShowThenAccept_MatchCase ()
  164. {
  165. TextField tf = GetTextFieldsInView ();
  166. tf.Autocomplete = new AppendAutocomplete (tf);
  167. var generator = (SingleWordSuggestionGenerator)tf.Autocomplete.SuggestionGenerator;
  168. generator.AllSuggestions = new List<string> { "fish" };
  169. View.SetClipToScreen ();
  170. tf.Draw ();
  171. tf.PositionCursor ();
  172. TestHelpers.AssertDriverContentsAre ("", output);
  173. tf.NewKeyDownEvent (new Key ('f'));
  174. View.SetClipToScreen ();
  175. tf.Draw ();
  176. tf.PositionCursor ();
  177. TestHelpers.AssertDriverContentsAre ("fish", output);
  178. Assert.Equal ("f", tf.Text);
  179. Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
  180. View.SetClipToScreen ();
  181. tf.Draw ();
  182. TestHelpers.AssertDriverContentsAre ("fish", output);
  183. Assert.Equal ("fish", tf.Text);
  184. // Tab should autcomplete but not move focus
  185. Assert.Same (tf, Application.Top.Focused);
  186. // Second tab should move focus (nothing to autocomplete)
  187. Application.Driver?.SendKeys ('\t', ConsoleKey.Tab, false, false, false);
  188. Assert.NotSame (tf, Application.Top.Focused);
  189. Application.Top.Dispose ();
  190. }
  191. [Theory]
  192. [AutoInitShutdown]
  193. [InlineData ("ffffffffffffffffffffffffff", "ffffffffff")]
  194. [InlineData ("f234567890", "f234567890")]
  195. [InlineData ("fisérables", "fisérables")]
  196. public void TestAutoAppendRendering_ShouldNotOverspill (string overspillUsing, string expectRender)
  197. {
  198. TextField tf = GetTextFieldsInViewSuggesting (overspillUsing);
  199. // f is typed we should only see 'f' up to size of View (10)
  200. Application.Driver?.SendKeys ('f', ConsoleKey.F, false, false, false);
  201. View.SetClipToScreen ();
  202. tf.Draw ();
  203. tf.PositionCursor ();
  204. TestHelpers.AssertDriverContentsAre (expectRender, output);
  205. Assert.Equal ("f", tf.Text);
  206. Application.Top.Dispose ();
  207. }
  208. private TextField GetTextFieldsInView ()
  209. {
  210. var tf = new TextField { Width = 10 };
  211. var tf2 = new TextField { Y = 1, Width = 10 };
  212. Toplevel top = new ();
  213. top.Add (tf);
  214. top.Add (tf2);
  215. Application.Begin (top);
  216. Assert.Same (tf, top.Focused);
  217. return tf;
  218. }
  219. private TextField GetTextFieldsInViewSuggesting (params string [] suggestions)
  220. {
  221. TextField tf = GetTextFieldsInView ();
  222. tf.Autocomplete = new AppendAutocomplete (tf);
  223. var generator = (SingleWordSuggestionGenerator)tf.Autocomplete.SuggestionGenerator;
  224. generator.AllSuggestions = suggestions.ToList ();
  225. tf.Draw ();
  226. tf.PositionCursor ();
  227. TestHelpers.AssertDriverContentsAre ("", output);
  228. return tf;
  229. }
  230. }