TextBoxTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using System.Reactive.Linq;
  5. using Avalonia.Controls.Presenters;
  6. using Avalonia.Controls.Primitives;
  7. using Avalonia.Controls.Templates;
  8. using Avalonia.Data;
  9. using Avalonia.Input;
  10. using Avalonia.Markup.Data;
  11. using Avalonia.Media;
  12. using Avalonia.Platform;
  13. using Avalonia.UnitTests;
  14. using Moq;
  15. using Xunit;
  16. namespace Avalonia.Controls.UnitTests
  17. {
  18. public class TextBoxTests
  19. {
  20. [Fact]
  21. public void DefaultBindingMode_Should_Be_TwoWay()
  22. {
  23. Assert.Equal(
  24. BindingMode.TwoWay,
  25. TextBox.TextProperty.GetMetadata(typeof(TextBox)).DefaultBindingMode);
  26. }
  27. [Fact]
  28. public void CaretIndex_Can_Moved_To_Position_After_The_End_Of_Text_With_Arrow_Key()
  29. {
  30. using (UnitTestApplication.Start(Services))
  31. {
  32. var target = new TextBox
  33. {
  34. Template = CreateTemplate(),
  35. Text = "1234"
  36. };
  37. target.CaretIndex = 3;
  38. RaiseKeyEvent(target, Key.Right, 0);
  39. Assert.Equal(4, target.CaretIndex);
  40. }
  41. }
  42. [Fact]
  43. public void Press_Ctrl_A_Select_All_Text()
  44. {
  45. using (UnitTestApplication.Start(Services))
  46. {
  47. var target = new TextBox
  48. {
  49. Template = CreateTemplate(),
  50. Text = "1234"
  51. };
  52. RaiseKeyEvent(target, Key.A, InputModifiers.Control);
  53. Assert.Equal(0, target.SelectionStart);
  54. Assert.Equal(4, target.SelectionEnd);
  55. }
  56. }
  57. [Fact]
  58. public void Press_Ctrl_A_Select_All_Null_Text()
  59. {
  60. using (UnitTestApplication.Start(Services))
  61. {
  62. var target = new TextBox
  63. {
  64. Template = CreateTemplate()
  65. };
  66. RaiseKeyEvent(target, Key.A, InputModifiers.Control);
  67. Assert.Equal(0, target.SelectionStart);
  68. Assert.Equal(0, target.SelectionEnd);
  69. }
  70. }
  71. [Fact]
  72. public void Press_Ctrl_Z_Will_Not_Modify_Text()
  73. {
  74. using (UnitTestApplication.Start(Services))
  75. {
  76. var target = new TextBox
  77. {
  78. Template = CreateTemplate(),
  79. Text = "1234"
  80. };
  81. RaiseKeyEvent(target, Key.Z, InputModifiers.Control);
  82. Assert.Equal("1234", target.Text);
  83. }
  84. }
  85. [Fact]
  86. public void Typing_Beginning_With_0_Should_Not_Modify_Text_When_Bound_To_Int()
  87. {
  88. using (UnitTestApplication.Start(Services))
  89. {
  90. var source = new Class1();
  91. var target = new TextBox
  92. {
  93. DataContext = source,
  94. Template = CreateTemplate(),
  95. };
  96. target.ApplyTemplate();
  97. target.Bind(TextBox.TextProperty, new Binding(nameof(Class1.Foo), BindingMode.TwoWay));
  98. Assert.Equal("0", target.Text);
  99. target.CaretIndex = 1;
  100. target.RaiseEvent(new TextInputEventArgs
  101. {
  102. RoutedEvent = InputElement.TextInputEvent,
  103. Text = "2",
  104. });
  105. Assert.Equal("02", target.Text);
  106. }
  107. }
  108. [Fact]
  109. public void Control_Backspace_Should_Remove_The_Word_Before_The_Caret_If_There_Is_No_Selection()
  110. {
  111. using (UnitTestApplication.Start(Services))
  112. {
  113. TextBox textBox = new TextBox
  114. {
  115. Text = "First Second Third Fourth",
  116. CaretIndex = 5
  117. };
  118. // (First| Second Third Fourth)
  119. RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control);
  120. Assert.Equal(" Second Third Fourth", textBox.Text);
  121. // ( Second |Third Fourth)
  122. textBox.CaretIndex = 8;
  123. RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control);
  124. Assert.Equal(" Third Fourth", textBox.Text);
  125. // ( Thi|rd Fourth)
  126. textBox.CaretIndex = 4;
  127. RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control);
  128. Assert.Equal(" rd Fourth", textBox.Text);
  129. // ( rd F[ou]rth)
  130. textBox.SelectionStart = 5;
  131. textBox.SelectionEnd = 7;
  132. RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control);
  133. Assert.Equal(" rd Frth", textBox.Text);
  134. // ( |rd Frth)
  135. textBox.CaretIndex = 1;
  136. RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control);
  137. Assert.Equal("rd Frth", textBox.Text);
  138. }
  139. }
  140. [Fact]
  141. public void Control_Delete_Should_Remove_The_Word_After_The_Caret_If_There_Is_No_Selection()
  142. {
  143. using (UnitTestApplication.Start(Services))
  144. {
  145. TextBox textBox = new TextBox
  146. {
  147. Text = "First Second Third Fourth",
  148. CaretIndex = 19
  149. };
  150. // (First Second Third |Fourth)
  151. RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control);
  152. Assert.Equal("First Second Third ", textBox.Text);
  153. // (First Second |Third )
  154. textBox.CaretIndex = 13;
  155. RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control);
  156. Assert.Equal("First Second ", textBox.Text);
  157. // (First Sec|ond )
  158. textBox.CaretIndex = 9;
  159. RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control);
  160. Assert.Equal("First Sec", textBox.Text);
  161. // (Fi[rs]t Sec )
  162. textBox.SelectionStart = 2;
  163. textBox.SelectionEnd = 4;
  164. RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control);
  165. Assert.Equal("Fit Sec", textBox.Text);
  166. // (Fit Sec| )
  167. textBox.Text += " ";
  168. textBox.CaretIndex = 7;
  169. RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control);
  170. Assert.Equal("Fit Sec", textBox.Text);
  171. }
  172. }
  173. [Fact]
  174. public void Setting_SelectionStart_To_SelectionEnd_Sets_CaretPosition_To_SelectionStart()
  175. {
  176. using (UnitTestApplication.Start(Services))
  177. {
  178. var textBox = new TextBox
  179. {
  180. Text = "0123456789"
  181. };
  182. textBox.SelectionStart = 2;
  183. textBox.SelectionEnd = 2;
  184. Assert.Equal(2, textBox.CaretIndex);
  185. }
  186. }
  187. [Fact]
  188. public void Setting_Text_Updates_CaretPosition()
  189. {
  190. using (UnitTestApplication.Start(Services))
  191. {
  192. var target = new TextBox
  193. {
  194. Text = "Initial Text",
  195. CaretIndex = 11
  196. };
  197. var invoked = false;
  198. target.GetObservable(TextBox.TextProperty).Skip(1).Subscribe(_ =>
  199. {
  200. // Caret index should be set before Text changed notification, as we don't want
  201. // to notify with an invalid CaretIndex.
  202. Assert.Equal(7, target.CaretIndex);
  203. invoked = true;
  204. });
  205. target.Text = "Changed";
  206. Assert.True(invoked);
  207. }
  208. }
  209. [Fact]
  210. public void Press_Enter_Does_Not_Accept_Return()
  211. {
  212. using (UnitTestApplication.Start(Services))
  213. {
  214. var target = new TextBox
  215. {
  216. Template = CreateTemplate(),
  217. AcceptsReturn = false,
  218. Text = "1234"
  219. };
  220. RaiseKeyEvent(target, Key.Enter, 0);
  221. Assert.Equal("1234", target.Text);
  222. }
  223. }
  224. [Fact]
  225. public void Press_Enter_Add_Default_Newline()
  226. {
  227. using (UnitTestApplication.Start(Services))
  228. {
  229. var target = new TextBox
  230. {
  231. Template = CreateTemplate(),
  232. AcceptsReturn = true
  233. };
  234. RaiseKeyEvent(target, Key.Enter, 0);
  235. Assert.Equal(Environment.NewLine, target.Text);
  236. }
  237. }
  238. [Fact]
  239. public void Press_Enter_Add_Custom_Newline()
  240. {
  241. using (UnitTestApplication.Start(Services))
  242. {
  243. var target = new TextBox
  244. {
  245. Template = CreateTemplate(),
  246. AcceptsReturn = true,
  247. NewLine = "Test"
  248. };
  249. RaiseKeyEvent(target, Key.Enter, 0);
  250. Assert.Equal("Test", target.Text);
  251. }
  252. }
  253. [Theory]
  254. [InlineData(new object[] { false, TextWrapping.NoWrap, ScrollBarVisibility.Hidden })]
  255. [InlineData(new object[] { false, TextWrapping.Wrap, ScrollBarVisibility.Hidden })]
  256. [InlineData(new object[] { true, TextWrapping.NoWrap, ScrollBarVisibility.Auto })]
  257. [InlineData(new object[] { true, TextWrapping.Wrap, ScrollBarVisibility.Disabled })]
  258. public void Has_Correct_Horizontal_ScrollBar_Visibility(
  259. bool acceptsReturn,
  260. TextWrapping wrapping,
  261. ScrollBarVisibility expected)
  262. {
  263. using (UnitTestApplication.Start(Services))
  264. {
  265. var target = new TextBox
  266. {
  267. AcceptsReturn = acceptsReturn,
  268. TextWrapping = wrapping,
  269. };
  270. Assert.Equal(expected, ScrollViewer.GetHorizontalScrollBarVisibility(target));
  271. }
  272. }
  273. private static TestServices Services => TestServices.MockThreadingInterface.With(
  274. standardCursorFactory: Mock.Of<IStandardCursorFactory>());
  275. private IControlTemplate CreateTemplate()
  276. {
  277. return new FuncControlTemplate<TextBox>(control =>
  278. new TextPresenter
  279. {
  280. Name = "PART_TextPresenter",
  281. [!!TextPresenter.TextProperty] = new Binding
  282. {
  283. Path = "Text",
  284. Mode = BindingMode.TwoWay,
  285. Priority = BindingPriority.TemplatedParent,
  286. RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
  287. },
  288. });
  289. }
  290. private void RaiseKeyEvent(TextBox textBox, Key key, InputModifiers inputModifiers)
  291. {
  292. textBox.RaiseEvent(new KeyEventArgs
  293. {
  294. RoutedEvent = InputElement.KeyDownEvent,
  295. Modifiers = inputModifiers,
  296. Key = key
  297. });
  298. }
  299. private class Class1 : NotifyingBase
  300. {
  301. private int _foo;
  302. public int Foo
  303. {
  304. get { return _foo; }
  305. set { _foo = value; RaisePropertyChanged(); }
  306. }
  307. }
  308. }
  309. }