KeyboardEventTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. using UnitTests;
  2. using Xunit.Abstractions;
  3. // Alias Console to MockConsole so we don't accidentally use Console
  4. namespace UnitTests_Parallelizable.ViewTests;
  5. [Collection ("Global Test Setup")]
  6. public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
  7. {
  8. /// <summary>
  9. /// This tests that when a new key down event is sent to the view will fire the key-down related
  10. /// events: KeyDown and KeyDownNotHandled. Note that KeyUp is independent.
  11. /// </summary>
  12. [Theory]
  13. [MemberData (nameof (AllViewTypes))]
  14. public void AllViews_NewKeyDownEvent_All_EventsFire (Type viewType)
  15. {
  16. var view = CreateInstanceIfNotGeneric (viewType);
  17. if (view == null)
  18. {
  19. output.WriteLine ($"ERROR: Skipping generic view: {viewType}");
  20. return;
  21. }
  22. output.WriteLine ($"Testing {viewType}");
  23. var keyDown = false;
  24. view.KeyDown += (s, a) =>
  25. {
  26. a.Handled = false; // don't handle it so the other events are called
  27. keyDown = true;
  28. };
  29. var keyDownNotHandled = false;
  30. view.KeyDownNotHandled += (s, a) =>
  31. {
  32. a.Handled = true;
  33. keyDownNotHandled = true;
  34. };
  35. // Key.Empty is invalid, but it's used here to test that the event is fired
  36. Assert.True (view.NewKeyDownEvent (Key.Empty)); // this will be true because the ProcessKeyDown event handled it
  37. Assert.True (keyDown);
  38. Assert.True (keyDownNotHandled);
  39. view.Dispose ();
  40. }
  41. /// <summary>
  42. /// This tests that when a new key up event is sent to the view the view will fire the 1 key-up related event:
  43. /// KeyUp
  44. /// </summary>
  45. [Theory]
  46. [MemberData (nameof (AllViewTypes))]
  47. public void AllViews_NewKeyUpEvent_All_EventsFire (Type viewType)
  48. {
  49. var view = CreateInstanceIfNotGeneric (viewType);
  50. if (view == null)
  51. {
  52. output.WriteLine ($"ERROR: Generic view {viewType}");
  53. return;
  54. }
  55. output.WriteLine ($"Testing {view.GetType ().Name}");
  56. var keyUp = false;
  57. view.KeyUp += (s, a) =>
  58. {
  59. a.Handled = true;
  60. keyUp = true;
  61. };
  62. Assert.True (view.NewKeyUpEvent (Key.A)); // this will be true because the KeyUp event handled it
  63. Assert.True (keyUp);
  64. view.Dispose ();
  65. }
  66. [Theory]
  67. [InlineData (true, false, false)]
  68. [InlineData (true, true, false)]
  69. [InlineData (true, true, true)]
  70. public void NewKeyDownUpEvents_Events_Are_Raised_With_Only_Key_Modifiers (bool shift, bool alt, bool control)
  71. {
  72. var keyDown = false;
  73. var keyDownNotHandled = false;
  74. var keyUp = false;
  75. var view = new OnNewKeyTestView ();
  76. view.CancelVirtualMethods = false;
  77. view.KeyDown += (s, e) =>
  78. {
  79. Assert.Equal (KeyCode.Null, e.KeyCode & ~KeyCode.CtrlMask & ~KeyCode.AltMask & ~KeyCode.ShiftMask);
  80. Assert.Equal (shift, e.IsShift);
  81. Assert.Equal (alt, e.IsAlt);
  82. Assert.Equal (control, e.IsCtrl);
  83. Assert.False (keyDown);
  84. Assert.True (view.OnKeyDownCalled);
  85. keyDown = true;
  86. };
  87. view.KeyDownNotHandled += (s, e) => { keyDownNotHandled = true; };
  88. view.KeyUp += (s, e) =>
  89. {
  90. Assert.Equal (KeyCode.Null, e.KeyCode & ~KeyCode.CtrlMask & ~KeyCode.AltMask & ~KeyCode.ShiftMask);
  91. Assert.Equal (shift, e.IsShift);
  92. Assert.Equal (alt, e.IsAlt);
  93. Assert.Equal (control, e.IsCtrl);
  94. Assert.False (keyUp);
  95. Assert.True (view.OnKeyUpCalled);
  96. keyUp = true;
  97. };
  98. view.NewKeyDownEvent (
  99. new (
  100. KeyCode.Null
  101. | (shift ? KeyCode.ShiftMask : 0)
  102. | (alt ? KeyCode.AltMask : 0)
  103. | (control ? KeyCode.CtrlMask : 0)
  104. )
  105. );
  106. Assert.True (keyDownNotHandled);
  107. Assert.True (view.OnKeyDownCalled);
  108. Assert.True (view.OnProcessKeyDownCalled);
  109. view.NewKeyUpEvent (
  110. new (
  111. KeyCode.Null
  112. | (shift ? KeyCode.ShiftMask : 0)
  113. | (alt ? KeyCode.AltMask : 0)
  114. | (control ? KeyCode.CtrlMask : 0)
  115. )
  116. );
  117. Assert.True (keyUp);
  118. Assert.True (view.OnKeyUpCalled);
  119. }
  120. [Fact]
  121. public void NewKeyDownEvent_Handled_True_Stops_Processing ()
  122. {
  123. var keyDown = false;
  124. var keyDownNotHandled = false;
  125. var view = new OnNewKeyTestView ();
  126. Assert.True (view.CanFocus);
  127. view.CancelVirtualMethods = false;
  128. view.KeyDown += (s, e) =>
  129. {
  130. Assert.Equal (KeyCode.A, e.KeyCode);
  131. Assert.False (keyDown);
  132. Assert.True (view.OnKeyDownCalled);
  133. e.Handled = true;
  134. keyDown = true;
  135. };
  136. view.KeyDownNotHandled += (s, e) =>
  137. {
  138. Assert.Equal (KeyCode.A, e.KeyCode);
  139. Assert.False (keyDownNotHandled);
  140. Assert.False (view.OnProcessKeyDownCalled);
  141. e.Handled = true;
  142. keyDownNotHandled = true;
  143. };
  144. view.NewKeyDownEvent (Key.A);
  145. Assert.True (keyDown);
  146. Assert.False (keyDownNotHandled);
  147. Assert.True (view.OnKeyDownCalled);
  148. Assert.False (view.OnProcessKeyDownCalled);
  149. }
  150. [Fact]
  151. public void NewKeyDownEvent_KeyDown_Handled_Stops_Processing ()
  152. {
  153. var view = new View ();
  154. var keyDownNotHandled = false;
  155. var setHandledTo = false;
  156. view.KeyDown += (s, e) =>
  157. {
  158. e.Handled = setHandledTo;
  159. Assert.Equal (setHandledTo, e.Handled);
  160. Assert.Equal (KeyCode.N, e.KeyCode);
  161. };
  162. view.KeyDownNotHandled += (s, e) =>
  163. {
  164. keyDownNotHandled = true;
  165. Assert.False (e.Handled);
  166. Assert.Equal (KeyCode.N, e.KeyCode);
  167. };
  168. view.NewKeyDownEvent (Key.N);
  169. Assert.True (keyDownNotHandled);
  170. keyDownNotHandled = false;
  171. setHandledTo = true;
  172. view.NewKeyDownEvent (Key.N);
  173. Assert.False (keyDownNotHandled);
  174. }
  175. [Fact]
  176. public void NewKeyDownEvent_ProcessKeyDown_Handled_Stops_Processing ()
  177. {
  178. var keyDown = false;
  179. var keyDownNotHandled = false;
  180. var view = new OnNewKeyTestView ();
  181. Assert.True (view.CanFocus);
  182. view.CancelVirtualMethods = false;
  183. view.KeyDown += (s, e) =>
  184. {
  185. Assert.Equal (KeyCode.A, e.KeyCode);
  186. Assert.False (keyDown);
  187. Assert.True (view.OnKeyDownCalled);
  188. e.Handled = false;
  189. keyDown = true;
  190. };
  191. view.KeyDownNotHandled += (s, e) =>
  192. {
  193. Assert.Equal (KeyCode.A, e.KeyCode);
  194. Assert.False (keyDownNotHandled);
  195. Assert.True (view.OnProcessKeyDownCalled);
  196. e.Handled = true;
  197. keyDownNotHandled = true;
  198. };
  199. view.NewKeyDownEvent (Key.A);
  200. Assert.True (keyDown);
  201. Assert.True (keyDownNotHandled);
  202. Assert.True (view.OnKeyDownCalled);
  203. Assert.True (view.OnProcessKeyDownCalled);
  204. }
  205. [Fact]
  206. public void NewKeyUpEvent_KeyUp_Handled_True_Stops_Processing ()
  207. {
  208. var keyUp = false;
  209. var view = new OnNewKeyTestView ();
  210. Assert.True (view.CanFocus);
  211. view.CancelVirtualMethods = false;
  212. view.KeyUp += (s, e) =>
  213. {
  214. Assert.Equal (KeyCode.A, e.KeyCode);
  215. Assert.False (keyUp);
  216. Assert.False (view.OnProcessKeyDownCalled);
  217. e.Handled = true;
  218. keyUp = true;
  219. };
  220. view.NewKeyUpEvent (Key.A);
  221. Assert.True (keyUp);
  222. Assert.True (view.OnKeyUpCalled);
  223. Assert.False (view.OnKeyDownCalled);
  224. Assert.False (view.OnProcessKeyDownCalled);
  225. }
  226. [Theory]
  227. [InlineData (null, null)]
  228. [InlineData (true, true)]
  229. [InlineData (false, false)]
  230. public void InvokeCommands_Returns_Nullable_Properly (bool? toReturn, bool? expected)
  231. {
  232. var view = new KeyBindingsTestView ();
  233. view.CommandReturns = toReturn;
  234. bool? result = view.InvokeCommands (Key.A);
  235. Assert.Equal (expected, result);
  236. }
  237. /// <summary>A view that overrides the OnKey* methods so we can test that they are called.</summary>
  238. public class KeyBindingsTestView : View
  239. {
  240. public KeyBindingsTestView ()
  241. {
  242. CanFocus = true;
  243. AddCommand (Command.HotKey, () => CommandReturns);
  244. KeyBindings.Add (Key.A, Command.HotKey);
  245. }
  246. public bool? CommandReturns { get; set; }
  247. }
  248. /// <summary>A view that overrides the OnKey* methods so we can test that they are called.</summary>
  249. public class OnNewKeyTestView : View
  250. {
  251. public OnNewKeyTestView () { CanFocus = true; }
  252. public bool CancelVirtualMethods { set; private get; }
  253. public bool OnKeyDownCalled { get; set; }
  254. public bool OnProcessKeyDownCalled { get; set; }
  255. public bool OnKeyUpCalled { get; set; }
  256. public override string Text { get; set; }
  257. protected override bool OnKeyDown (Key keyEvent)
  258. {
  259. OnKeyDownCalled = true;
  260. return CancelVirtualMethods;
  261. }
  262. public override bool OnKeyUp (Key keyEvent)
  263. {
  264. OnKeyUpCalled = true;
  265. return CancelVirtualMethods;
  266. }
  267. protected override bool OnKeyDownNotHandled (Key keyEvent)
  268. {
  269. OnProcessKeyDownCalled = true;
  270. return CancelVirtualMethods;
  271. }
  272. }
  273. }