Files
Terminal.Gui/Tests/UnitTestsParallelizable/Application/Popover/Application.PopoverTests.cs
Tig 5da7e59aa2 Fixes #4456 - Clear MouseGrabView in App.End (#4460)
* Fixed MouseGrabView bug.

Added extensive test coverage for `Keyboard`, `Mouse`, `Timeout`, and `Popover` functionalities, including edge cases and concurrent access. Introduced parameterized and data-driven tests to reduce redundancy and improve clarity.

Refactored codebase for modularity and maintainability,
introducing new namespaces and reorganizing classes. Enhanced `MouseImpl`, `KeyboardImpl`, and `Runnable` implementations with improved event handling, thread safety, and support for the Terminal.Gui Cancellable Work Pattern (CWP).

Removed deprecated code and legacy tests, such as `LogarithmicTimeout` and `SmoothAcceleratingTimeout`. Fixed bugs related to mouse grabbing during drag operations and unbalanced `ApplicationImpl.Begin/End` calls. Improved documentation and code readability with modern C# features.

* Code cleanup.

* Update Tests/UnitTestsParallelizable/Application/Runnable/RunnableIntegrationTests.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Improve null handling and simplify test setup

In `MouseImpl.cs`, added an early `return` after the `UngrabMouse()`
call within the `if (view is null)` block to prevent further execution
when `view` is `null`, improving null reference handling.

In `RunnableIntegrationTests.cs`, removed the initialization of the
`IApplication` object (`app`) from the `MultipleRunnables_IndependentResults`
test method, simplifying the test setup and focusing on runnable behavior.

* Code cleanup

* API doc link cleanup

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-07 13:01:19 -07:00

197 lines
5.2 KiB
C#

#nullable enable
using Moq;
using Terminal.Gui.App;
namespace ApplicationTests.Popover;
public class ApplicationPopoverTests
{
[Fact]
public void Register_AddsPopover ()
{
// Arrange
var popover = new Mock<IPopover> ().Object;
var popoverManager = new ApplicationPopover ();
// Act
popoverManager.Register (popover);
// Assert
Assert.Contains (popover, popoverManager.Popovers);
}
[Fact]
public void DeRegister_RemovesPopover ()
{
// Arrange
var popover = new Mock<IPopover> ().Object;
var popoverManager = new ApplicationPopover ();
popoverManager.Register (popover);
// Act
var result = popoverManager.DeRegister (popover);
// Assert
Assert.True (result);
Assert.DoesNotContain (popover, popoverManager.Popovers);
}
[Fact]
public void Show_SetsActivePopover ()
{
// Arrange
var popover = new Mock<PopoverTestClass> ().Object;
var popoverManager = new ApplicationPopover ();
popoverManager.Register (popover);
// Act
popoverManager.Show (popover);
// Assert
Assert.Equal (popover, popoverManager.GetActivePopover ());
}
[Fact]
public void Hide_ClearsActivePopover ()
{
// Arrange
var popover = new Mock<IPopover> ().Object;
var popoverManager = new ApplicationPopover ();
popoverManager.Register (popover);
popoverManager.Show (popover);
// Act
popoverManager.Hide (popover);
// Assert
Assert.Null (popoverManager.GetActivePopover ());
}
[Fact]
public void DispatchKeyDown_ActivePopoverGetsKey ()
{
// Arrange
var popover = new PopoverTestClass ();
var popoverManager = new ApplicationPopover ();
popoverManager.Register (popover);
popoverManager.Show (popover);
// Act
popoverManager.DispatchKeyDown (Key.A);
// Assert
Assert.Contains (KeyCode.A, popover.HandledKeys);
}
[Fact]
public void DispatchKeyDown_ActivePopoverGetsHotKey ()
{
// Arrange
var popover = new PopoverTestClass ();
var popoverManager = new ApplicationPopover ();
popoverManager.Register (popover);
popoverManager.Show (popover);
// Act
popoverManager.DispatchKeyDown (Key.N.WithCtrl);
// Assert
Assert.Equal (1, popover.NewCommandInvokeCount);
Assert.Contains (Key.N.WithCtrl, popover.HandledKeys);
}
[Fact]
public void DispatchKeyDown_InactivePopoverGetsHotKey ()
{
// Arrange
var activePopover = new PopoverTestClass () { Id = "activePopover" };
var inactivePopover = new PopoverTestClass () { Id = "inactivePopover" }; ;
var popoverManager = new ApplicationPopover ();
popoverManager.Register (activePopover);
popoverManager.Show (activePopover);
popoverManager.Register (inactivePopover);
// Act
popoverManager.DispatchKeyDown (Key.N.WithCtrl);
// Assert
Assert.Equal (1, activePopover.NewCommandInvokeCount);
Assert.Equal (1, inactivePopover.NewCommandInvokeCount);
Assert.Contains (Key.N.WithCtrl, activePopover.HandledKeys);
Assert.NotEmpty (inactivePopover.HandledKeys);
}
[Fact]
public void DispatchKeyDown_InactivePopoverDoesGetKey ()
{
// Arrange
var activePopover = new PopoverTestClass ();
var inactivePopover = new PopoverTestClass ();
var popoverManager = new ApplicationPopover ();
popoverManager.Register (activePopover);
popoverManager.Show (activePopover);
popoverManager.Register (inactivePopover);
// Act
popoverManager.DispatchKeyDown (Key.A);
// Assert
Assert.Contains (Key.A, activePopover.HandledKeys);
Assert.NotEmpty (inactivePopover.HandledKeys);
}
public class PopoverTestClass : View, IPopover
{
public List<Key> HandledKeys { get; } = new List<Key> ();
public int NewCommandInvokeCount { get; private set; }
public PopoverTestClass ()
{
ViewportSettings = ViewportSettingsFlags.Transparent | ViewportSettingsFlags.TransparentMouse;
CanFocus = true;
AddCommand (Command.New, NewCommandHandler!);
HotKeyBindings.Add (Key.N.WithCtrl, Command.New);
AddCommand (Command.Quit, Quit);
KeyBindings.Add (Application.QuitKey, Command.Quit);
return;
bool? Quit (ICommandContext? ctx)
{
if (!Visible)
{
return false;
}
Visible = false;
return true;
}
bool? NewCommandHandler (ICommandContext ctx)
{
NewCommandInvokeCount++;
return false;
}
}
protected override bool OnKeyDown (Key key)
{
HandledKeys.Add (key);
return false;
}
/// <inheritdoc />
public IRunnable? Current { get; set; }
}
}