Browse Source

MouseBindings tests

Tig 7 tháng trước cách đây
mục cha
commit
e502a13402

+ 6 - 5
Terminal.Gui/Application/Application.Keyboard.cs

@@ -45,16 +45,17 @@ public static partial class Application // Keyboard handling
 
         // Invoke any Application-scoped KeyBindings.
         // The first view that handles the key will stop the loop.
-        foreach (KeyValuePair<Key, KeyBinding> binding in KeyBindings.GetBindings (key))
+        // foreach (KeyValuePair<Key, KeyBinding> binding in KeyBindings.GetBindings (key))
+        if (KeyBindings.TryGet (key, out KeyBinding binding))
         {
-            if (binding.Value.Target is { })
+            if (binding.Target is { })
             {
-                if (!binding.Value.Target.Enabled)
+                if (!binding.Target.Enabled)
                 {
                     return false;
                 }
 
-                bool? handled = binding.Value.Target?.InvokeCommands (binding.Value.Commands, binding.Value);
+                bool? handled = binding.Target?.InvokeCommands (binding.Commands, binding);
 
                 if (handled != null && (bool)handled)
                 {
@@ -65,7 +66,7 @@ public static partial class Application // Keyboard handling
             {
                 if (!KeyBindings.TryGet (key, out KeyBinding appBinding))
                 {
-                    continue;
+                    return false;
                 }
 
                 bool? toReturn = null;

+ 3 - 8
Terminal.Gui/Input/Keyboard/KeyBindings.cs

@@ -105,17 +105,12 @@ public class KeyBindings
     private readonly Dictionary<Key, KeyBinding> _bindings = new (new KeyEqualityComparer ());
 
     /// <summary>
-    ///     Gets the bindings bound to <paramref name="key"/>.
+    ///     Gets the bindings.
     /// </summary>
-    /// <param name="key"></param>
     /// <returns></returns>
-    public IEnumerable<KeyValuePair<Key, KeyBinding>> GetBindings (Key? key = null)
+    public IEnumerable<KeyValuePair<Key, KeyBinding>> GetBindings ()
     {
-        if (key is null)
-        {
-            return _bindings;
-        }
-        return _bindings.Where (b => b.Key == key.KeyCode);
+        return _bindings;
     }
 
     /// <summary>

+ 50 - 36
Terminal.Gui/Input/Mouse/MouseBindings.cs

@@ -28,7 +28,7 @@ public class MouseBindings
         // IMPORTANT: update the memory referenced by the key, and Dictionary uses caching for performance, and thus 
         // IMPORTANT: Apply will update the Dictionary with the new mouseEventArgs, but the old mouseEventArgs will still be in the dictionary.
         // IMPORTANT: See the ConfigurationManager.Illustrate_DeepMemberWiseCopy_Breaks_Dictionary test for details.
-        Bindings.Add (mouseEventArgs, binding);
+        _bindings.Add (mouseEventArgs, binding);
     }
 
     /// <summary>
@@ -42,16 +42,16 @@ public class MouseBindings
     ///     Commands are only ever applied to the current <see cref="View"/> (i.e. this feature cannot be used to switch
     ///     focus to another view and perform multiple commands there).
     /// </remarks>
-    /// <param name="mouseEventArgs">The mouse flags to check.</param>
+    /// <param name="mouseFlags">The mouse flags to check.</param>
     /// <param name="commands">
-    ///     The command to invoked on the <see cref="View"/> when <paramref name="mouseEventArgs"/> is received. When
-    ///     multiple commands are provided,they will be applied in sequence. The bound <paramref name="mouseEventArgs"/> event
+    ///     The command to invoked on the <see cref="View"/> when <paramref name="mouseFlags"/> is received. When
+    ///     multiple commands are provided,they will be applied in sequence. The bound <paramref name="mouseFlags"/> event
     ///     will be
     ///     consumed if any took effect.
     /// </param>
-    public void Add (MouseFlags mouseEventArgs, params Command [] commands)
+    public void Add (MouseFlags mouseFlags, params Command [] commands)
     {
-        if (mouseEventArgs == MouseFlags.None)
+        if (!Enum.IsDefined (typeof (MouseFlags), mouseFlags) || mouseFlags == MouseFlags.None)
         {
             throw new ArgumentException (@"Invalid MouseFlag", nameof (commands));
         }
@@ -61,21 +61,27 @@ public class MouseBindings
             throw new ArgumentException (@"At least one command must be specified", nameof (commands));
         }
 
-        if (TryGet (mouseEventArgs, out MouseBinding binding))
+        if (TryGet (mouseFlags, out MouseBinding binding))
         {
-            throw new InvalidOperationException (@$"A binding for {mouseEventArgs} exists ({binding}).");
+            throw new InvalidOperationException (@$"A binding for {mouseFlags} exists ({binding}).");
         }
 
-        Add (mouseEventArgs, new MouseBinding (commands, mouseEventArgs));
+        Add (mouseFlags, new MouseBinding (commands, mouseFlags));
     }
 
-    // TODO: Add a dictionary comparer that ignores Scope
-    // TODO: This should not be public!
-    /// <summary>The collection of <see cref="MouseBinding"/> objects.</summary>
-    public Dictionary<MouseFlags, MouseBinding> Bindings { get; } = new ();
+    private readonly Dictionary<MouseFlags, MouseBinding> _bindings = new ();
+
+    /// <summary>
+    ///     Gets the bindings.
+    /// </summary>
+    /// <returns></returns>
+    public IEnumerable<KeyValuePair<MouseFlags, MouseBinding>> GetBindings ()
+    {
+        return _bindings;
+    }
 
     /// <summary>Removes all <see cref="MouseBinding"/> objects from the collection.</summary>
-    public void Clear () { Bindings.Clear (); }
+    public void Clear () { _bindings.Clear (); }
 
     /// <summary>
     ///     Removes all bindings that trigger the given command set. Views can have multiple different events bound to
@@ -84,7 +90,7 @@ public class MouseBindings
     /// <param name="command"></param>
     public void Clear (params Command [] command)
     {
-        KeyValuePair<MouseFlags, MouseBinding> [] kvps = Bindings
+        KeyValuePair<MouseFlags, MouseBinding> [] kvps = _bindings
                                                              .Where (kvp => kvp.Value.Commands.SequenceEqual (command))
                                                              .ToArray ();
 
@@ -118,25 +124,25 @@ public class MouseBindings
     /// </returns>
     public IEnumerable<MouseFlags> GetAllMouseFlagsFromCommands (params Command [] commands)
     {
-        return Bindings.Where (a => a.Value.Commands.SequenceEqual (commands)).Select (a => a.Key);
+        return _bindings.Where (a => a.Value.Commands.SequenceEqual (commands)).Select (a => a.Key);
     }
 
     /// <summary>
     ///     Gets the <see cref="MouseFlags"/> that are bound.
     /// </summary>
     /// <returns></returns>
-    public IEnumerable<MouseFlags> GetBoundMouseFlags () { return Bindings.Keys; }
+    public IEnumerable<MouseFlags> GetBoundMouseFlags () { return _bindings.Keys; }
 
-    /// <summary>Gets the array of <see cref="Command"/>s bound to <paramref name="mouseEventArgs"/> if it exists.</summary>
-    /// <param name="mouseEventArgs">The key to check.</param>
+    /// <summary>Gets the array of <see cref="Command"/>s bound to <paramref name="mouseFlags"/> if it exists.</summary>
+    /// <param name="mouseFlags">The key to check.</param>
     /// <returns>
-    ///     The array of <see cref="Command"/>s if <paramref name="mouseEventArgs"/> is bound. An empty <see cref="Command"/>
+    ///     The array of <see cref="Command"/>s if <paramref name="mouseFlags"/> is bound. An empty <see cref="Command"/>
     ///     array
     ///     if not.
     /// </returns>
-    public Command [] GetCommands (MouseFlags mouseEventArgs)
+    public Command [] GetCommands (MouseFlags mouseFlags)
     {
-        if (TryGet (mouseEventArgs, out MouseBinding bindings))
+        if (TryGet (mouseFlags, out MouseBinding bindings))
         {
             return bindings.Commands;
         }
@@ -153,9 +159,9 @@ public class MouseBindings
     ///     The first combination of <see cref="MouseFlags"/> bound to the set of commands specified by
     ///     <paramref name="commands"/>. <see langword="null"/> if the set of caommands was not found.
     /// </returns>
-    public MouseFlags? GetMouseFlagsFromCommands (params Command [] commands)
+    public MouseFlags GetMouseFlagsFromCommands (params Command [] commands)
     {
-        return Bindings.FirstOrDefault (a => a.Value.Commands.SequenceEqual (commands)).Key;
+        return _bindings.FirstOrDefault (a => a.Value.Commands.SequenceEqual (commands)).Key;
     }
 
     /// <summary>Removes a <see cref="MouseBinding"/> from the collection.</summary>
@@ -167,7 +173,7 @@ public class MouseBindings
             return;
         }
 
-        Bindings.Remove (mouseEventArgs);
+        _bindings.Remove (mouseEventArgs);
     }
 
     /// <summary>Replaces the commands already bound to a combination of <see cref="MouseFlags"/>.</summary>
@@ -177,16 +183,17 @@ public class MouseBindings
     ///     </para>
     /// </remarks>
     /// <param name="mouseEventArgs">The combination of <see cref="MouseFlags"/> bound to the command to be replaced.</param>
-    /// <param name="commands">The set of commands to replace the old ones with.</param>
-    public void ReplaceCommands (MouseFlags mouseEventArgs, params Command [] commands)
+    /// <param name="newCommands">The set of commands to replace the old ones with.</param>
+    public void ReplaceCommands (MouseFlags mouseEventArgs, params Command [] newCommands)
     {
         if (TryGet (mouseEventArgs, out MouseBinding binding))
         {
-            binding.Commands = commands;
+            Remove (mouseEventArgs);
+            Add (mouseEventArgs, newCommands);
         }
         else
         {
-            Add (mouseEventArgs, commands);
+            Add (mouseEventArgs, newCommands);
         }
     }
 
@@ -197,16 +204,23 @@ public class MouseBindings
     ///     The new <see cref="MouseFlags"/> to be used. If <see cref="Key.Empty"/> no action
     ///     will be taken.
     /// </param>
-    public void ReplaceKey (MouseFlags oldMouseFlags, MouseFlags newMouseFlags)
+    public void ReplaceMouseFlag (MouseFlags oldMouseFlags, MouseFlags newMouseFlags)
     {
-        if (!TryGet (oldMouseFlags, out MouseBinding _))
+        if (newMouseFlags == MouseFlags.None)
         {
-            throw new InvalidOperationException ($"Key {oldMouseFlags} is not bound.");
+            throw new ArgumentException (@"Invalid MouseFlag", nameof (newMouseFlags));
         }
 
-        MouseBinding value = Bindings [oldMouseFlags];
-        Remove (oldMouseFlags);
-        Add (newMouseFlags, value);
+
+        if (TryGet (oldMouseFlags, out MouseBinding binding))
+        {
+            Remove (oldMouseFlags);
+            Add (newMouseFlags, binding);
+        }
+        else
+        {
+            Add (newMouseFlags, binding);
+        }
     }
 
     /// <summary>Gets the commands bound with the specified <see cref="MouseFlags"/>.</summary>
@@ -221,6 +235,6 @@ public class MouseBindings
     {
         binding = new ([], mouseEventArgs);
 
-        return Bindings.TryGetValue (mouseEventArgs, out binding);
+        return _bindings.TryGetValue (mouseEventArgs, out binding);
     }
 }

+ 7 - 2
Terminal.Gui/View/View.Mouse.cs

@@ -595,8 +595,6 @@ public partial class View // Mouse APIs
             return true;
         }
 
