Files
Terminal.Gui/Tests/UnitTestsParallelizable/Application/InitTests.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

171 lines
4.5 KiB
C#

using Xunit.Abstractions;
namespace ApplicationTests.Init;
/// <summary>
/// Comprehensive tests for ApplicationImpl.Begin/End logic that manages Current and SessionStack.
/// These tests ensure the fragile state management logic is robust and catches regressions.
/// Tests work directly with ApplicationImpl instances to avoid global Application state issues.
/// </summary>
public class InitTests (ITestOutputHelper output)
{
private readonly ITestOutputHelper _output = output;
[Fact]
public void Init_Unbalanced_Throws ()
{
IApplication? app = Application.Create ();
app.Init ("fake");
Assert.Throws<InvalidOperationException> (() =>
app.Init ("fake")
);
}
[Fact]
public void Init_Null_Driver_Should_Pick_A_Driver ()
{
IApplication app = Application.Create ();
app.Init ();
Assert.NotNull (app.Driver);
app.Dispose ();
}
[Fact]
public void Init_Dispose_Cleans_Up ()
{
IApplication app = Application.Create ();
app.Init ("fake");
app.Dispose ();
#if DEBUG_IDISPOSABLE
// Validate there are no outstanding Responder-based instances
// after cleanup
// Note: We can't check View.Instances in parallel tests as it's a static field
// that would be shared across parallel test runs
#endif
}
[Fact]
public void Init_Dispose_Fire_InitializedChanged ()
{
var initialized = false;
var Dispose = false;
IApplication app = Application.Create ();
app.InitializedChanged += OnApplicationOnInitializedChanged;
app.Init (driverName: "fake");
Assert.True (initialized);
Assert.False (Dispose);
app.Dispose ();
Assert.True (initialized);
Assert.True (Dispose);
app.InitializedChanged -= OnApplicationOnInitializedChanged;
return;
void OnApplicationOnInitializedChanged (object? s, EventArgs<bool> a)
{
if (a.Value)
{
initialized = true;
}
else
{
Dispose = true;
}
}
}
[Fact]
public void Init_KeyBindings_Are_Not_Reset ()
{
IApplication app = Application.Create ();
// Set via Keyboard property (modern API)
app.Keyboard.QuitKey = Key.Q;
Assert.Equal (Key.Q, app.Keyboard.QuitKey);
app.Init ("fake");
Assert.Equal (Key.Q, app.Keyboard.QuitKey);
app.Dispose ();
}
[Fact]
public void Init_NoParam_ForceDriver_Works ()
{
using IApplication app = Application.Create ();
app.ForceDriver = "fake";
// Note: Init() without params picks up driver configuration
app.Init ();
Assert.Equal ("fake", app.Driver!.GetName ());
}
[Fact]
public void Init_Dispose_Resets_Instance_Properties ()
{
IApplication app = Application.Create ();
// Init the app
app.Init (driverName: "fake");
// Verify initialized
Assert.True (app.Initialized);
Assert.NotNull (app.Driver);
// Dispose cleans up
app.Dispose ();
// Check reset state on the instance
CheckReset (app);
// Create a new instance and set values
app = Application.Create ();
app.Init ("fake");
app.StopAfterFirstIteration = true;
app.Keyboard.PrevTabGroupKey = Key.A;
app.Keyboard.NextTabGroupKey = Key.B;
app.Keyboard.QuitKey = Key.C;
app.Keyboard.KeyBindings.Add (Key.D, Command.Cancel);
app.Mouse.CachedViewsUnderMouse.Clear ();
app.Mouse.LastMousePosition = new Point (1, 1);
// Dispose and check reset
app.Dispose ();
CheckReset (app);
return;
void CheckReset (IApplication application)
{
// Check that all fields and properties are reset on the instance
// Public Properties
Assert.Null (application.TopRunnableView);
Assert.Null (application.Mouse.MouseGrabView);
Assert.Null (application.Driver);
Assert.False (application.StopAfterFirstIteration);
// Internal properties
Assert.False (application.Initialized);
Assert.Null (application.MainThreadId);
Assert.Empty (application.Mouse.CachedViewsUnderMouse);
}
}
}