TextBoxTests.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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.Templates;
  7. using Avalonia.Data;
  8. using Avalonia.Input;
  9. using Avalonia.Markup.Xaml.Data;
  10. using Avalonia.Platform;
  11. using Avalonia.UnitTests;
  12. using Moq;
  13. using Xunit;
  14. namespace Avalonia.Controls.UnitTests
  15. {
  16. public class TextBoxTests
  17. {
  18. [Fact]
  19. public void DefaultBindingMode_Should_Be_TwoWay()
  20. {
  21. Assert.Equal(
  22. BindingMode.TwoWay,
  23. TextBox.TextProperty.GetMetadata(typeof(TextBox)).DefaultBindingMode);
  24. }
  25. [Fact]
  26. public void CaretIndex_Can_Moved_To_Position_After_The_End_Of_Text_With_Arrow_Key()
  27. {
  28. using (UnitTestApplication.Start(Services))
  29. {
  30. var target = new TextBox
  31. {
  32. Template = CreateTemplate(),
  33. Text = "1234"
  34. };
  35. target.CaretIndex = 3;
  36. RaiseKeyEvent(target, Key.Right, 0);
  37. Assert.Equal(4, target.CaretIndex);
  38. }
  39. }
  40. [Fact]
  41. public void Press_Ctrl_A_Select_All_Text()
  42. {
  43. using (UnitTestApplication.Start(Services))
  44. {
  45. var target = new TextBox
  46. {
  47. Template = CreateTemplate(),
  48. Text = "1234"
  49. };
  50. RaiseKeyEvent(target, Key.A, InputModifiers.Control);
  51. Assert.Equal(0, target.SelectionStart);
  52. Assert.Equal(4, target.SelectionEnd);
  53. }
  54. }
  55. [Fact]
  56. public void Press_Ctrl_A_Select_All_Null_Text()
  57. {
  58. using (UnitTestApplication.Start(Services))
  59. {
  60. var target = new TextBox
  61. {
  62. Template = CreateTemplate()
  63. };
  64. RaiseKeyEvent(target, Key.A, InputModifiers.Control);
  65. Assert.Equal(0, target.SelectionStart);
  66. Assert.Equal(0, target.SelectionEnd);
  67. }
  68. }
  69. [Fact]
  70. public void Press_Ctrl_Z_Will_Not_Modify_Text()
  71. {
  72. using (UnitTestApplication.Start(Services))
  73. {
  74. var target = new TextBox
  75. {
  76. Template = CreateTemplate(),
  77. Text = "1234"
  78. };
  79. RaiseKeyEvent(target, Key.Z, InputModifiers.Control);
  80. Assert.Equal("1234", target.Text);
  81. }
  82. }
  83. [Fact]
  84. public void Typing_Beginning_With_0_Should_Not_Modify_Text_When_Bound_To_Int()
  85. {
  86. using (UnitTestApplication.Start(Services))
  87. {
  88. var source = new Class1();
  89. var target = new TextBox
  90. {
  91. DataContext = source,
  92. Template = CreateTemplate(),
  93. };
  94. target.ApplyTemplate();
  95. target.Bind(TextBox.TextProperty, new Binding(nameof(Class1.Foo), BindingMode.TwoWay));
  96. Assert.Equal("0", target.Text);
  97. target.CaretIndex = 1;
  98. target.RaiseEvent(new TextInputEventArgs
  99. {
  100. RoutedEvent = InputElement.TextInputEvent,
  101. Text = "2",
  102. });
  103. Assert.Equal("02", target.Text);
  104. }
  105. }
  106. [Fact]
  107. public void Control_Backspace_Should_Remove_The_Word_Before_The_Caret_If_There_Is_No_Selection()
  108. {
  109. using (UnitTestApplication.Start(Services))
  110. {
  111. TextBox textBox = new TextBox
  112. {
  113. Text = "First Second Third Fourth",
  114. CaretIndex = 5
  115. };
  116. // (First| Second Third Fourth)
  117. RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control);
  118. Assert.Equal(" Second Third Fourth", textBox.Text);
  119. // ( Second |Third Fourth)
  120. textBox.CaretIndex = 8;
  121. RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control);
  122. Assert.Equal(" Third Fourth", textBox.Text);
  123. // ( Thi|rd Fourth)
  124. textBox.CaretIndex = 4;
  125. RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control);
  126. Assert.Equal(" rd Fourth", textBox.Text);
  127. // ( rd F[ou]rth)
  128. textBox.SelectionStart = 5;
  129. textBox.SelectionEnd = 7;
  130. RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control);
  131. Assert.Equal(" rd Frth", textBox.Text);
  132. // ( |rd Frth)
  133. textBox.CaretIndex = 1;
  134. RaiseKeyEvent(textBox, Key.Back, InputModifiers.Control);
  135. Assert.Equal("rd Frth", textBox.Text);
  136. }
  137. }
  138. [Fact]
  139. public void Control_Delete_Should_Remove_The_Word_After_The_Caret_If_There_Is_No_Selection()
  140. {
  141. using (UnitTestApplication.Start(Services))
  142. {
  143. TextBox textBox = new TextBox
  144. {
  145. Text = "First Second Third Fourth",
  146. CaretIndex = 19
  147. };
  148. // (First Second Third |Fourth)
  149. RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control);
  150. Assert.Equal("First Second Third ", textBox.Text);
  151. // (First Second |Third )
  152. textBox.CaretIndex = 13;
  153. RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control);
  154. Assert.Equal("First Second ", textBox.Text);
  155. // (First Sec|ond )
  156. textBox.CaretIndex = 9;
  157. RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control);
  158. Assert.Equal("First Sec", textBox.Text);
  159. // (Fi[rs]t Sec )
  160. textBox.SelectionStart = 2;
  161. textBox.SelectionEnd = 4;
  162. RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control);
  163. Assert.Equal("Fit Sec", textBox.Text);
  164. // (Fit Sec| )
  165. textBox.Text += " ";
  166. textBox.CaretIndex = 7;
  167. RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control);
  168. Assert.Equal("Fit Sec", textBox.Text);
  169. }
  170. }
  171. [Fact]
  172. public void Setting_Text_Updates_CaretPosition()
  173. {
  174. using (UnitTestApplication.Start(Services))
  175. {
  176. var target = new TextBox
  177. {
  178. Text = "Initial Text",
  179. CaretIndex = 11
  180. };
  181. var invoked = false;
  182. target.GetObservable(TextBox.TextProperty).Skip(1).Subscribe(_ =>
  183. {
  184. // Caret index should be set before Text changed notification, as we don't want
  185. // to notify with an invalid CaretIndex.
  186. Assert.Equal(7, target.CaretIndex);
  187. invoked = true;
  188. });
  189. target.Text = "Changed";
  190. Assert.True(invoked);
  191. }
  192. }
  193. private static TestServices Services => TestServices.MockThreadingInterface.With(
  194. standardCursorFactory: Mock.Of<IStandardCursorFactory>());
  195. private IControlTemplate CreateTemplate()
  196. {
  197. return new FuncControlTemplate<TextBox>(control =>
  198. new TextPresenter
  199. {
  200. Name = "PART_TextPresenter",
  201. [!!TextPresenter.TextProperty] = new Binding
  202. {
  203. Path = "Text",
  204. Mode = BindingMode.TwoWay,
  205. Priority = BindingPriority.TemplatedParent,
  206. RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
  207. },
  208. });
  209. }
  210. private void RaiseKeyEvent(TextBox textBox, Key key, InputModifiers inputModifiers)
  211. {
  212. textBox.RaiseEvent(new KeyEventArgs
  213. {
  214. RoutedEvent = InputElement.KeyDownEvent,
  215. Modifiers = inputModifiers,
  216. Key = key
  217. });
  218. }
  219. private class Class1 : NotifyingBase
  220. {
  221. private int _foo;
  222. public int Foo
  223. {
  224. get { return _foo; }
  225. set { _foo = value; RaisePropertyChanged(); }
  226. }
  227. }
  228. }
  229. }