KeyBindingTests.cs 14 KB

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