-        // Post-conditions
-
         args.Handled = InvokeCommandsBoundToMouse (args) == true;
 
         return args.Handled;
@@ -643,6 +641,13 @@ public partial class View // Mouse APIs
 
         Highlight?.Invoke (this, args);
 
+        //if (args.Cancel)
+        //{
+        //    return true;
+        //}
+
+        //args.Cancel = InvokeCommandsBoundToMouse (args) == true;
+
         return args.Cancel;
     }
 

+ 1 - 1
UnitTests/Application/ApplicationTests.cs

@@ -552,7 +552,7 @@ public class ApplicationTests
 
         Assert.Equal (Key.Q.WithCtrl, Application.QuitKey);
 
-        Assert.NotEmpty (Application.KeyBindings.GetBindings (Key.Q.WithCtrl));
+        Assert.True (Application.KeyBindings.TryGet (Key.Q.WithCtrl, out _));
 
         Application.Shutdown ();
         Locations = ConfigLocations.Default;

+ 33 - 26
UnitTests/Input/Keyboard/KeyBindingsTests.cs

@@ -6,6 +6,27 @@ namespace Terminal.Gui.InputTests;
 
 public class KeyBindingsTests ()
 {
+    [Fact]
+    public void Add_Adds ()
+    {
+        var keyBindings = new KeyBindings (new ());
+        Command [] commands = { Command.Right, Command.Left };
+
+        var key = new Key (Key.A);
+        keyBindings.Add (Key.A, commands);
+        KeyBinding binding = keyBindings.Get (key);
+        Assert.Contains (Command.Right, binding.Commands);
+        Assert.Contains (Command.Left, binding.Commands);
+
+        binding = keyBindings.Get (key);
+        Assert.Contains (Command.Right, binding.Commands);
+        Assert.Contains (Command.Left, binding.Commands);
+
+        Command [] resultCommands = keyBindings.GetCommands (key);
+        Assert.Contains (Command.Right, resultCommands);
+        Assert.Contains (Command.Left, resultCommands);
+    }
+
     [Fact]
     public void Add_Invalid_Key_Throws ()
     {
@@ -15,7 +36,7 @@ public class KeyBindingsTests ()
     }
 
     [Fact]
-    public void Add_Multiple_Adds ()
+    public void Add_Multiple_Commands_Adds ()
     {
         var keyBindings = new KeyBindings (new ());
         Command [] commands = [Command.Right, Command.Left];
@@ -40,7 +61,7 @@ public class KeyBindingsTests ()
     }
 
     [Fact]
-    public void Add_Single_Adds ()
+    public void Add_Single_Command_Adds ()
     {
         var keyBindings = new KeyBindings (new ());
         keyBindings.Add (Key.A, Command.HotKey);
@@ -55,7 +76,7 @@ public class KeyBindingsTests ()
 
     // Add should not allow duplicates
     [Fact]
-    public void Add_With_Throws_If_Exists ()
+    public void Add_Throws_If_Exists ()
     {
         var keyBindings = new KeyBindings (new View ());
         keyBindings.Add (Key.A, Command.HotKey);
@@ -79,7 +100,14 @@ public class KeyBindingsTests ()
         Assert.Contains (Command.HotKey, resultCommands);
 
         keyBindings = new (new View ());
-        keyBindings.Add (Key.A, new KeyBinding (new [] { Command.HotKey }));
+        keyBindings.Add (Key.A, Command.Accept);
+        Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, Command.ScrollDown));
+
+        resultCommands = keyBindings.GetCommands (Key.A);
+        Assert.Contains (Command.Accept, resultCommands);
+
+        keyBindings = new (new View ());
+        keyBindings.Add (Key.A, new KeyBinding ([Command.HotKey]));
         Assert.Throws<InvalidOperationException> (() => keyBindings.Add (Key.A, new KeyBinding (new [] { Command.Accept })));
 
         resultCommands = keyBindings.GetCommands (Key.A);
@@ -247,7 +275,7 @@ public class KeyBindingsTests ()
     {
         var keyBindings = new KeyBindings (new ());
         keyBindings.ReplaceKey (Key.A, Key.B);
-        Assert.NotEmpty (keyBindings.GetBindings (Key.B));
+        Assert.True (keyBindings.TryGet (Key.B, out _));
     }
 
     [Fact]
@@ -258,27 +286,6 @@ public class KeyBindingsTests ()
         Assert.Throws<InvalidOperationException> (() => keyBindings.ReplaceKey (Key.A, Key.Empty));
     }
 
