AppendAutocompleteTests.cs 9.0 KB

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