KeyBindingsTests.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. using Terminal.Gui.EnumExtensions;
  2. using Xunit.Abstractions;
  3. using static Unix.Terminal.Delegates;
  4. namespace Terminal.Gui.InputTests;
  5. public class KeyBindingsTests ()
  6. {
  7. [Fact]
  8. public void Add_Invalid_Key_Throws ()
  9. {
  10. var keyBindings = new KeyBindings (new View ());
  11. List<Command> commands = new ();
  12. Assert.Throws<ArgumentException> (() => keyBindings.Add (Key.Empty, KeyBindingScope.HotKey, Command.Accept));
  13. }
  14. [Fact]
  15. public void Add_BoundView_Null_Non_AppScope_Throws ()
  16. {
  17. var keyBindings = new KeyBindings ();
  18. List<Command> commands = new ();
  19. Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.Empty, KeyBindingScope.HotKey, Command.Accept));
  20. }
  21. [Fact]
  22. public void Add_Multiple_Adds ()
  23. {
  24. var keyBindings = new KeyBindings ();
  25. Command [] commands = { Command.Right, Command.Left };
  26. keyBindings.Add (Key.A, KeyBindingScope.Application, commands);
  27. Command [] resultCommands = keyBindings.GetCommands (Key.A);
  28. Assert.Contains (Command.Right, resultCommands);
  29. Assert.Contains (Command.Left, resultCommands);
  30. keyBindings.Add (Key.B, KeyBindingScope.Application, commands);
  31. resultCommands = keyBindings.GetCommands (Key.B);
  32. Assert.Contains (Command.Right, resultCommands);
  33. Assert.Contains (Command.Left, resultCommands);
  34. }
  35. [Fact]
  36. public void Add_No_Commands_Throws ()
  37. {
  38. var keyBindings = new KeyBindings ();
  39. List<Command> commands = new ();
  40. Assert.Throws<ArgumentException> (() => keyBindings.Add (Key.A, commands.ToArray ()));
  41. }
  42. [Fact]
  43. public void Add_Single_Adds ()
  44. {
  45. var keyBindings = new KeyBindings ();
  46. keyBindings.Add (Key.A, KeyBindingScope.Application, Command.HotKey);
  47. Command [] resultCommands = keyBindings.GetCommands (Key.A);
  48. Assert.Contains (Command.HotKey, resultCommands);
  49. keyBindings.Add (Key.B, KeyBindingScope.Application, Command.HotKey);
  50. resultCommands = keyBindings.GetCommands (Key.B);
  51. Assert.Contains (Command.HotKey, resultCommands);
  52. }
  53. // Add should not allow duplicates
  54. [Fact]
  55. public void Add_With_Bound_View_Throws_If_App_Scope ()
  56. {
  57. var keyBindings = new KeyBindings (new View ());
  58. Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, KeyBindingScope.Application, Command.Accept));
  59. }
  60. // Add should not allow duplicates
  61. [Fact]
  62. public void Add_With_Throws_If_Exists ()
  63. {
  64. var keyBindings = new KeyBindings (new View ());
  65. keyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.HotKey);
  66. Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.Accept));
  67. Command [] resultCommands = keyBindings.GetCommands (Key.A);
  68. Assert.Contains (Command.HotKey, resultCommands);
  69. keyBindings = new (new View ());
  70. keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.HotKey);
  71. Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.Accept));
  72. resultCommands = keyBindings.GetCommands (Key.A);
  73. Assert.Contains (Command.HotKey, resultCommands);
  74. keyBindings = new (new View ());
  75. keyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.HotKey);
  76. Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, KeyBindingScope.HotKey, Command.Accept));
  77. resultCommands = keyBindings.GetCommands (Key.A);
  78. Assert.Contains (Command.HotKey, resultCommands);
  79. keyBindings = new (new View ());
  80. keyBindings.Add (Key.A, new KeyBinding (new [] { Command.HotKey }, KeyBindingScope.HotKey));
  81. Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, new KeyBinding (new [] { Command.Accept }, KeyBindingScope.HotKey)));
  82. resultCommands = keyBindings.GetCommands (Key.A);
  83. Assert.Contains (Command.HotKey, resultCommands);
  84. }
  85. // Clear
  86. [Fact]
  87. public void Clear_Clears ()
  88. {
  89. var keyBindings = new KeyBindings ();
  90. keyBindings.Add (Key.B, KeyBindingScope.Application, Command.HotKey);
  91. keyBindings.Clear ();
  92. Command [] resultCommands = keyBindings.GetCommands (Key.A);
  93. Assert.Empty (resultCommands);
  94. resultCommands = keyBindings.GetCommands (Key.B);
  95. Assert.Empty (resultCommands);
  96. }
  97. [Fact]
  98. public void Defaults ()
  99. {
  100. var keyBindings = new KeyBindings ();
  101. Assert.Empty (keyBindings.Bindings);
  102. Assert.Null (keyBindings.GetKeyFromCommands (Command.Accept));
  103. Assert.Null (keyBindings.BoundView);
  104. }
  105. [Fact]
  106. public void Get_Binding_Not_Found_Throws ()
  107. {
  108. var keyBindings = new KeyBindings ();
  109. Assert.Throws<InvalidOperationException> (() => keyBindings.Get (Key.A));
  110. Assert.Throws<InvalidOperationException> (() => keyBindings.Get (Key.B, KeyBindingScope.Application));
  111. }
  112. // GetCommands
  113. [Fact]
  114. public void GetCommands_Unknown_ReturnsEmpty ()
  115. {
  116. var keyBindings = new KeyBindings ();
  117. Command [] resultCommands = keyBindings.GetCommands (Key.A);
  118. Assert.Empty (resultCommands);
  119. }
  120. [Fact]
  121. public void GetCommands_WithCommands_ReturnsCommands ()
  122. {
  123. var keyBindings = new KeyBindings ();
  124. keyBindings.Add (Key.A, KeyBindingScope.Application, Command.HotKey);
  125. Command [] resultCommands = keyBindings.GetCommands (Key.A);
  126. Assert.Contains (Command.HotKey, resultCommands);
  127. }
  128. [Fact]
  129. public void GetCommands_WithMultipleBindings_ReturnsCommands ()
  130. {
  131. var keyBindings = new KeyBindings ();
  132. Command [] commands = { Command.Right, Command.Left };
  133. keyBindings.Add (Key.A, KeyBindingScope.Application, commands);
  134. keyBindings.Add (Key.B, KeyBindingScope.Application, commands);
  135. Command [] resultCommands = keyBindings.GetCommands (Key.A);
  136. Assert.Contains (Command.Right, resultCommands);
  137. Assert.Contains (Command.Left, resultCommands);
  138. resultCommands = keyBindings.GetCommands (Key.B);
  139. Assert.Contains (Command.Right, resultCommands);
  140. Assert.Contains (Command.Left, resultCommands);
  141. }
  142. [Fact]
  143. public void GetCommands_WithMultipleCommands_ReturnsCommands ()
  144. {
  145. var keyBindings = new KeyBindings ();
  146. Command [] commands = { Command.Right, Command.Left };
  147. keyBindings.Add (Key.A, KeyBindingScope.Application, commands);
  148. Command [] resultCommands = keyBindings.GetCommands (Key.A);
  149. Assert.Contains (Command.Right, resultCommands);
  150. Assert.Contains (Command.Left, resultCommands);
  151. }
  152. [Fact]
  153. public void GetKeyFromCommands_MultipleCommands ()
  154. {
  155. var keyBindings = new KeyBindings ();
  156. Command [] commands1 = { Command.Right, Command.Left };
  157. keyBindings.Add (Key.A, KeyBindingScope.Application, commands1);
  158. Command [] commands2 = { Command.Up, Command.Down };
  159. keyBindings.Add (Key.B, KeyBindingScope.Application, commands2);
  160. Key key = keyBindings.GetKeyFromCommands (commands1);
  161. Assert.Equal (Key.A, key);
  162. key = keyBindings.GetKeyFromCommands (commands2);
  163. Assert.Equal (Key.B, key);
  164. }
  165. [Fact]
  166. public void GetKeyFromCommands_OneCommand ()
  167. {
  168. var keyBindings = new KeyBindings ();
  169. keyBindings.Add (Key.A, KeyBindingScope.Application, Command.Right);
  170. Key key = keyBindings.GetKeyFromCommands (Command.Right);
  171. Assert.Equal (Key.A, key);
  172. }
  173. // GetKeyFromCommands
  174. [Fact]
  175. public void GetKeyFromCommands_Unknown_Returns_Key_Empty ()
  176. {
  177. var keyBindings = new KeyBindings ();
  178. Assert.Null (keyBindings.GetKeyFromCommands (Command.Accept));
  179. }
  180. [Fact]
  181. public void GetKeyFromCommands_WithCommands_ReturnsKey ()
  182. {
  183. var keyBindings = new KeyBindings ();
  184. keyBindings.Add (Key.A, KeyBindingScope.Application, Command.HotKey);
  185. Key resultKey = keyBindings.GetKeyFromCommands (Command.HotKey);
  186. Assert.Equal (Key.A, resultKey);
  187. }
  188. [Fact]
  189. public void ReplaceKey_Replaces ()
  190. {
  191. var keyBindings = new KeyBindings (new ());
  192. keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.HotKey);
  193. keyBindings.Add (Key.B, KeyBindingScope.Focused, Command.HotKey);
  194. keyBindings.Add (Key.C, KeyBindingScope.Focused, Command.HotKey);
  195. keyBindings.Add (Key.D, KeyBindingScope.Focused, Command.HotKey);
  196. keyBindings.ReplaceKey (Key.A, Key.E);
  197. Assert.Empty (keyBindings.GetCommands (Key.A));
  198. Assert.Contains (Command.HotKey, keyBindings.GetCommands (Key.E));
  199. keyBindings.ReplaceKey (Key.B, Key.F);
  200. Assert.Empty (keyBindings.GetCommands (Key.B));
  201. Assert.Contains (Command.HotKey, keyBindings.GetCommands (Key.F));
  202. keyBindings.ReplaceKey (Key.C, Key.G);
  203. Assert.Empty (keyBindings.GetCommands (Key.C));
  204. Assert.Contains (Command.HotKey, keyBindings.GetCommands (Key.G));
  205. keyBindings.ReplaceKey (Key.D, Key.H);
  206. Assert.Empty (keyBindings.GetCommands (Key.D));
  207. Assert.Contains (Command.HotKey, keyBindings.GetCommands (Key.H));
  208. }
  209. [Fact]
  210. public void ReplaceKey_Replaces_Leaves_Old_Binding ()
  211. {
  212. var keyBindings = new KeyBindings (new ());
  213. keyBindings.Add (Key.A, KeyBindingScope.Focused, Command.Accept);
  214. keyBindings.Add (Key.B, KeyBindingScope.Focused, Command.HotKey);
  215. keyBindings.ReplaceKey (keyBindings.GetKeyFromCommands (Command.Accept), Key.C);
  216. Assert.Empty (keyBindings.GetCommands (Key.A));
  217. Assert.Contains (Command.Accept, keyBindings.GetCommands (Key.C));
  218. }
  219. [Fact]
  220. public void ReplaceKey_Throws_If_DoesNotContain_Old ()
  221. {
  222. var keyBindings = new KeyBindings ();
  223. Assert.Throws<InvalidOperationException> (() => keyBindings.ReplaceKey (Key.A, Key.B));
  224. }
  225. [Fact]
  226. public void ReplaceKey_Throws_If_New_Is_Empty ()
  227. {
  228. var keyBindings = new KeyBindings ();
  229. keyBindings.Add (Key.A, KeyBindingScope.Application, Command.HotKey);
  230. Assert.Throws<InvalidOperationException> (() => keyBindings.ReplaceKey (Key.A, Key.Empty));
  231. }
  232. // Add with scope does the right things
  233. [Theory]
  234. [InlineData (KeyBindingScope.Focused)]
  235. [InlineData (KeyBindingScope.HotKey)]
  236. [InlineData (KeyBindingScope.Application)]
  237. public void Scope_Add_Adds (KeyBindingScope scope)
  238. {
  239. var keyBindings = new KeyBindings (scope.FastHasFlags (KeyBindingScope.Application) ? null : new ());
  240. Command [] commands = { Command.Right, Command.Left };
  241. var key = new Key (Key.A);
  242. keyBindings.Add (Key.A, scope, commands);
  243. KeyBinding binding = keyBindings.Get (key);
  244. Assert.Contains (Command.Right, binding.Commands);
  245. Assert.Contains (Command.Left, binding.Commands);
  246. binding = keyBindings.Get (key, scope);
  247. Assert.Contains (Command.Right, binding.Commands);
  248. Assert.Contains (Command.Left, binding.Commands);
  249. Command [] resultCommands = keyBindings.GetCommands (key);
  250. Assert.Contains (Command.Right, resultCommands);
  251. Assert.Contains (Command.Left, resultCommands);
  252. }
  253. [Theory]
  254. [InlineData (KeyBindingScope.Focused)]
  255. [InlineData (KeyBindingScope.HotKey)]
  256. [InlineData (KeyBindingScope.Application)]
  257. public void Scope_Get_Filters (KeyBindingScope scope)
  258. {
  259. var keyBindings = new KeyBindings (scope.FastHasFlags (KeyBindingScope.Application) ? null : new ());
  260. Command [] commands = { Command.Right, Command.Left };
  261. var key = new Key (Key.A);
  262. keyBindings.Add (key, scope, commands);
  263. KeyBinding binding = keyBindings.Get (key);
  264. Assert.Contains (Command.Right, binding.Commands);
  265. Assert.Contains (Command.Left, binding.Commands);
  266. binding = keyBindings.Get (key, scope);
  267. Assert.Contains (Command.Right, binding.Commands);
  268. Assert.Contains (Command.Left, binding.Commands);
  269. }
  270. [Theory]
  271. [InlineData (KeyBindingScope.Focused)]
  272. [InlineData (KeyBindingScope.HotKey)]
  273. [InlineData (KeyBindingScope.Application)]
  274. public void Scope_TryGet_Filters (KeyBindingScope scope)
  275. {
  276. var keyBindings = new KeyBindings (scope.FastHasFlags (KeyBindingScope.Application) ? null : new ());
  277. Command [] commands = { Command.Right, Command.Left };
  278. var key = new Key (Key.A);
  279. keyBindings.Add (key, scope, commands);
  280. bool success = keyBindings.TryGet (key, out KeyBinding binding);
  281. Assert.Contains (Command.Right, binding.Commands);
  282. Assert.Contains (Command.Left, binding.Commands);
  283. success = keyBindings.TryGet (key, scope, out binding);
  284. Assert.Contains (Command.Right, binding.Commands);
  285. Assert.Contains (Command.Left, binding.Commands);
  286. // negative test
  287. success = keyBindings.TryGet (key, 0, out binding);
  288. Assert.False (success);
  289. Command [] resultCommands = keyBindings.GetCommands (key);
  290. Assert.Contains (Command.Right, resultCommands);
  291. Assert.Contains (Command.Left, resultCommands);
  292. }
  293. // TryGet
  294. [Fact]
  295. public void TryGet_Succeeds ()
  296. {
  297. var keyBindings = new KeyBindings ();
  298. keyBindings.Add (Key.Q.WithCtrl, KeyBindingScope.Application, Command.HotKey);
  299. var key = new Key (Key.Q.WithCtrl);
  300. bool result = keyBindings.TryGet (key, out KeyBinding _);
  301. Assert.True (result); ;
  302. result = keyBindings.Bindings.TryGetValue (key, out KeyBinding _);
  303. Assert.True (result);
  304. }
  305. [Fact]
  306. public void TryGet_Unknown_ReturnsFalse ()
  307. {
  308. var keyBindings = new KeyBindings ();
  309. bool result = keyBindings.TryGet (Key.A, out KeyBinding _);
  310. Assert.False (result);
  311. }
  312. [Fact]
  313. public void TryGet_WithCommands_ReturnsTrue ()
  314. {
  315. var keyBindings = new KeyBindings ();
  316. keyBindings.Add (Key.A, KeyBindingScope.Application, Command.HotKey);
  317. bool result = keyBindings.TryGet (Key.A, out KeyBinding bindings);
  318. Assert.True (result);
  319. Assert.Contains (Command.HotKey, bindings.Commands);
  320. }
  321. [Fact]
  322. public void ReplaceCommands_Replaces ()
  323. {
  324. var keyBindings = new KeyBindings ();
  325. keyBindings.Add (Key.A, KeyBindingScope.Application, Command.Accept);
  326. keyBindings.ReplaceCommands (Key.A, Command.Refresh);
  327. bool result = keyBindings.TryGet (Key.A, out KeyBinding bindings);
  328. Assert.True (result);
  329. Assert.Contains (Command.Refresh, bindings.Commands);
  330. }
  331. }