-    [Fact]
-    public void Add_Adds ()
-    {
-        var keyBindings = new KeyBindings (new ());
-        Command [] commands = { Command.Right, Command.Left };
-
-        var key = new Key (Key.A);
-        keyBindings.Add (Key.A, commands);
-        KeyBinding binding = keyBindings.Get (key);
-        Assert.Contains (Command.Right, binding.Commands);
-        Assert.Contains (Command.Left, binding.Commands);
-
-        binding = keyBindings.Get (key);
-        Assert.Contains (Command.Right, binding.Commands);
-        Assert.Contains (Command.Left, binding.Commands);
-
-        Command [] resultCommands = keyBindings.GetCommands (key);
-        Assert.Contains (Command.Right, resultCommands);
-        Assert.Contains (Command.Left, resultCommands);
-    }
-
     [Fact]
     public void Get_Gets ()
     {

+ 6 - 0
UnitTests/Input/Mouse/MouseBindingTests.cs

@@ -0,0 +1,6 @@
+namespace Terminal.Gui.InputTests;
+
+public class MouseBindingTests
+{
+    // TODO: Add tests for MouseBinding
+}

+ 346 - 0
UnitTests/Input/Mouse/MouseBindingsTests.cs

@@ -0,0 +1,346 @@
+namespace Terminal.Gui.InputTests;
+
+public class MouseBindingsTests
+{
+    [Fact]
+    public void Add_Adds ()
+    {
+        var mouseBindings = new MouseBindings ();
+        Command [] commands = [Command.Right, Command.Left];
+
+        var flags = MouseFlags.AllEvents;
+        mouseBindings.Add (flags, commands);
+        MouseBinding binding = mouseBindings.Get (flags);
+        Assert.Contains (Command.Right, binding.Commands);
+        Assert.Contains (Command.Left, binding.Commands);
+
+        binding = mouseBindings.Get (flags);
+        Assert.Contains (Command.Right, binding.Commands);
+        Assert.Contains (Command.Left, binding.Commands);
+
+        Command [] resultCommands = mouseBindings.GetCommands (flags);
+        Assert.Contains (Command.Right, resultCommands);
+        Assert.Contains (Command.Left, resultCommands);
+    }
+
+    [Fact]
+    public void Add_Invalid_Flag_Throws ()
+    {
+        var mouseBindings = new MouseBindings ();
+        List<Command> commands = new ();
+        Assert.Throws<ArgumentException> (() => mouseBindings.Add (MouseFlags.None, Command.Accept));
+
+        Assert.Throws<ArgumentException> (() => mouseBindings.Add ((MouseFlags)0x8ffffff, Command.Accept));
+    }
+
+    [Fact]
+    public void Add_Multiple_Commands_Adds ()
+    {
+        var mouseBindings = new MouseBindings ();
+        Command [] commands = [Command.Right, Command.Left];
+
+        mouseBindings.Add (MouseFlags.Button1Clicked, commands);
+        Command [] resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.Right, resultCommands);
+        Assert.Contains (Command.Left, resultCommands);
+
+        mouseBindings.Add (MouseFlags.Button2Clicked, commands);
+        resultCommands = mouseBindings.GetCommands (MouseFlags.Button2Clicked);
+        Assert.Contains (Command.Right, resultCommands);
+        Assert.Contains (Command.Left, resultCommands);
+    }
+
+    [Fact]
+    public void Add_No_Commands_Throws ()
+    {
+        var mouseBindings = new MouseBindings ();
+        List<Command> commands = new ();
+        Assert.Throws<ArgumentException> (() => mouseBindings.Add (MouseFlags.Button1Clicked, commands.ToArray ()));
+    }
+
+    [Fact]
+    public void Add_Single_Command_Adds ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        Command [] resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.HotKey, resultCommands);
+
+        mouseBindings.Add (MouseFlags.Button2Clicked, Command.HotKey);
+        resultCommands = mouseBindings.GetCommands (MouseFlags.Button2Clicked);
+        Assert.Contains (Command.HotKey, resultCommands);
+    }
+
+    // Add should not allow duplicates
+    [Fact]
+    public void Add_Throws_If_Exists ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        Assert.Throws<InvalidOperationException> (() => mouseBindings.Add (MouseFlags.Button1Clicked, Command.Accept));
+
+        Command [] resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.HotKey, resultCommands);
+
+        mouseBindings = new ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        Assert.Throws<InvalidOperationException> (() => mouseBindings.Add (MouseFlags.Button1Clicked, Command.Accept));
+
+        resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.HotKey, resultCommands);
+
+        mouseBindings = new ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        Assert.Throws<InvalidOperationException> (() => mouseBindings.Add (MouseFlags.Button1Clicked, Command.Accept));
+
+        resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.HotKey, resultCommands);
+
+        mouseBindings = new ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.Accept);
+        Assert.Throws<InvalidOperationException> (() => mouseBindings.Add (MouseFlags.Button1Clicked, Command.ScrollDown));
+
+        resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.Accept, resultCommands);
+
+        mouseBindings = new ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, new MouseBinding ([Command.HotKey], MouseFlags.Button1Clicked));
+
+        Assert.Throws<InvalidOperationException> (
+                                                  () => mouseBindings.Add (
+                                                                           MouseFlags.Button1Clicked,
+                                                                           new MouseBinding ([Command.Accept], MouseFlags.Button1Clicked)));
+
+        resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.HotKey, resultCommands);
+    }
+
+    // Clear
+    [Fact]
+    public void Clear_Clears ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        mouseBindings.Clear ();
+        Command [] resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Empty (resultCommands);
+        resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Empty (resultCommands);
+    }
+
+    [Fact]
+    public void Defaults ()
+    {
+        var mouseBindings = new MouseBindings ();
+        Assert.Empty (mouseBindings.GetBindings ());
+        Assert.Equal (MouseFlags.None, mouseBindings.GetMouseFlagsFromCommands (Command.Accept));
+    }
+
+    [Fact]
+    public void Get_Binding_Not_Found_Throws ()
+    {
+        var mouseBindings = new MouseBindings ();
+        Assert.Throws<InvalidOperationException> (() => mouseBindings.Get (MouseFlags.Button1Clicked));
+        Assert.Throws<InvalidOperationException> (() => mouseBindings.Get (MouseFlags.AllEvents));
+    }
+
+    // GetCommands
+    [Fact]
+    public void GetCommands_Unknown_ReturnsEmpty ()
+    {
+        var mouseBindings = new MouseBindings ();
+        Command [] resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Empty (resultCommands);
+    }
+
+    [Fact]
+    public void GetCommands_WithCommands_ReturnsCommands ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        Command [] resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.HotKey, resultCommands);
+    }
+
+    [Fact]
+    public void GetCommands_WithMultipleBindings_ReturnsCommands ()
+    {
+        var mouseBindings = new MouseBindings ();
+        Command [] commands = [Command.Right, Command.Left];
+        mouseBindings.Add (MouseFlags.Button1Clicked, commands);
+        mouseBindings.Add (MouseFlags.Button2Clicked, commands);
+        Command [] resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.Right, resultCommands);
+        Assert.Contains (Command.Left, resultCommands);
+        resultCommands = mouseBindings.GetCommands (MouseFlags.Button2Clicked);
+        Assert.Contains (Command.Right, resultCommands);
+        Assert.Contains (Command.Left, resultCommands);
+    }
+
+    [Fact]
+    public void GetCommands_WithMultipleCommands_ReturnsCommands ()
+    {
+        var mouseBindings = new MouseBindings ();
+        Command [] commands = [Command.Right, Command.Left];
+        mouseBindings.Add (MouseFlags.Button1Clicked, commands);
+        Command [] resultCommands = mouseBindings.GetCommands (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.Right, resultCommands);
+        Assert.Contains (Command.Left, resultCommands);
+    }
+
+    [Fact]
+    public void GetMouseFlagsFromCommands_MultipleCommands ()
+    {
+        var mouseBindings = new MouseBindings ();
+        Command [] commands1 = [Command.Right, Command.Left];
+        mouseBindings.Add (MouseFlags.Button1Clicked, commands1);
+
+        Command [] commands2 = { Command.Up, Command.Down };
+        mouseBindings.Add (MouseFlags.Button2Clicked, commands2);
+
+        MouseFlags mouseFlags = mouseBindings.GetMouseFlagsFromCommands (commands1);
+        Assert.Equal (MouseFlags.Button1Clicked, mouseFlags);
+
+        mouseFlags = mouseBindings.GetMouseFlagsFromCommands (commands2);
+        Assert.Equal (MouseFlags.Button2Clicked, mouseFlags);
+    }
+
+    [Fact]
+    public void GetMouseFlagsFromCommands_OneCommand ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.Right);
+
+        MouseFlags mouseFlags = mouseBindings.GetMouseFlagsFromCommands (Command.Right);
+        Assert.Equal (MouseFlags.Button1Clicked, mouseFlags);
+    }
+
+    // GetMouseFlagsFromCommands
+    [Fact]
+    public void GetMouseFlagsFromCommands_Unknown_Returns_Key_Empty ()
+    {
+        var mouseBindings = new MouseBindings ();
+        Assert.Equal (MouseFlags.None, mouseBindings.GetMouseFlagsFromCommands (Command.Accept));
+    }
+
+    [Fact]
+    public void GetMouseFlagsFromCommands_WithCommands_ReturnsKey ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        MouseFlags mouseFlags = mouseBindings.GetMouseFlagsFromCommands (Command.HotKey);
+        Assert.Equal (MouseFlags.Button1Clicked, mouseFlags);
+    }
+
+    [Fact]
+    public void ReplaceMouseFlags_Replaces ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        mouseBindings.Add (MouseFlags.Button2Clicked, Command.HotKey);
+        mouseBindings.Add (MouseFlags.Button3Clicked, Command.HotKey);
+        mouseBindings.Add (MouseFlags.Button4Clicked, Command.HotKey);
+
+        mouseBindings.ReplaceMouseFlag (MouseFlags.Button1Clicked, MouseFlags.Button1DoubleClicked);
+        Assert.Empty (mouseBindings.GetCommands (MouseFlags.Button1Clicked));
+        Assert.Contains (Command.HotKey, mouseBindings.GetCommands (MouseFlags.Button1DoubleClicked));
+
+        mouseBindings.ReplaceMouseFlag (MouseFlags.Button2Clicked, MouseFlags.Button2DoubleClicked);
+        Assert.Empty (mouseBindings.GetCommands (MouseFlags.Button2Clicked));
+        Assert.Contains (Command.HotKey, mouseBindings.GetCommands (MouseFlags.Button2DoubleClicked));
+
+        mouseBindings.ReplaceMouseFlag (MouseFlags.Button3Clicked, MouseFlags.Button3DoubleClicked);
+        Assert.Empty (mouseBindings.GetCommands (MouseFlags.Button3Clicked));
+        Assert.Contains (Command.HotKey, mouseBindings.GetCommands (MouseFlags.Button3DoubleClicked));
+
+        mouseBindings.ReplaceMouseFlag (MouseFlags.Button4Clicked, MouseFlags.Button4DoubleClicked);
+        Assert.Empty (mouseBindings.GetCommands (MouseFlags.Button4Clicked));
+        Assert.Contains (Command.HotKey, mouseBindings.GetCommands (MouseFlags.Button4DoubleClicked));
+    }
+
+    [Fact]
+    public void ReplaceMouseFlags_Replaces_Leaves_Old_Binding ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.Accept);
+        mouseBindings.Add (MouseFlags.Button2Clicked, Command.HotKey);
+
+        mouseBindings.ReplaceMouseFlag (mouseBindings.GetMouseFlagsFromCommands (Command.Accept), MouseFlags.Button3Clicked);
+        Assert.Empty (mouseBindings.GetCommands (MouseFlags.Button1Clicked));
+        Assert.Contains (Command.Accept, mouseBindings.GetCommands (MouseFlags.Button3Clicked));
+    }
+
+    [Fact]
+    public void ReplaceMouseFlags_Adds_If_DoesNotContain_Old ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.ReplaceMouseFlag (MouseFlags.Button1Clicked, MouseFlags.Button2Clicked);
+        Assert.True (mouseBindings.TryGet (MouseFlags.Button2Clicked, out _));
+    }
+
+    [Fact]
+    public void ReplaceMouseFlags_Throws_If_New_Is_None ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        Assert.Throws<ArgumentException> (() => mouseBindings.ReplaceMouseFlag (MouseFlags.Button1Clicked, MouseFlags.None));
+    }
+
+    [Fact]
+    public void Get_Gets ()
+    {
+        var mouseBindings = new MouseBindings ();
+        Command [] commands = [Command.Right, Command.Left];
+
+        mouseBindings.Add (MouseFlags.Button1Clicked, commands);
+        MouseBinding binding = mouseBindings.Get (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.Right, binding.Commands);
+        Assert.Contains (Command.Left, binding.Commands);
+
+        binding = mouseBindings.Get (MouseFlags.Button1Clicked);
+        Assert.Contains (Command.Right, binding.Commands);
+        Assert.Contains (Command.Left, binding.Commands);
+    }
+
+    // TryGet
+    [Fact]
+    public void TryGet_Succeeds ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        bool result = mouseBindings.TryGet (MouseFlags.Button1Clicked, out MouseBinding _);
+        Assert.True (result);
+        ;
+    }
+
+    [Fact]
+    public void TryGet_Unknown_ReturnsFalse ()
+    {
+        var mouseBindings = new MouseBindings ();
+        bool result = mouseBindings.TryGet (MouseFlags.Button1Clicked, out MouseBinding _);
+        Assert.False (result);
+    }
+
+    [Fact]
+    public void TryGet_WithCommands_ReturnsTrue ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.HotKey);
+        bool result = mouseBindings.TryGet (MouseFlags.Button1Clicked, out MouseBinding bindings);
+        Assert.True (result);
+        Assert.Contains (Command.HotKey, bindings.Commands);
+    }
+
+    [Fact]
+    public void ReplaceCommands_Replaces ()
+    {
+        var mouseBindings = new MouseBindings ();
+        mouseBindings.Add (MouseFlags.Button1Clicked, Command.Accept);
+
+        mouseBindings.ReplaceCommands (MouseFlags.Button1Clicked, Command.Refresh);
+
+        bool result = mouseBindings.TryGet (MouseFlags.Button1Clicked, out MouseBinding bindings);
+        Assert.True (result);
+        Assert.Contains (Command.Refresh, bindings.Commands);
+    }
+}

