ShortcutTests.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. using JetBrains.Annotations;
  2. using UnitTests;
  3. namespace UnitTests.ViewsTests;
  4. [TestSubject (typeof (Shortcut))]
  5. public class ShortcutTests
  6. {
  7. [Theory]
  8. // 0123456789
  9. // " C 0 A "
  10. [InlineData (-1, 0)]
  11. [InlineData (0, 1)]
  12. [InlineData (1, 1)]
  13. [InlineData (2, 1)]
  14. [InlineData (3, 1)]
  15. [InlineData (4, 1)]
  16. [InlineData (5, 1)]
  17. [InlineData (6, 1)]
  18. [InlineData (7, 1)]
  19. [InlineData (8, 1)]
  20. [InlineData (9, 0)]
  21. public void MouseClick_Raises_Accepted (int x, int expectedAccepted)
  22. {
  23. Application.Begin (new Runnable<bool> ());
  24. var shortcut = new Shortcut
  25. {
  26. Key = Key.A,
  27. Text = "0",
  28. Title = "C"
  29. };
  30. Application.TopRunnableView.Add (shortcut);
  31. Application.TopRunnableView.Layout ();
  32. var accepted = 0;
  33. shortcut.Accepting += (s, e) => accepted++;
  34. Application.RaiseMouseEvent (
  35. new ()
  36. {
  37. ScreenPosition = new (x, 0),
  38. Flags = MouseFlags.Button1Clicked
  39. });
  40. Assert.Equal (expectedAccepted, accepted);
  41. Application.TopRunnableView.Dispose ();
  42. Application.ResetState (true);
  43. }
  44. [Theory]
  45. // 0123456789
  46. // " C 0 A "
  47. [InlineData (-1, 0, 0, 0, 0)]
  48. [InlineData (0, 0, 1, 1, 1)] // mouseX = 0 is on the CommandView.Margin, so Shortcut will get MouseEvent for click
  49. [InlineData (1, 0, 1, 1, 1)] // mouseX = 1 is on the CommandView, so CommandView will get MouseEvent for click
  50. [InlineData (2, 0, 1, 1, 1)] // mouseX = 2 is on the CommandView.Margin, so Shortcut will get MouseEvent for click
  51. [InlineData (3, 0, 1, 1, 1)]
  52. [InlineData (4, 0, 1, 1, 1)]
  53. [InlineData (5, 0, 1, 1, 1)]
  54. [InlineData (6, 0, 1, 1, 1)]
  55. [InlineData (7, 0, 1, 1, 1)]
  56. [InlineData (8, 0, 1, 1, 1)]
  57. [InlineData (9, 0, 0, 0, 0)]
  58. public void MouseClick_Default_CommandView_Raises_Accepted_Selected_Correctly (
  59. int mouseX,
  60. int expectedCommandViewAccepted,
  61. int expectedCommandViewActivated,
  62. int expectedShortcutAccepted,
  63. int expectedShortcutActivated
  64. )
  65. {
  66. Application.Begin (new Runnable<bool> ());
  67. var shortcut = new Shortcut
  68. {
  69. Title = "C",
  70. Key = Key.A,
  71. HelpText = "0"
  72. };
  73. var commandViewAcceptCount = 0;
  74. shortcut.CommandView.Accepting += (s, e) => { commandViewAcceptCount++; };
  75. var commandViewActivatingCount = 0;
  76. shortcut.CommandView.Activating += (s, e) => { commandViewActivatingCount++; };
  77. var shortcutAcceptCount = 0;
  78. shortcut.Accepting += (s, e) => { shortcutAcceptCount++; };
  79. var shortcutSelectCount = 0;
  80. shortcut.Activating += (s, e) => { shortcutSelectCount++; };
  81. Application.TopRunnableView.Add (shortcut);
  82. Application.TopRunnableView.SetRelativeLayout (new (100, 100));
  83. Application.TopRunnableView.LayoutSubViews ();
  84. Application.RaiseMouseEvent (
  85. new ()
  86. {
  87. ScreenPosition = new (mouseX, 0),
  88. Flags = MouseFlags.Button1Clicked
  89. });
  90. Assert.Equal (expectedShortcutAccepted, shortcutAcceptCount);
  91. Assert.Equal (expectedShortcutActivated, shortcutSelectCount);
  92. Assert.Equal (expectedCommandViewAccepted, commandViewAcceptCount);
  93. Assert.Equal (expectedCommandViewActivated, commandViewActivatingCount);
  94. Application.TopRunnableView.Dispose ();
  95. Application.ResetState (true);
  96. }
  97. [Theory]
  98. // 0123456789
  99. // " C 0 A "
  100. [InlineData (-1, 0, 0)]
  101. [InlineData (0, 1, 0)]
  102. [InlineData (1, 1, 0)]
  103. [InlineData (2, 1, 0)]
  104. [InlineData (3, 1, 0)]
  105. [InlineData (4, 1, 0)]
  106. [InlineData (5, 1, 0)]
  107. [InlineData (6, 1, 0)]
  108. [InlineData (7, 1, 0)]
  109. [InlineData (8, 1, 0)]
  110. [InlineData (9, 0, 0)]
  111. public void MouseClick_Button_CommandView_Raises_Shortcut_Accepted (int mouseX, int expectedAccept, int expectedButtonAccept)
  112. {
  113. Application.Begin (new Runnable<bool> ());
  114. var shortcut = new Shortcut
  115. {
  116. Key = Key.A,
  117. Text = "0"
  118. };
  119. shortcut.CommandView = new Button
  120. {
  121. Title = "C",
  122. NoDecorations = true,
  123. NoPadding = true,
  124. CanFocus = false
  125. };
  126. var buttonAccepted = 0;
  127. shortcut.CommandView.Accepting += (s, e) => { buttonAccepted++; };
  128. Application.TopRunnableView.Add (shortcut);
  129. Application.TopRunnableView.SetRelativeLayout (new (100, 100));
  130. Application.TopRunnableView.LayoutSubViews ();
  131. var accepted = 0;
  132. shortcut.Accepting += (s, e) => { accepted++; };
  133. Application.RaiseMouseEvent (
  134. new ()
  135. {
  136. ScreenPosition = new (mouseX, 0),
  137. Flags = MouseFlags.Button1Clicked
  138. });
  139. Assert.Equal (expectedAccept, accepted);
  140. Assert.Equal (expectedButtonAccept, buttonAccepted);
  141. Application.TopRunnableView.Dispose ();
  142. Application.ResetState (true);
  143. }
  144. [Theory]
  145. // 01234567890
  146. // " ☑C 0 A "
  147. [InlineData (-1, 0, 0)]
  148. [InlineData (0, 1, 0)]
  149. [InlineData (1, 1, 0)]
  150. [InlineData (2, 1, 0)]
  151. [InlineData (3, 1, 0)]
  152. [InlineData (4, 1, 0)]
  153. [InlineData (5, 1, 0)]
  154. [InlineData (6, 1, 0)]
  155. [InlineData (7, 1, 0)]
  156. [InlineData (8, 1, 0)]
  157. [InlineData (9, 1, 0)]
  158. [InlineData (10, 1, 0)]
  159. public void MouseClick_CheckBox_CommandView_Raises_Shortcut_Accepted_Selected_Correctly (int mouseX, int expectedAccepted, int expectedCheckboxAccepted)
  160. {
  161. Application.Begin (new Runnable<bool> ());
  162. var shortcut = new Shortcut
  163. {
  164. Key = Key.A,
  165. Text = "0"
  166. };
  167. shortcut.CommandView = new CheckBox
  168. {
  169. Title = "C",
  170. CanFocus = false
  171. };
  172. var checkboxAccepted = 0;
  173. shortcut.CommandView.Accepting += (s, e) => { checkboxAccepted++; };
  174. var checkboxActivated = 0;
  175. shortcut.CommandView.Activating += (s, e) =>
  176. {
  177. if (e.Handled)
  178. {
  179. return;
  180. }
  181. checkboxActivated++;
  182. };
  183. Application.TopRunnableView.Add (shortcut);
  184. Application.TopRunnableView.SetRelativeLayout (new (100, 100));
  185. Application.TopRunnableView.LayoutSubViews ();
  186. var activatingCount = 0;
  187. shortcut.Activating += (s, e) =>
  188. {
  189. activatingCount++;
  190. };
  191. var accepted = 0;
  192. shortcut.Accepting += (s, e) =>
  193. {
  194. accepted++;
  195. e.Handled = true;
  196. };
  197. Application.RaiseMouseEvent (
  198. new ()
  199. {
  200. ScreenPosition = new (mouseX, 0),
  201. Flags = MouseFlags.Button1Clicked
  202. });
  203. Assert.Equal (expectedAccepted, accepted);
  204. Assert.Equal (expectedAccepted, activatingCount);
  205. Assert.Equal (expectedCheckboxAccepted, checkboxAccepted);
  206. Assert.Equal (expectedCheckboxAccepted, checkboxActivated);
  207. Application.TopRunnableView.Dispose ();
  208. Application.ResetState (true);
  209. }
  210. [Theory]
  211. [InlineData (true, KeyCode.A, 1, 1)]
  212. [InlineData (true, KeyCode.C, 1, 1)]
  213. [InlineData (true, KeyCode.C | KeyCode.AltMask, 1, 1)]
  214. [InlineData (true, KeyCode.Enter, 1, 1)]
  215. [InlineData (true, KeyCode.Space, 1, 1)]
  216. [InlineData (true, KeyCode.F1, 0, 0)]
  217. [InlineData (false, KeyCode.A, 1, 1)]
  218. [InlineData (false, KeyCode.C, 1, 1)]
  219. [InlineData (false, KeyCode.C | KeyCode.AltMask, 1, 1)]
  220. [InlineData (false, KeyCode.Enter, 0, 0)]
  221. [InlineData (false, KeyCode.Space, 0, 0)]
  222. [InlineData (false, KeyCode.F1, 0, 0)]
  223. public void KeyDown_Raises_Accepted_Selected (bool canFocus, KeyCode key, int expectedAccept, int expectedSelect)
  224. {
  225. Application.Begin (new Runnable<bool> ());
  226. var shortcut = new Shortcut
  227. {
  228. Key = Key.A,
  229. Text = "0",
  230. Title = "_C",
  231. CanFocus = canFocus
  232. };
  233. Application.TopRunnableView.Add (shortcut);
  234. shortcut.SetFocus ();
  235. Assert.Equal (canFocus, shortcut.HasFocus);
  236. var accepted = 0;
  237. shortcut.Accepting += (s, e) => accepted++;
  238. var selected = 0;
  239. shortcut.Activating += (s, e) => selected++;
  240. Application.RaiseKeyDownEvent (key);
  241. Assert.Equal (expectedAccept, accepted);
  242. Assert.Equal (expectedSelect, selected);
  243. Application.TopRunnableView.Dispose ();
  244. Application.ResetState (true);
  245. }
  246. [Theory]
  247. [InlineData (KeyCode.A, 1)]
  248. [InlineData (KeyCode.C, 1)]
  249. [InlineData (KeyCode.C | KeyCode.AltMask, 1)]
  250. [InlineData (KeyCode.Enter, 1)]
  251. [InlineData (KeyCode.Space, 1)]
  252. [InlineData (KeyCode.F1, 0)]
  253. public void KeyDown_App_Scope_Invokes_Accept (KeyCode key, int expectedAccept)
  254. {
  255. Application.Begin (new Runnable<bool> ());
  256. var shortcut = new Shortcut
  257. {
  258. Key = Key.A,
  259. Text = "0",
  260. Title = "_C"
  261. };
  262. Application.TopRunnableView.Add (shortcut);
  263. shortcut.BindKeyToApplication = true;
  264. Application.TopRunnableView.SetFocus ();
  265. var accepted = 0;
  266. shortcut.Accepting += (s, e) => accepted++;
  267. Application.RaiseKeyDownEvent (key);
  268. Assert.Equal (expectedAccept, accepted);
  269. Application.TopRunnableView.Dispose ();
  270. Application.ResetState (true);
  271. }
  272. [Theory]
  273. [InlineData (true, KeyCode.A, 1)]
  274. [InlineData (true, KeyCode.C, 1)]
  275. [InlineData (true, KeyCode.C | KeyCode.AltMask, 1)]
  276. [InlineData (true, KeyCode.Enter, 1)]
  277. [InlineData (true, KeyCode.Space, 1)]
  278. [InlineData (true, KeyCode.F1, 0)]
  279. [InlineData (false, KeyCode.A, 1)]
  280. [InlineData (false, KeyCode.C, 1)]
  281. [InlineData (false, KeyCode.C | KeyCode.AltMask, 1)]
  282. [InlineData (false, KeyCode.Enter, 0)]
  283. [InlineData (false, KeyCode.Space, 0)]
  284. [InlineData (false, KeyCode.F1, 0)]
  285. [AutoInitShutdown]
  286. public void KeyDown_Invokes_Action (bool canFocus, KeyCode key, int expectedAction)
  287. {
  288. var current = new Runnable ();
  289. var shortcut = new Shortcut
  290. {
  291. Key = Key.A,
  292. Text = "0",
  293. Title = "_C",
  294. CanFocus = canFocus
  295. };
  296. current.Add (shortcut);
  297. Application.Begin (current);
  298. Assert.Equal (canFocus, shortcut.HasFocus);
  299. var action = 0;
  300. shortcut.Action += () => action++;
  301. Application.RaiseKeyDownEvent (key);
  302. Assert.Equal (expectedAction, action);
  303. current.Dispose ();
  304. }
  305. [Theory]
  306. [InlineData (true, KeyCode.A, 1)]
  307. [InlineData (true, KeyCode.C, 1)]
  308. [InlineData (true, KeyCode.C | KeyCode.AltMask, 1)]
  309. [InlineData (true, KeyCode.Enter, 1)]
  310. [InlineData (true, KeyCode.Space, 1)]
  311. [InlineData (true, KeyCode.F1, 0)]
  312. [InlineData (false, KeyCode.A, 1)]
  313. [InlineData (false, KeyCode.C, 1)]
  314. [InlineData (false, KeyCode.C | KeyCode.AltMask, 1)]
  315. [InlineData (false, KeyCode.Enter, 0)]
  316. [InlineData (false, KeyCode.Space, 0)]
  317. [InlineData (false, KeyCode.F1, 0)]
  318. public void KeyDown_App_Scope_Invokes_Action (bool canFocus, KeyCode key, int expectedAction)
  319. {
  320. Application.Begin (new Runnable<bool> ());
  321. var shortcut = new Shortcut
  322. {
  323. App = ApplicationImpl.Instance, // HACK: Move to Parallel and get rid of this
  324. BindKeyToApplication = true,
  325. Key = Key.A,
  326. Text = "0",
  327. Title = "_C",
  328. CanFocus = canFocus,
  329. };
  330. Application.TopRunnableView.Add (shortcut);
  331. Application.TopRunnableView.SetFocus ();
  332. var action = 0;
  333. shortcut.Action += () => action++;
  334. Application.RaiseKeyDownEvent (key);
  335. Assert.Equal (expectedAction, action);
  336. Application.TopRunnableView.Dispose ();
  337. Application.ResetState (true);
  338. }
  339. // https://github.com/gui-cs/Terminal.Gui/issues/3664
  340. [Fact]
  341. public void Scheme_SetScheme_Does_Not_Fault_3664 ()
  342. {
  343. Application.Begin (new Runnable<bool> ());
  344. var shortcut = new Shortcut ();
  345. Application.TopRunnableView.SetScheme (null);
  346. Assert.False (shortcut.HasScheme);
  347. Assert.NotNull (shortcut.GetScheme ());
  348. shortcut.HasFocus = true;
  349. Assert.False (shortcut.HasScheme);
  350. Assert.NotNull (shortcut.GetScheme ());
  351. Application.TopRunnableView.Dispose ();
  352. Application.ResetState ();
  353. }
  354. }