mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-27 00:07:58 +01:00
* touching publish.yml
* Fixed UICatalog bugs. Added fluent tests.
* marked v1 menu stuff as obsolte
* Tweaks.
Added View.GetSubMenus<type>().
* fixed unit tests
* general messing around
* general messing around
* Playing with Fluent
* ColorScheme tweaks
* WIP: ColorScheme tweaks
* Playing with Fluent
* Merged from laptop2
* Hacky-ish fixes to:
- #4016
- #4014
* Fixed Region bug preventing menus without borders from working
* Tweaks
* Fixed a bunch of CM issues
* Fixed OoptionSelector
* ip
* FixedCM issues
* Fixed CM issues2
* Revert "FixedCM issues"
This reverts commit dd6c6a70a3.
* Reverted stuff
* Found and fixed bug in AllViews_Center_Properly
* Fixed CM issues2
* removed menuv2 onapplied.
Changed how UICatalog Applys CM
* changed test time out to see if it helkps with ubuntu fails
* reset app on fail?
* back to 1500ms
* Made StatusBar nullable.
* Code Cleanup.
* HexEditor Code Cleanup.
* HexEditor Code Cleanup.
* Back to 3000ms. Sigh.
* Trying different logic
* Trying different logic2
* Fixed potential crash in runlop
* Fixed potential crash in runlop2
* Tweaked Spinner stuff
* Removed TabView from TextEffects scenario. Not needed and possible culprit.
* back to 2000ms
* WIP: Revamping menu scenarios
* Menu Scenario refinements.
Fixed a few bugs.
Code cleanup.
* fixed unit test
* Fixed warnings
* Fixed warnings2
* Fixed File.Exit
* WIP: Dealing with QuitKey struggles
* WIP: Dealing with QuitKey struggles 2
* WIP: Dealing with QuitKey struggles 3
* Fixed ListView collection nav bug
* Fixed a bunch of menu stuff.
Fixed Appv2 stuff.
* Lots of refactoring and fixing
* Lots of unit test issues
* Fixed DebugIDisposable issues
* Fixed release build issue
* Fixed release build issue 2
* DebugIDisposable -> EnableDebugIDisposableAsserts and more
* DebugIDisposable -> EnableDebugIDisposableAsserts and more 2
* Fixed Menus scenario - context menu
* Added @bdisp suggested assert. Commented it out as it breaks tests.
* Code cleanup
* Fixed disposed but
* Fixed UICatalog exit
* Fixed Unit test I broke.
Added 'Minimal' Theme that turns off all borders etc...
377 lines
12 KiB
C#
377 lines
12 KiB
C#
using System.Text;
|
||
using Xunit.Abstractions;
|
||
|
||
namespace Terminal.Gui.ViewTests;
|
||
|
||
[Collection ("Global Test Setup")]
|
||
public class HotKeyTests
|
||
{
|
||
[Theory]
|
||
[InlineData (KeyCode.A)]
|
||
[InlineData (KeyCode.A | KeyCode.ShiftMask)]
|
||
[InlineData (KeyCode.D1)]
|
||
[InlineData (KeyCode.D1 | KeyCode.ShiftMask)] // '!'
|
||
[InlineData ((KeyCode)'х')] // Cyrillic x
|
||
[InlineData ((KeyCode)'你')] // Chinese ni
|
||
public void AddKeyBindingsForHotKey_Sets (KeyCode key)
|
||
{
|
||
var view = new View ();
|
||
view.HotKey = KeyCode.Z;
|
||
Assert.Equal (string.Empty, view.Title);
|
||
Assert.Equal (KeyCode.Z, view.HotKey);
|
||
|
||
view.AddKeyBindingsForHotKey (KeyCode.Null, key);
|
||
|
||
// Verify key bindings were set
|
||
|
||
// As passed
|
||
Command [] commands = view.HotKeyBindings.GetCommands (key);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
commands = view.HotKeyBindings.GetCommands (key | KeyCode.AltMask);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
|
||
KeyCode baseKey = key & ~KeyCode.ShiftMask;
|
||
|
||
// If A...Z, with and without shift
|
||
if (baseKey is >= KeyCode.A and <= KeyCode.Z)
|
||
{
|
||
commands = view.HotKeyBindings.GetCommands (key | KeyCode.ShiftMask);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
commands = view.HotKeyBindings.GetCommands (key & ~KeyCode.ShiftMask);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
commands = view.HotKeyBindings.GetCommands (key | KeyCode.AltMask);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
commands = view.HotKeyBindings.GetCommands ((key & ~KeyCode.ShiftMask) | KeyCode.AltMask);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
}
|
||
else
|
||
{
|
||
// Non A..Z keys should not have shift bindings
|
||
if (key.HasFlag (KeyCode.ShiftMask))
|
||
{
|
||
commands = view.HotKeyBindings.GetCommands (key & ~KeyCode.ShiftMask);
|
||
Assert.Empty (commands);
|
||
}
|
||
else
|
||
{
|
||
commands = view.HotKeyBindings.GetCommands (key | KeyCode.ShiftMask);
|
||
Assert.Empty (commands);
|
||
}
|
||
}
|
||
}
|
||
|
||
[Fact]
|
||
public void AddKeyBindingsForHotKey_SetsBinding_Key ()
|
||
{
|
||
var view = new View ();
|
||
view.HotKey = KeyCode.Z;
|
||
Assert.Equal (string.Empty, view.Title);
|
||
Assert.Equal (KeyCode.Z, view.HotKey);
|
||
|
||
view.AddKeyBindingsForHotKey (view.HotKey, Key.A);
|
||
view.HotKeyBindings.TryGet (Key.A, out var binding);
|
||
Assert.Equal (Key.A, binding.Key);
|
||
}
|
||
|
||
[Fact]
|
||
public void AddKeyBindingsForHotKey_SetsBinding_Data ()
|
||
{
|
||
var view = new View ();
|
||
view.HotKey = KeyCode.Z;
|
||
Assert.Equal (KeyCode.Z, view.HotKey);
|
||
|
||
view.AddKeyBindingsForHotKey (view.HotKey, Key.A, "data");
|
||
view.HotKeyBindings.TryGet (Key.A, out var binding);
|
||
Assert.Equal ("data", binding.Data);
|
||
}
|
||
|
||
[Fact]
|
||
public void Defaults ()
|
||
{
|
||
var view = new View ();
|
||
Assert.Equal (string.Empty, view.Title);
|
||
Assert.Equal (KeyCode.Null, view.HotKey);
|
||
|
||
// Verify key bindings were set
|
||
Command [] commands = view.KeyBindings.GetCommands (KeyCode.Null);
|
||
Assert.Empty (commands);
|
||
|
||
commands = view.HotKeyBindings.GetCommands (KeyCode.Null);
|
||
Assert.Empty (commands);
|
||
|
||
Assert.Empty (view.HotKeyBindings.GetBindings ());
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData (KeyCode.Null, true)] // non-shift
|
||
[InlineData (KeyCode.ShiftMask, true)]
|
||
[InlineData (KeyCode.AltMask, true)]
|
||
[InlineData (KeyCode.ShiftMask | KeyCode.AltMask, true)]
|
||
[InlineData (KeyCode.CtrlMask, false)]
|
||
[InlineData (KeyCode.ShiftMask | KeyCode.CtrlMask, false)]
|
||
public void NewKeyDownEvent_Runs_Default_HotKey_Command (KeyCode mask, bool expected)
|
||
{
|
||
var view = new View { HotKeySpecifier = (Rune)'^', Title = "^Test" };
|
||
view.CanFocus = true;
|
||
Assert.False (view.HasFocus);
|
||
view.NewKeyDownEvent (KeyCode.T | mask);
|
||
Assert.Equal (expected, view.HasFocus);
|
||
}
|
||
|
||
[Fact]
|
||
public void NewKeyDownEvent_Ignores_Focus_KeyBindings_SuperView ()
|
||
{
|
||
var view = new View ();
|
||
view.HotKeyBindings.Add (Key.A, Command.HotKey);
|
||
view.KeyDownNotHandled += (s, e) => { Assert.Fail (); };
|
||
|
||
var superView = new View ();
|
||
superView.Add (view);
|
||
|
||
var ke = Key.A;
|
||
superView.NewKeyDownEvent (ke);
|
||
}
|
||
|
||
[Fact]
|
||
public void NewKeyDownEvent_Honors_HotKey_KeyBindings_SuperView ()
|
||
{
|
||
var view = new View ();
|
||
view.HotKeyBindings.Add (Key.A, Command.HotKey);
|
||
bool hotKeyInvoked = false;
|
||
view.HandlingHotKey += (s, e) => { hotKeyInvoked = true; };
|
||
|
||
bool notHandled = false;
|
||
view.KeyDownNotHandled += (s, e) => { notHandled = true; };
|
||
|
||
var superView = new View ();
|
||
superView.Add (view);
|
||
|
||
var ke = Key.A;
|
||
superView.NewKeyDownEvent (ke);
|
||
|
||
Assert.False (notHandled);
|
||
Assert.True (hotKeyInvoked);
|
||
}
|
||
|
||
|
||
[Fact]
|
||
public void NewKeyDownEvent_InNewKeyDownEvent_Invokes_HotKey_Command_With_SuperView ()
|
||
{
|
||
var superView = new View ()
|
||
{
|
||
CanFocus = true
|
||
};
|
||
|
||
var view1 = new View
|
||
{
|
||
HotKeySpecifier = (Rune)'^',
|
||
Title = "view^1",
|
||
CanFocus = true
|
||
};
|
||
|
||
var view2 = new View
|
||
{
|
||
HotKeySpecifier = (Rune)'^',
|
||
Title = "view^2",
|
||
CanFocus = true
|
||
};
|
||
|
||
superView.Add (view1, view2);
|
||
|
||
superView.SetFocus ();
|
||
Assert.True (view1.HasFocus);
|
||
|
||
var ke = Key.D2;
|
||
superView.NewKeyDownEvent (ke);
|
||
Assert.True (view2.HasFocus);
|
||
}
|
||
|
||
[Fact]
|
||
public void Set_RemovesOldKeyBindings ()
|
||
{
|
||
var view = new View ();
|
||
view.HotKey = KeyCode.A;
|
||
Assert.Equal (string.Empty, view.Title);
|
||
Assert.Equal (KeyCode.A, view.HotKey);
|
||
|
||
// Verify key bindings were set
|
||
Command [] commands = view.HotKeyBindings.GetCommands (KeyCode.A);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
|
||
commands = view.HotKeyBindings.GetCommands (KeyCode.A | KeyCode.ShiftMask);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
|
||
commands = view.HotKeyBindings.GetCommands (KeyCode.A | KeyCode.AltMask);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
|
||
commands = view.HotKeyBindings.GetCommands (KeyCode.A | KeyCode.ShiftMask | KeyCode.AltMask);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
|
||
// Now set again
|
||
view.HotKey = KeyCode.B;
|
||
Assert.Equal (string.Empty, view.Title);
|
||
Assert.Equal (KeyCode.B, view.HotKey);
|
||
|
||
commands = view.HotKeyBindings.GetCommands (KeyCode.A);
|
||
Assert.DoesNotContain (Command.HotKey, commands);
|
||
|
||
commands = view.HotKeyBindings.GetCommands (KeyCode.A | KeyCode.ShiftMask);
|
||
Assert.DoesNotContain (Command.HotKey, commands);
|
||
|
||
commands = view.HotKeyBindings.GetCommands (KeyCode.A | KeyCode.AltMask);
|
||
Assert.DoesNotContain (Command.HotKey, commands);
|
||
|
||
commands = view.HotKeyBindings.GetCommands (KeyCode.A | KeyCode.ShiftMask | KeyCode.AltMask);
|
||
Assert.DoesNotContain (Command.HotKey, commands);
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData (KeyCode.A)]
|
||
[InlineData (KeyCode.A | KeyCode.ShiftMask)]
|
||
[InlineData (KeyCode.D1)]
|
||
[InlineData (KeyCode.D1 | KeyCode.ShiftMask)]
|
||
[InlineData ((KeyCode)'!')]
|
||
[InlineData ((KeyCode)'х')] // Cyrillic x
|
||
[InlineData ((KeyCode)'你')] // Chinese ni
|
||
[InlineData ((KeyCode)'ö')] // German o umlaut
|
||
[InlineData (KeyCode.Null)]
|
||
public void Set_Sets_WithValidKey (KeyCode key)
|
||
{
|
||
var view = new View ();
|
||
view.HotKey = key;
|
||
Assert.Equal (key, view.HotKey);
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData (KeyCode.A)]
|
||
[InlineData (KeyCode.A | KeyCode.ShiftMask)]
|
||
[InlineData (KeyCode.D1)]
|
||
[InlineData (KeyCode.D1 | KeyCode.ShiftMask)] // '!'
|
||
[InlineData ((KeyCode)'х')] // Cyrillic x
|
||
[InlineData ((KeyCode)'你')] // Chinese ni
|
||
[InlineData ((KeyCode)'ö')] // German o umlaut
|
||
public void Set_SetsKeyBindings (KeyCode key)
|
||
{
|
||
var view = new View ();
|
||
view.HotKey = key;
|
||
Assert.Equal (string.Empty, view.Title);
|
||
Assert.Equal (key, view.HotKey);
|
||
|
||
// Verify key bindings were set
|
||
|
||
// As passed
|
||
Command [] commands = view.HotKeyBindings.GetCommands (view.HotKey);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
|
||
Key baseKey = view.HotKey.NoShift;
|
||
|
||
// If A...Z, with and without shift
|
||
if (baseKey.IsKeyCodeAtoZ)
|
||
{
|
||
commands = view.HotKeyBindings.GetCommands (view.HotKey.WithShift);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
commands = view.HotKeyBindings.GetCommands (view.HotKey.NoShift);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
commands = view.HotKeyBindings.GetCommands (view.HotKey.WithAlt);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
commands = view.HotKeyBindings.GetCommands (view.HotKey.NoShift.WithAlt);
|
||
Assert.Contains (Command.HotKey, commands);
|
||
}
|
||
else
|
||
{
|
||
// Non A..Z keys should not have shift bindings
|
||
if (view.HotKey.IsShift)
|
||
{
|
||
commands = view.HotKeyBindings.GetCommands (view.HotKey.NoShift);
|
||
Assert.Empty (commands);
|
||
}
|
||
else
|
||
{
|
||
commands = view.HotKeyBindings.GetCommands (view.HotKey.WithShift);
|
||
Assert.Empty (commands);
|
||
}
|
||
}
|
||
}
|
||
|
||
[Fact]
|
||
public void Set_Throws_If_Modifiers_Are_Included ()
|
||
{
|
||
var view = new View ();
|
||
|
||
// A..Z must be naked (Alt is assumed)
|
||
view.HotKey = Key.A.WithAlt;
|
||
Assert.Throws<ArgumentException> (() => view.HotKey = Key.A.WithCtrl);
|
||
|
||
Assert.Throws<ArgumentException> (
|
||
() =>
|
||
view.HotKey =
|
||
KeyCode.A | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask
|
||
);
|
||
|
||
// All others must not have Ctrl (Alt is assumed)
|
||
view.HotKey = Key.D1.WithAlt;
|
||
Assert.Throws<ArgumentException> (() => view.HotKey = Key.D1.WithCtrl);
|
||
|
||
Assert.Throws<ArgumentException> (
|
||
() =>
|
||
view.HotKey =
|
||
KeyCode.D1 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask
|
||
);
|
||
|
||
// Shift is ok (e.g. this is '!')
|
||
view.HotKey = Key.D1.WithShift;
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData (KeyCode.Delete)]
|
||
[InlineData (KeyCode.Backspace)]
|
||
[InlineData (KeyCode.Tab)]
|
||
[InlineData (KeyCode.Enter)]
|
||
[InlineData (KeyCode.Esc)]
|
||
[InlineData (KeyCode.Space)]
|
||
[InlineData (KeyCode.CursorLeft)]
|
||
[InlineData (KeyCode.F1)]
|
||
[InlineData (KeyCode.Null | KeyCode.ShiftMask)]
|
||
public void Set_Throws_With_Invalid_Key (KeyCode key)
|
||
{
|
||
var view = new View ();
|
||
Assert.Throws<ArgumentException> (() => view.HotKey = key);
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData ("Test", KeyCode.Null)]
|
||
[InlineData ("^Test", KeyCode.T)]
|
||
[InlineData ("T^est", KeyCode.E)]
|
||
[InlineData ("Te^st", KeyCode.S)]
|
||
[InlineData ("Tes^t", KeyCode.T)]
|
||
[InlineData ("other", KeyCode.Null)]
|
||
[InlineData ("oTher", KeyCode.Null)]
|
||
[InlineData ("^Öther", (KeyCode)'Ö')]
|
||
[InlineData ("^öther", (KeyCode)'ö')]
|
||
|
||
// BUGBUG: '!' should be supported. Line 968 of TextFormatter filters on char.IsLetterOrDigit
|
||
//[InlineData ("Test^!", (Key)'!')]
|
||
public void Title_Change_Sets_HotKey (string title, KeyCode expectedHotKey)
|
||
{
|
||
var view = new View { HotKeySpecifier = new Rune ('^'), Title = "^Hello" };
|
||
Assert.Equal (KeyCode.H, view.HotKey);
|
||
|
||
view.Title = title;
|
||
Assert.Equal (expectedHotKey, view.HotKey);
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData ("^Test")]
|
||
public void Title_Empty_Sets_HotKey_To_Null (string title)
|
||
{
|
||
var view = new View { HotKeySpecifier = (Rune)'^', Title = title };
|
||
|
||
Assert.Equal (title, view.Title);
|
||
Assert.Equal (KeyCode.T, view.HotKey);
|
||
|
||
view.Title = string.Empty;
|
||
Assert.Equal ("", view.Title);
|
||
Assert.Equal (KeyCode.Null, view.HotKey);
|
||
}
|
||
}
|