ShortcutTests.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. using JetBrains.Annotations;
  2. using UnitTests;
  3. namespace Terminal.Gui.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.Top = new ();
  24. var shortcut = new Shortcut
  25. {
  26. Key = Key.A,
  27. Text = "0",
  28. Title = "C"
  29. };
  30. Application.Top.Add (shortcut);
  31. Application.Top.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.Top.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 MouseClick
  49. [InlineData (1, 0, 1, 1, 1)] // mouseX = 1 is on the CommandView, so CommandView will get MouseClick
  50. [InlineData (2, 0, 1, 1, 1)] // mouseX = 2 is on the CommandView.Margin, so Shortcut will get MouseClick
  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 expectedCommandViewSelected,
  62. int expectedShortcutAccepted,
  63. int expectedShortcutSelected
  64. )
  65. {
  66. Application.Top = new ();
  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 commandViewSelectCount = 0;
  76. shortcut.CommandView.Selecting += (s, e) => { commandViewSelectCount++; };
  77. var shortcutAcceptCount = 0;
  78. shortcut.Accepting += (s, e) => { shortcutAcceptCount++; };
  79. var shortcutSelectCount = 0;
  80. shortcut.Selecting += (s, e) => { shortcutSelectCount++; };
  81. Application.Top.Add (shortcut);
  82. Application.Top.SetRelativeLayout (new (100, 100));
  83. Application.Top.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 (expectedShortcutSelected, shortcutSelectCount);
  92. Assert.Equal (expectedCommandViewAccepted, commandViewAcceptCount);
  93. Assert.Equal (expectedCommandViewSelected, commandViewSelectCount);
  94. Application.Top.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.Top = new ();
  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.Top.Add (shortcut);
  129. Application.Top.SetRelativeLayout (new (100, 100));
  130. Application.Top.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.Top.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.Top = new ();
  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 checkboxSelected = 0;
  175. shortcut.CommandView.Selecting += (s, e) =>
  176. {
  177. if (e.Cancel)
  178. {
  179. return;
  180. }
  181. checkboxSelected++;
  182. };
  183. Application.Top.Add (shortcut);
  184. Application.Top.SetRelativeLayout (new (100, 100));
  185. Application.Top.LayoutSubViews ();
  186. var selected = 0;
  187. shortcut.Selecting += (s, e) =>
  188. {
  189. selected++;
  190. };
  191. var accepted = 0;
  192. shortcut.Accepting += (s, e) =>
  193. {
  194. accepted++;
  195. e.Cancel = 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, selected);
  205. Assert.Equal (expectedCheckboxAccepted, checkboxAccepted);
  206. Assert.Equal (expectedCheckboxAccepted, checkboxSelected);
  207. Application.Top.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.Top = new ();
  226. var shortcut = new Shortcut
  227. {
  228. Key = Key.A,
  229. Text = "0",
  230. Title = "_C",
  231. CanFocus = canFocus
  232. };
  233. Application.Top.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.Selecting += (s, e) => selected++;
  240. Application.RaiseKeyDownEvent (key);
  241. Assert.Equal (expectedAccept, accepted);
  242. Assert.Equal (expectedSelect, selected);
  243. Application.Top.Dispose ();
  244. Application.ResetState (true);
  245. }
  246. [Theory]
  247. [InlineData (true, KeyCode.A, 1, 1)]
  248. [InlineData (true, KeyCode.C, 1, 1)]
  249. [InlineData (true, KeyCode.C | KeyCode.AltMask, 1, 1)]
  250. [InlineData (true, KeyCode.Enter, 1, 1)]
  251. [InlineData (true, KeyCode.Space, 1, 1)]
  252. [InlineData (true, KeyCode.F1, 0, 0)]
  253. [InlineData (false, KeyCode.A, 1, 1)]
  254. [InlineData (false, KeyCode.C, 1, 1)]
  255. [InlineData (false, KeyCode.C | KeyCode.AltMask, 1, 1)]
  256. [InlineData (false, KeyCode.Enter, 0, 0)]
  257. [InlineData (false, KeyCode.Space, 0, 0)]
  258. [InlineData (false, KeyCode.F1, 0, 0)]
  259. public void KeyDown_CheckBox_Raises_Accepted_Selected (bool canFocus, KeyCode key, int expectedAccept, int expectedSelect)
  260. {
  261. Application.Top = new ();
  262. var shortcut = new Shortcut
  263. {
  264. Key = Key.A,
  265. Text = "0",
  266. CommandView = new CheckBox ()
  267. {
  268. Title = "_C"
  269. },
  270. CanFocus = canFocus
  271. };
  272. Application.Top.Add (shortcut);
  273. shortcut.SetFocus ();
  274. Assert.Equal (canFocus, shortcut.HasFocus);
  275. var accepted = 0;
  276. shortcut.Accepting += (s, e) =>
  277. {
  278. accepted++;
  279. e.Cancel = true;
  280. };
  281. var selected = 0;
  282. shortcut.Selecting += (s, e) => selected++;
  283. Application.RaiseKeyDownEvent (key);
  284. Assert.Equal (expectedAccept, accepted);
  285. Assert.Equal (expectedSelect, selected);
  286. Application.Top.Dispose ();
  287. Application.ResetState (true);
  288. }
  289. [Theory]
  290. [InlineData (KeyCode.A, 1)]
  291. [InlineData (KeyCode.C, 1)]
  292. [InlineData (KeyCode.C | KeyCode.AltMask, 1)]
  293. [InlineData (KeyCode.Enter, 1)]
  294. [InlineData (KeyCode.Space, 1)]
  295. [InlineData (KeyCode.F1, 0)]
  296. public void KeyDown_App_Scope_Invokes_Accept (KeyCode key, int expectedAccept)
  297. {
  298. Application.Top = new ();
  299. var shortcut = new Shortcut
  300. {
  301. Key = Key.A,
  302. BindKeyToApplication = true,
  303. Text = "0",
  304. Title = "_C"
  305. };
  306. Application.Top.Add (shortcut);
  307. Application.Top.SetFocus ();
  308. var accepted = 0;
  309. shortcut.Accepting += (s, e) => accepted++;
  310. Application.RaiseKeyDownEvent (key);
  311. Assert.Equal (expectedAccept, accepted);
  312. Application.Top.Dispose ();
  313. Application.ResetState (true);
  314. }
  315. [Theory]
  316. [InlineData (true, KeyCode.A, 1)]
  317. [InlineData (true, KeyCode.C, 1)]
  318. [InlineData (true, KeyCode.C | KeyCode.AltMask, 1)]
  319. [InlineData (true, KeyCode.Enter, 1)]
  320. [InlineData (true, KeyCode.Space, 1)]
  321. [InlineData (true, KeyCode.F1, 0)]
  322. [InlineData (false, KeyCode.A, 1)]
  323. [InlineData (false, KeyCode.C, 1)]
  324. [InlineData (false, KeyCode.C | KeyCode.AltMask, 1)]
  325. [InlineData (false, KeyCode.Enter, 0)]
  326. [InlineData (false, KeyCode.Space, 0)]
  327. [InlineData (false, KeyCode.F1, 0)]
  328. [AutoInitShutdown]
  329. public void KeyDown_Invokes_Action (bool canFocus, KeyCode key, int expectedAction)
  330. {
  331. var current = new Toplevel ();
  332. var shortcut = new Shortcut
  333. {
  334. Key = Key.A,
  335. Text = "0",
  336. Title = "_C",
  337. CanFocus = canFocus
  338. };
  339. current.Add (shortcut);
  340. Application.Begin (current);
  341. Assert.Equal (canFocus, shortcut.HasFocus);
  342. var action = 0;
  343. shortcut.Action += () => action++;
  344. Application.RaiseKeyDownEvent (key);
  345. Assert.Equal (expectedAction, action);
  346. current.Dispose ();
  347. }
  348. [Theory]
  349. [InlineData (true, KeyCode.A, 1)]
  350. [InlineData (true, KeyCode.C, 1)]
  351. [InlineData (true, KeyCode.C | KeyCode.AltMask, 1)]
  352. [InlineData (true, KeyCode.Enter, 1)]
  353. [InlineData (true, KeyCode.Space, 1)]
  354. [InlineData (true, KeyCode.F1, 0)]
  355. [InlineData (false, KeyCode.A, 1)]
  356. [InlineData (false, KeyCode.C, 1)]
  357. [InlineData (false, KeyCode.C | KeyCode.AltMask, 1)]
  358. [InlineData (false, KeyCode.Enter, 0)]
  359. [InlineData (false, KeyCode.Space, 0)]
  360. [InlineData (false, KeyCode.F1, 0)]
  361. public void KeyDown_App_Scope_Invokes_Action (bool canFocus, KeyCode key, int expectedAction)
  362. {
  363. Application.Top = new ();
  364. var shortcut = new Shortcut
  365. {
  366. Key = Key.A,
  367. BindKeyToApplication = true,
  368. Text = "0",
  369. Title = "_C",
  370. CanFocus = canFocus
  371. };
  372. Application.Top.Add (shortcut);
  373. Application.Top.SetFocus ();
  374. var action = 0;
  375. shortcut.Action += () => action++;
  376. Application.RaiseKeyDownEvent (key);
  377. Assert.Equal (expectedAction, action);
  378. Application.Top.Dispose ();
  379. Application.ResetState (true);
  380. }
  381. // https://github.com/gui-cs/Terminal.Gui/issues/3664
  382. [Fact]
  383. public void ColorScheme_SetColorScheme_Does_Not_Fault_3664 ()
  384. {
  385. Application.Top = new ();
  386. Application.Navigation = new ();
  387. var shortcut = new Shortcut ();
  388. Application.Top.ColorScheme = null;
  389. Assert.Null (shortcut.ColorScheme);
  390. shortcut.HasFocus = true;
  391. Assert.NotNull (shortcut.ColorScheme);
  392. Application.Top.Dispose ();
  393. Application.ResetState ();
  394. }
  395. }