ShortcutTests.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. using JetBrains.Annotations;
  2. namespace Terminal.Gui.ViewsTests;
  3. [TestSubject (typeof (Shortcut))]
  4. public class ShortcutTests
  5. {
  6. [Fact]
  7. public void Constructor_Defaults ()
  8. {
  9. var shortcut = new Shortcut ();
  10. Assert.NotNull (shortcut);
  11. Assert.True (shortcut.CanFocus);
  12. Assert.IsType<DimAuto> (shortcut.Width);
  13. Assert.IsType<DimAuto> (shortcut.Height);
  14. // TOOD: more
  15. }
  16. [Theory]
  17. [InlineData ("", "", KeyCode.Null, 2)]
  18. [InlineData ("C", "", KeyCode.Null, 3)]
  19. [InlineData ("", "H", KeyCode.Null, 5)]
  20. [InlineData ("", "", KeyCode.K, 5)]
  21. [InlineData ("C", "", KeyCode.K, 6)]
  22. [InlineData ("C", "H", KeyCode.Null, 6)]
  23. [InlineData ("", "H", KeyCode.K, 8)]
  24. [InlineData ("C", "H", KeyCode.K, 9)]
  25. public void NaturalSize (string command, string help, KeyCode key, int expectedWidth)
  26. {
  27. var shortcut = new Shortcut
  28. {
  29. Title = command,
  30. HelpText = help,
  31. Key = key
  32. };
  33. Assert.IsType<DimAuto> (shortcut.Width);
  34. Assert.IsType<DimAuto> (shortcut.Height);
  35. shortcut.SetRelativeLayout (new (100, 100));
  36. // |0123456789
  37. // | C H K |
  38. Assert.Equal (expectedWidth, shortcut.Frame.Width);
  39. }
  40. [Theory]
  41. [InlineData (5, 0, 3, 6)]
  42. [InlineData (6, 0, 3, 6)]
  43. [InlineData (7, 0, 3, 6)]
  44. [InlineData (8, 0, 3, 6)]
  45. [InlineData (9, 0, 3, 6)]
  46. [InlineData (10, 0, 4, 7)]
  47. [InlineData (11, 0, 5, 8)]
  48. public void Set_Width_Layouts_Correctly (int width, int expectedCmdX, int expectedHelpX, int expectedKeyX)
  49. {
  50. var shortcut = new Shortcut
  51. {
  52. Width = width,
  53. Title = "C",
  54. Text = "H",
  55. Key = Key.K
  56. };
  57. shortcut.LayoutSubviews ();
  58. shortcut.SetRelativeLayout (new (100, 100));
  59. // 0123456789
  60. // -C--H--K-
  61. Assert.Equal (expectedCmdX, shortcut.CommandView.Frame.X);
  62. Assert.Equal (expectedHelpX, shortcut.HelpView.Frame.X);
  63. Assert.Equal (expectedKeyX, shortcut.KeyView.Frame.X);
  64. }
  65. [Fact]
  66. public void CommandView_Text_And_Title_Track ()
  67. {
  68. var shortcut = new Shortcut
  69. {
  70. Title = "T"
  71. };
  72. Assert.Equal (shortcut.Title, shortcut.CommandView.Text);
  73. shortcut = new ();
  74. shortcut.CommandView = new ()
  75. {
  76. Text = "T"
  77. };
  78. Assert.Equal (shortcut.Title, shortcut.CommandView.Text);
  79. }
  80. [Fact]
  81. public void HelpText_And_Text_Are_The_Same ()
  82. {
  83. var shortcut = new Shortcut
  84. {
  85. Text = "H"
  86. };
  87. Assert.Equal (shortcut.Text, shortcut.HelpText);
  88. shortcut = new ()
  89. {
  90. HelpText = "H"
  91. };
  92. Assert.Equal (shortcut.Text, shortcut.HelpText);
  93. }
  94. [Theory]
  95. [InlineData (KeyCode.Null, "")]
  96. [InlineData (KeyCode.F1, "F1")]
  97. public void KeyView_Text_Tracks_Key (KeyCode key, string expected)
  98. {
  99. var shortcut = new Shortcut
  100. {
  101. Key = key
  102. };
  103. Assert.Equal (expected, shortcut.KeyView.Text);
  104. }
  105. // Test Key
  106. [Fact]
  107. public void Key_Defaults_To_Empty ()
  108. {
  109. var shortcut = new Shortcut ();
  110. Assert.Equal (Key.Empty, shortcut.Key);
  111. }
  112. [Fact]
  113. public void Key_Can_Be_Set ()
  114. {
  115. var shortcut = new Shortcut ();
  116. shortcut.Key = Key.F1;
  117. Assert.Equal (Key.F1, shortcut.Key);
  118. }
  119. [Fact]
  120. public void Key_Can_Be_Set_To_Empty ()
  121. {
  122. var shortcut = new Shortcut ();
  123. shortcut.Key = Key.Empty;
  124. Assert.Equal (Key.Empty, shortcut.Key);
  125. }
  126. [Fact]
  127. public void Key_Set_Binds_Key_To_CommandView_Accept ()
  128. {
  129. var shortcut = new Shortcut ();
  130. shortcut.Key = Key.F1;
  131. // TODO:
  132. }
  133. [Fact]
  134. public void Key_Changing_Removes_Previous_Binding ()
  135. {
  136. Shortcut shortcut = new Shortcut ();
  137. shortcut.Key = Key.A;
  138. Assert.Contains (Key.A, shortcut.KeyBindings.Bindings.Keys);
  139. shortcut.Key = Key.B;
  140. Assert.DoesNotContain (Key.A, shortcut.KeyBindings.Bindings.Keys);
  141. Assert.Contains (Key.B, shortcut.KeyBindings.Bindings.Keys);
  142. }
  143. // Test Key gets bound correctly
  144. [Fact]
  145. public void KeyBindingScope_Defaults_To_HotKey ()
  146. {
  147. var shortcut = new Shortcut ();
  148. Assert.Equal (KeyBindingScope.HotKey, shortcut.KeyBindingScope);
  149. }
  150. [Fact]
  151. public void KeyBindingScope_Can_Be_Set ()
  152. {
  153. var shortcut = new Shortcut ();
  154. shortcut.KeyBindingScope = KeyBindingScope.Application;
  155. Assert.Equal (KeyBindingScope.Application, shortcut.KeyBindingScope);
  156. }
  157. [Fact]
  158. public void KeyBindingScope_Changing_Adjusts_KeyBindings ()
  159. {
  160. Shortcut shortcut = new Shortcut ();
  161. shortcut.Key = Key.A;
  162. Assert.Contains (Key.A, shortcut.KeyBindings.Bindings.Keys);
  163. shortcut.KeyBindingScope = KeyBindingScope.Application;
  164. Assert.DoesNotContain (Key.A, shortcut.KeyBindings.Bindings.Keys);
  165. Assert.Contains (Key.A, Application.KeyBindings.Bindings.Keys);
  166. shortcut.KeyBindingScope = KeyBindingScope.HotKey;
  167. Assert.Contains (Key.A, shortcut.KeyBindings.Bindings.Keys);
  168. Assert.DoesNotContain (Key.A, Application.KeyBindings.Bindings.Keys);
  169. }
  170. [Theory]
  171. [InlineData (Orientation.Horizontal)]
  172. [InlineData (Orientation.Vertical)]
  173. public void Orientation_SetsCorrectly (Orientation orientation)
  174. {
  175. var shortcut = new Shortcut
  176. {
  177. Orientation = orientation
  178. };
  179. Assert.Equal (orientation, shortcut.Orientation);
  180. }
  181. [Theory]
  182. [InlineData (AlignmentModes.StartToEnd)]
  183. [InlineData (AlignmentModes.EndToStart)]
  184. public void AlignmentModes_SetsCorrectly (AlignmentModes alignmentModes)
  185. {
  186. var shortcut = new Shortcut
  187. {
  188. AlignmentModes = alignmentModes
  189. };
  190. Assert.Equal (alignmentModes, shortcut.AlignmentModes);
  191. }
  192. [Fact]
  193. public void Action_SetsAndGetsCorrectly ()
  194. {
  195. var actionInvoked = false;
  196. var shortcut = new Shortcut
  197. {
  198. Action = () => { actionInvoked = true; }
  199. };
  200. shortcut.Action.Invoke ();
  201. Assert.True (actionInvoked);
  202. }
  203. [Fact]
  204. public void Subview_Visibility_Controlled_By_Removal ()
  205. {
  206. var shortcut = new Shortcut ();
  207. Assert.True (shortcut.CommandView.Visible);
  208. Assert.Contains (shortcut.CommandView, shortcut.Subviews);
  209. Assert.True (shortcut.HelpView.Visible);
  210. Assert.DoesNotContain (shortcut.HelpView, shortcut.Subviews);
  211. Assert.True (shortcut.KeyView.Visible);
  212. Assert.DoesNotContain (shortcut.KeyView, shortcut.Subviews);
  213. shortcut.HelpText = "help";
  214. Assert.True (shortcut.HelpView.Visible);
  215. Assert.Contains (shortcut.HelpView, shortcut.Subviews);
  216. Assert.True (shortcut.KeyView.Visible);
  217. Assert.DoesNotContain (shortcut.KeyView, shortcut.Subviews);
  218. shortcut.Key = Key.A;
  219. Assert.True (shortcut.HelpView.Visible);
  220. Assert.Contains (shortcut.HelpView, shortcut.Subviews);
  221. Assert.True (shortcut.KeyView.Visible);
  222. Assert.Contains (shortcut.KeyView, shortcut.Subviews);
  223. shortcut.HelpView.Visible = false;
  224. shortcut.ShowHide ();
  225. Assert.False (shortcut.HelpView.Visible);
  226. Assert.DoesNotContain (shortcut.HelpView, shortcut.Subviews);
  227. Assert.True (shortcut.KeyView.Visible);
  228. Assert.Contains (shortcut.KeyView, shortcut.Subviews);
  229. shortcut.KeyView.Visible = false;
  230. shortcut.ShowHide ();
  231. Assert.False (shortcut.HelpView.Visible);
  232. Assert.DoesNotContain (shortcut.HelpView, shortcut.Subviews);
  233. Assert.False (shortcut.KeyView.Visible);
  234. Assert.DoesNotContain (shortcut.KeyView, shortcut.Subviews);
  235. }
  236. [Fact]
  237. public void Focus_CanFocus_Default_Is_True ()
  238. {
  239. Shortcut shortcut = new ();
  240. shortcut.Key = Key.A;
  241. shortcut.Text = "Help";
  242. shortcut.Title = "Command";
  243. Assert.True (shortcut.CanFocus);
  244. Assert.False (shortcut.CommandView.CanFocus);
  245. }
  246. [Fact]
  247. public void Focus_CanFocus_CommandView_Add_Tracks ()
  248. {
  249. Shortcut shortcut = new ();
  250. Assert.True (shortcut.CanFocus);
  251. Assert.False (shortcut.CommandView.CanFocus);
  252. shortcut.CommandView = new () { CanFocus = true };
  253. Assert.False (shortcut.CommandView.CanFocus);
  254. shortcut.CommandView.CanFocus = true;
  255. Assert.True (shortcut.CommandView.CanFocus);
  256. shortcut.CanFocus = false;
  257. Assert.False (shortcut.CanFocus);
  258. Assert.True (shortcut.CommandView.CanFocus);
  259. shortcut.CommandView.CanFocus = false;
  260. Assert.False (shortcut.CanFocus);
  261. Assert.False (shortcut.CommandView.CanFocus);
  262. shortcut.CommandView.CanFocus = true;
  263. Assert.False (shortcut.CanFocus);
  264. Assert.True (shortcut.CommandView.CanFocus);
  265. }
  266. [Theory]
  267. // 0123456789
  268. // " C 0 A "
  269. [InlineData (-1, 0)]
  270. [InlineData (0, 1)]
  271. [InlineData (1, 1)]
  272. [InlineData (2, 1)]
  273. [InlineData (3, 1)]
  274. [InlineData (4, 1)]
  275. [InlineData (5, 1)]
  276. [InlineData (6, 1)]
  277. [InlineData (7, 1)]
  278. [InlineData (8, 1)]
  279. [InlineData (9, 0)]
  280. [AutoInitShutdown]
  281. public void MouseClick_Fires_Accept (int x, int expectedAccept)
  282. {
  283. var current = new Toplevel ();
  284. var shortcut = new Shortcut
  285. {
  286. Key = Key.A,
  287. Text = "0",
  288. Title = "C"
  289. };
  290. current.Add (shortcut);
  291. Application.Begin (current);
  292. var accepted = 0;
  293. shortcut.Accept += (s, e) => accepted++;
  294. Application.OnMouseEvent (
  295. new ()
  296. {
  297. Position = new (x, 0),
  298. Flags = MouseFlags.Button1Clicked
  299. });
  300. Assert.Equal (expectedAccept, accepted);
  301. current.Dispose ();
  302. }
  303. [Theory]
  304. // 0123456789
  305. // " C 0 A "
  306. [InlineData (-1, 0, 0)]
  307. [InlineData (0, 1, 1)]
  308. [InlineData (1, 1, 1, Skip = "BUGBUG: This breaks. We need to fix the logic in the Shortcut class.")]
  309. [InlineData (2, 1, 1)]
  310. [InlineData (3, 1, 1)]
  311. [InlineData (4, 1, 1)]
  312. [InlineData (5, 1, 1)]
  313. [InlineData (6, 1, 1)]
  314. [InlineData (7, 1, 1)]
  315. [InlineData (8, 1, 1)]
  316. [InlineData (9, 0, 0)]
  317. [AutoInitShutdown]
  318. public void MouseClick_Button_CommandView_Fires_Accept (int x, int expectedAccept, int expectedButtonAccept)
  319. {
  320. var current = new Toplevel ();
  321. var shortcut = new Shortcut
  322. {
  323. Key = Key.A,
  324. Text = "0"
  325. };
  326. shortcut.CommandView = new Button
  327. {
  328. Title = "C",
  329. NoDecorations = true,
  330. NoPadding = true
  331. };
  332. var buttonAccepted = 0;
  333. shortcut.CommandView.Accept += (s, e) => { buttonAccepted++; };
  334. current.Add (shortcut);
  335. Application.Begin (current);
  336. var accepted = 0;
  337. shortcut.Accept += (s, e) => accepted++;
  338. //Assert.True (shortcut.HasFocus);
  339. Application.OnMouseEvent (
  340. new ()
  341. {
  342. Position = new (x, 0),
  343. Flags = MouseFlags.Button1Clicked
  344. });
  345. Assert.Equal (expectedAccept, accepted);
  346. Assert.Equal (expectedButtonAccept, buttonAccepted);
  347. current.Dispose ();
  348. }
  349. [Theory]
  350. [InlineData (true, KeyCode.A, 1)]
  351. [InlineData (true, KeyCode.C, 1)]
  352. [InlineData (true, KeyCode.C | KeyCode.AltMask, 1)]
  353. [InlineData (true, KeyCode.Enter, 1)]
  354. [InlineData (true, KeyCode.Space, 0)]
  355. [InlineData (true, KeyCode.F1, 0)]
  356. [InlineData (false, KeyCode.A, 1)]
  357. [InlineData (false, KeyCode.C, 1)]
  358. [InlineData (false, KeyCode.C | KeyCode.AltMask, 1)]
  359. [InlineData (false, KeyCode.Enter, 0)]
  360. [InlineData (false, KeyCode.Space, 0)]
  361. [InlineData (false, KeyCode.F1, 0)]
  362. [AutoInitShutdown]
  363. public void KeyDown_Invokes_Accept (bool canFocus, KeyCode key, int expectedAccept)
  364. {
  365. var current = new Toplevel ();
  366. var shortcut = new Shortcut
  367. {
  368. Key = Key.A,
  369. Text = "0",
  370. Title = "_C",
  371. CanFocus = canFocus
  372. };
  373. current.Add (shortcut);
  374. Application.Begin (current);
  375. Assert.Equal (canFocus, shortcut.HasFocus);
  376. var accepted = 0;
  377. shortcut.Accept += (s, e) => accepted++;
  378. Application.OnKeyDown (key);
  379. Assert.Equal (expectedAccept, accepted);
  380. current.Dispose ();
  381. }
  382. [Theory]
  383. [InlineData (KeyCode.A, 1)]
  384. [InlineData (KeyCode.C, 1)]
  385. [InlineData (KeyCode.C | KeyCode.AltMask, 1)]
  386. [InlineData (KeyCode.Enter, 1)]
  387. [InlineData (KeyCode.Space, 0)]
  388. [InlineData (KeyCode.F1, 0)]
  389. [AutoInitShutdown]
  390. public void KeyDown_App_Scope_Invokes_Accept (KeyCode key, int expectedAccept)
  391. {
  392. var current = new Toplevel ();
  393. var shortcut = new Shortcut
  394. {
  395. Key = Key.A,
  396. KeyBindingScope = KeyBindingScope.Application,
  397. Text = "0",
  398. Title = "_C"
  399. };
  400. current.Add (shortcut);
  401. Application.Begin (current);
  402. var accepted = 0;
  403. shortcut.Accept += (s, e) => accepted++;
  404. Application.OnKeyDown (key);
  405. Assert.Equal (expectedAccept, accepted);
  406. current.Dispose ();
  407. }
  408. [Theory]
  409. [InlineData (true, KeyCode.A, 1)]
  410. [InlineData (true, KeyCode.C, 1)]
  411. [InlineData (true, KeyCode.C | KeyCode.AltMask, 1)]
  412. [InlineData (true, KeyCode.Enter, 1)]
  413. [InlineData (true, KeyCode.Space, 0)]
  414. [InlineData (true, KeyCode.F1, 0)]
  415. [InlineData (false, KeyCode.A, 1)]
  416. [InlineData (false, KeyCode.C, 1)]
  417. [InlineData (false, KeyCode.C | KeyCode.AltMask, 1)]
  418. [InlineData (false, KeyCode.Enter, 0)]
  419. [InlineData (false, KeyCode.Space, 0)]
  420. [InlineData (false, KeyCode.F1, 0)]
  421. [AutoInitShutdown]
  422. public void KeyDown_Invokes_Action (bool canFocus, KeyCode key, int expectedAction)
  423. {
  424. var current = new Toplevel ();
  425. var shortcut = new Shortcut
  426. {
  427. Key = Key.A,
  428. Text = "0",
  429. Title = "_C",
  430. CanFocus = canFocus
  431. };
  432. current.Add (shortcut);
  433. Application.Begin (current);
  434. Assert.Equal (canFocus, shortcut.HasFocus);
  435. var action = 0;
  436. shortcut.Action += () => action++;
  437. Application.OnKeyDown (key);
  438. Assert.Equal (expectedAction, action);
  439. current.Dispose ();
  440. }
  441. [Theory]
  442. [InlineData (true, KeyCode.A, 1)]
  443. [InlineData (true, KeyCode.C, 1)]
  444. [InlineData (true, KeyCode.C | KeyCode.AltMask, 1)]
  445. [InlineData (true, KeyCode.Enter, 1)]
  446. [InlineData (true, KeyCode.Space, 0)]
  447. [InlineData (true, KeyCode.F1, 0)]
  448. [InlineData (false, KeyCode.A, 1)]
  449. [InlineData (false, KeyCode.C, 1)]
  450. [InlineData (false, KeyCode.C | KeyCode.AltMask, 1)]
  451. [InlineData (false, KeyCode.Enter, 0)]
  452. [InlineData (false, KeyCode.Space, 0)]
  453. [InlineData (false, KeyCode.F1, 0)]
  454. [AutoInitShutdown]
  455. public void KeyDown_App_Scope_Invokes_Action (bool canFocus, KeyCode key, int expectedAction)
  456. {
  457. var current = new Toplevel ();
  458. var shortcut = new Shortcut
  459. {
  460. Key = Key.A,
  461. KeyBindingScope = KeyBindingScope.Application,
  462. Text = "0",
  463. Title = "_C",
  464. CanFocus = canFocus
  465. };
  466. current.Add (shortcut);
  467. Application.Begin (current);
  468. Assert.Equal (canFocus, shortcut.HasFocus);
  469. var action = 0;
  470. shortcut.Action += () => action++;
  471. Application.OnKeyDown (key);
  472. Assert.Equal (expectedAction, action);
  473. current.Dispose ();
  474. }
  475. [Fact]
  476. public void ColorScheme_SetsAndGetsCorrectly ()
  477. {
  478. var colorScheme = new ColorScheme ();
  479. var shortcut = new Shortcut
  480. {
  481. ColorScheme = colorScheme
  482. };
  483. Assert.Same (colorScheme, shortcut.ColorScheme);
  484. }
  485. // https://github.com/gui-cs/Terminal.Gui/issues/3664
  486. [Fact]
  487. public void ColorScheme_SetColorScheme_Does_Not_Fault_3664 ()
  488. {
  489. Application.Current = new ();
  490. Application.Navigation = new ();
  491. Shortcut shortcut = new Shortcut ();
  492. Application.Current.ColorScheme = null;
  493. Assert.Null (shortcut.ColorScheme);
  494. shortcut.HasFocus = true;
  495. Assert.NotNull (shortcut.ColorScheme);
  496. Application.Current.Dispose ();
  497. Application.ResetState ();
  498. }
  499. }