+ 18 - 0
UnitTests/Input/Mouse/MouseEventArgsTest.cs

@@ -0,0 +1,18 @@
+namespace Terminal.Gui.InputTests;
+
+public class MouseEventArgsTests
+{
+    [Fact]
+    public void Constructor_Default_ShouldSetFlagsToNone ()
+    {
+        var eventArgs = new MouseEventArgs ();
+        Assert.Equal (MouseFlags.None, eventArgs.Flags);
+    }
+
+    [Fact]
+    public void HandledProperty_ShouldBeFalseByDefault ()
+    {
+        var eventArgs = new MouseEventArgs ();
+        Assert.False (eventArgs.Handled);
+    }
+}

+ 5 - 5
UnitTests/Views/ShortcutTests.cs

@@ -100,7 +100,7 @@ public class ShortcutTests
             Title = command,
         };
 
-        shortcut.Layout();
+        shortcut.Layout ();
 
         // |0123456789
         // | C  H  K |
@@ -281,7 +281,7 @@ public class ShortcutTests
         var shortcut = new Shortcut ();
 
         shortcut.Key = Key.A;
-        Assert.True(shortcut.HotKeyBindings.TryGet(Key.A, out _));
+        Assert.True (shortcut.HotKeyBindings.TryGet (Key.A, out _));
 
         shortcut.Key = Key.B;
         Assert.False (shortcut.HotKeyBindings.TryGet (Key.A, out _));
@@ -313,15 +313,15 @@ public class ShortcutTests
         var shortcut = new Shortcut ();
 
         shortcut.Key = Key.A;
-        Assert.True (shortcut.HotKeyBindings.TryGet(Key.A, out _));
+        Assert.True (shortcut.HotKeyBindings.TryGet (Key.A, out _));
 
         shortcut.BindKeyToApplication = true;
         Assert.False (shortcut.HotKeyBindings.TryGet (Key.A, out _));
-        Assert.NotEmpty (Application.KeyBindings.GetBindings(Key.A));
+        Assert.True (Application.KeyBindings.TryGet (Key.A, out _));
 
         shortcut.BindKeyToApplication = false;
         Assert.True (shortcut.HotKeyBindings.TryGet (Key.A, out _));
-        Assert.Empty (Application.KeyBindings.GetBindings (Key.A));
+        Assert.False (Application.KeyBindings.TryGet (Key.A, out _));
     }
 
     [Theory]