mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 07:47:54 +01:00
504 lines
14 KiB
C#
504 lines
14 KiB
C#
using UnitTests;
|
|
using Xunit;
|
|
|
|
using Xunit.Abstractions;
|
|
|
|
namespace UnitTests.DriverTests;
|
|
|
|
/// <summary>
|
|
/// Tests for the FakeDriver to ensure it works properly with the modern component factory architecture.
|
|
/// </summary>
|
|
public class FakeDriverTests (ITestOutputHelper output)
|
|
{
|
|
private readonly ITestOutputHelper _output = output;
|
|
|
|
#region Basic FakeDriver Tests
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Init_Works ()
|
|
{
|
|
// Verify Application was initialized
|
|
Assert.True (Application.Initialized);
|
|
// Assert.NotNull (Application.Top);
|
|
|
|
// Verify it's using a driver facade (modern architecture)
|
|
Assert.IsAssignableFrom<IConsoleDriverFacade> (Application.Driver);
|
|
|
|
_output.WriteLine ($"Driver type: {Application.Driver.GetType().Name}");
|
|
_output.WriteLine ($"Screen size: {Application.Screen}");
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Screen_Has_Default_Size ()
|
|
{
|
|
// Default size should be 80x25
|
|
Assert.Equal (new (0, 0, 80, 25), Application.Screen);
|
|
Assert.Equal (80, Application.Driver!.Cols);
|
|
Assert.Equal (25, Application.Driver.Rows);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Can_Resize ()
|
|
{
|
|
// Start with default size
|
|
Assert.Equal (80, Application.Driver!.Cols);
|
|
Assert.Equal (25, Application.Driver.Rows);
|
|
|
|
// Resize to 100x30
|
|
AutoInitShutdownAttribute.FakeResize (new (100, 30));
|
|
|
|
// Verify new size
|
|
Assert.Equal (100, Application.Driver.Cols);
|
|
Assert.Equal (30, Application.Driver.Rows);
|
|
Assert.Equal (new (0, 0, 100, 30), Application.Screen);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Top_Is_Created ()
|
|
{
|
|
Application.Top = new Toplevel ();
|
|
|
|
Application.Begin (Application.Top);
|
|
|
|
Assert.NotNull (Application.Top);
|
|
Assert.True (Application.Top.IsInitialized);
|
|
Assert.Equal (new (0, 0, 80, 25), Application.Top.Frame);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Can_Add_View_To_Top ()
|
|
{
|
|
Application.Top = new Toplevel ();
|
|
|
|
var label = new Label { Text = "Hello World" };
|
|
Application.Top!.Add (label);
|
|
|
|
Assert.Contains (label, Application.Top!.SubViews);
|
|
Assert.Same (Application.Top, label.SuperView);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_RunIteration_Works ()
|
|
{
|
|
Application.Top = new Toplevel ();
|
|
|
|
var label = new Label { Text = "Hello" };
|
|
Application.Top!.Add (label);
|
|
|
|
|
|
Application.Begin (Application.Top);
|
|
|
|
// Run a single iteration - this should layout and draw
|
|
AutoInitShutdownAttribute.RunIteration ();
|
|
|
|
// Verify the view was laid out
|
|
Assert.True (label.Frame.Width > 0);
|
|
Assert.True (label.IsInitialized);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region AutoInitShutdown Attribute Tests
|
|
|
|
[Theory]
|
|
[InlineData (true)]
|
|
[InlineData (false)]
|
|
public void AutoInitShutdown_Attribute_Respects_AutoInit_Parameter (bool autoInit)
|
|
{
|
|
// When autoInit is false, Application should not be initialized
|
|
// When autoInit is true, Application should be initialized
|
|
|
|
// This test will be called twice - once with autoInit=true, once with false
|
|
// We can't use the attribute directly in the test body, but we can verify
|
|
// the behavior by checking Application.Initialized
|
|
|
|
// For this test to work properly, we need to call Application.Init manually when autoInit=false
|
|
bool wasInitialized = Application.Initialized;
|
|
|
|
try
|
|
{
|
|
if (!wasInitialized)
|
|
{
|
|
Application.ResetState ();
|
|
var fa = new FakeApplicationFactory ();
|
|
using var cleanup = fa.SetupFakeApplication ();
|
|
Assert.True (Application.Initialized);
|
|
}
|
|
else
|
|
{
|
|
Assert.True (Application.Initialized);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (!wasInitialized)
|
|
{
|
|
Application.Shutdown ();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Without_AutoInitShutdown_Application_Is_Not_Initialized ()
|
|
{
|
|
// This test deliberately does NOT use [AutoInitShutdown]
|
|
// Application should not be initialized
|
|
Assert.False (Application.Initialized);
|
|
Assert.Null (Application.Driver);
|
|
Assert.Null (Application.Top);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void AutoInitShutdown_Cleans_Up_After_Test ()
|
|
{
|
|
// This test verifies that Application is properly initialized
|
|
// The After method of AutoInitShutdown will verify cleanup
|
|
Assert.True (Application.Initialized);
|
|
Assert.NotNull (Application.Driver);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SetupFakeDriver Attribute Tests
|
|
|
|
[Fact]
|
|
[SetupFakeDriver]
|
|
public void SetupFakeDriver_Initializes_Driver_With_25x25 ()
|
|
{
|
|
Assert.NotNull (Application.Driver);
|
|
Assert.Equal (new (0, 0, 25, 25), Application.Screen);
|
|
Assert.Equal (25, Application.Driver.Cols);
|
|
Assert.Equal (25, Application.Driver.Rows);
|
|
}
|
|
|
|
[Fact]
|
|
[SetupFakeDriver]
|
|
public void SetupFakeDriver_Driver_Is_FakeConsoleDriver ()
|
|
{
|
|
Assert.NotNull (Application.Driver);
|
|
|
|
// Should be IFakeConsoleDriver
|
|
Assert.IsAssignableFrom<IFakeConsoleDriver> (Application.Driver);
|
|
|
|
_output.WriteLine ($"Driver type: {Application.Driver.GetType().Name}");
|
|
}
|
|
|
|
[Fact]
|
|
[SetupFakeDriver]
|
|
public void SetupFakeDriver_Can_Set_Buffer_Size ()
|
|
{
|
|
var fakeDriver = Application.Driver as IFakeConsoleDriver;
|
|
Assert.NotNull (fakeDriver);
|
|
|
|
fakeDriver!.SetBufferSize (100, 50);
|
|
|
|
Assert.Equal (100, Application.Driver!.Cols);
|
|
Assert.Equal (50, Application.Driver.Rows);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Integration Tests
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Can_Draw_Simple_View ()
|
|
{
|
|
Application.Top = new Toplevel ();
|
|
|
|
var window = new Window
|
|
{
|
|
Title = "Test Window",
|
|
X = 0,
|
|
Y = 0,
|
|
Width = 40,
|
|
Height = 10
|
|
};
|
|
|
|
var label = new Label
|
|
{
|
|
Text = "Hello World",
|
|
X = 1,
|
|
Y = 1
|
|
};
|
|
|
|
window.Add (label);
|
|
Application.Top!.Add (window);
|
|
|
|
Application.Begin (Application.Top);
|
|
|
|
// Run iteration to layout and draw
|
|
AutoInitShutdownAttribute.RunIteration ();
|
|
|
|
// Verify views were initialized and laid out
|
|
Assert.True (window.IsInitialized);
|
|
Assert.True (label.IsInitialized);
|
|
Assert.True (window.Frame.Width > 0);
|
|
Assert.True (label.Frame.Width > 0);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Multiple_RunIterations_Work ()
|
|
{
|
|
Application.Top = new Toplevel ();
|
|
|
|
var label = new Label { Text = "Iteration Test" };
|
|
Application.Top!.Add (label);
|
|
|
|
// Run multiple iterations
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
AutoInitShutdownAttribute.RunIteration ();
|
|
}
|
|
|
|
Application.Begin (Application.Top);
|
|
|
|
// Should still be working
|
|
Assert.True (Application.Initialized);
|
|
Assert.True (label.IsInitialized);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Resize_Triggers_Layout ()
|
|
{
|
|
Application.Top = new Toplevel ();
|
|
|
|
var view = new View
|
|
{
|
|
Width = Dim.Fill (),
|
|
Height = Dim.Fill ()
|
|
};
|
|
Application.Top!.Add (view);
|
|
|
|
Application.Begin (Application.Top);
|
|
|
|
AutoInitShutdownAttribute.FakeResize (new Size (80,25));
|
|
AutoInitShutdownAttribute.RunIteration ();
|
|
|
|
// Check initial size
|
|
var initialFrame = view.Frame;
|
|
Assert.Equal (80, initialFrame.Width);
|
|
Assert.Equal (25, initialFrame.Height);
|
|
|
|
// Resize
|
|
AutoInitShutdownAttribute.FakeResize (new (100, 40));
|
|
|
|
// Check new size
|
|
Assert.Equal (100, view.Frame.Width);
|
|
Assert.Equal (40, view.Frame.Height);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Window_Can_Be_Shown_And_Closed ()
|
|
{
|
|
Application.Top = new Toplevel ();
|
|
|
|
var window = new Window { Title = "Test" };
|
|
Application.Top!.Add (window);
|
|
|
|
Application.Begin (Application.Top);
|
|
|
|
AutoInitShutdownAttribute.RunIteration ();
|
|
|
|
Assert.True (window.IsInitialized);
|
|
Assert.Contains (window, Application.Top!.SubViews);
|
|
|
|
// Remove window
|
|
Application.Top.Remove (window);
|
|
AutoInitShutdownAttribute.RunIteration ();
|
|
|
|
Assert.DoesNotContain (window, Application.Top!.SubViews);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Clipboard Tests
|
|
|
|
[Fact]
|
|
[AutoInitShutdown (useFakeClipboard: true)]
|
|
public void FakeDriver_Clipboard_Works_When_Enabled ()
|
|
{
|
|
Assert.NotNull (Application.Driver!.Clipboard);
|
|
Assert.True (Application.Driver.Clipboard.IsSupported);
|
|
|
|
// Set clipboard content
|
|
Application.Driver.Clipboard.SetClipboardData ("Test content");
|
|
|
|
// Get clipboard content
|
|
string content = Application.Driver.Clipboard.GetClipboardData ();
|
|
Assert.Equal ("Test content", content);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown (useFakeClipboard: true, fakeClipboardAlwaysThrowsNotSupportedException: true)]
|
|
public void FakeDriver_Clipboard_Can_Throw_NotSupportedException ()
|
|
{
|
|
Assert.NotNull (Application.Driver!.Clipboard);
|
|
|
|
// Should throw NotSupportedException
|
|
Assert.Throws<NotSupportedException> (() =>
|
|
Application.Driver.Clipboard.GetClipboardData ());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Error Handling Tests
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Handles_Invalid_Coordinates_Gracefully ()
|
|
{
|
|
Application.Top = new Toplevel ();
|
|
|
|
// Try to add a view with invalid coordinates - should not crash
|
|
var view = new View
|
|
{
|
|
X = -1000,
|
|
Y = -1000,
|
|
Width = 10,
|
|
Height = 10
|
|
};
|
|
|
|
Application.Top!.Add (view);
|
|
|
|
// Should not throw
|
|
AutoInitShutdownAttribute.RunIteration ();
|
|
|
|
Assert.True (Application.Initialized);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeDriver_Survives_Rapid_Resizes ()
|
|
{
|
|
var sizes = new[]
|
|
{
|
|
new Size (80, 25),
|
|
new Size (100, 30),
|
|
new Size (60, 20),
|
|
new Size (120, 40),
|
|
new Size (80, 25)
|
|
};
|
|
|
|
foreach (var size in sizes)
|
|
{
|
|
AutoInitShutdownAttribute.FakeResize (size);
|
|
AutoInitShutdownAttribute.RunIteration ();
|
|
|
|
Assert.Equal (size.Width, Application.Driver!.Cols);
|
|
Assert.Equal (size.Height, Application.Driver.Rows);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ScreenChanged Event Tests
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void SetScreenSize_Fires_ScreenChanged_Event ()
|
|
{
|
|
// Arrange
|
|
bool eventFired = false;
|
|
Size? newSize = null;
|
|
|
|
if (Application.Driver is FakeDriver fakeDriver)
|
|
{
|
|
((ConsoleDriver)fakeDriver).ScreenChanged += (sender, args) =>
|
|
{
|
|
eventFired = true;
|
|
newSize = args.Size;
|
|
};
|
|
|
|
// Act
|
|
fakeDriver.SetScreenSize (100, 40);
|
|
|
|
// Assert
|
|
Assert.True (eventFired);
|
|
Assert.NotNull (newSize);
|
|
Assert.Equal (100, newSize.Value.Width);
|
|
Assert.Equal (40, newSize.Value.Height);
|
|
Assert.Equal (100, Application.Driver!.Cols);
|
|
Assert.Equal (40, Application.Driver.Rows);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void FakeResize_Fires_ScreenChanged_Event_And_Updates_Screen ()
|
|
{
|
|
// Arrange
|
|
bool eventFired = false;
|
|
Size? newSize = null;
|
|
|
|
// Subscribe to deprecated SizeChanged event (which forwards to the new ScreenChanged event)
|
|
Application.Driver!.SizeChanged += (sender, args) =>
|
|
{
|
|
eventFired = true;
|
|
newSize = args.Size;
|
|
};
|
|
|
|
// Act
|
|
AutoInitShutdownAttribute.FakeResize (new Size (90, 35));
|
|
|
|
// Assert
|
|
Assert.True (eventFired);
|
|
Assert.NotNull (newSize);
|
|
Assert.Equal (90, newSize.Value.Width);
|
|
Assert.Equal (35, newSize.Value.Height);
|
|
Assert.Equal (90, Application.Driver.Cols);
|
|
Assert.Equal (35, Application.Driver.Rows);
|
|
Assert.Equal (new Rectangle (0, 0, 90, 35), Application.Screen);
|
|
}
|
|
|
|
[Fact]
|
|
[AutoInitShutdown]
|
|
public void Multiple_Resizes_Maintain_Buffer_Integrity ()
|
|
{
|
|
// Arrange
|
|
Application.Top = new Toplevel ();
|
|
var label = new Label { Text = "Test Label", X = 5, Y = 5 };
|
|
Application.Top.Add (label);
|
|
Application.Begin (Application.Top);
|
|
AutoInitShutdownAttribute.RunIteration ();
|
|
|
|
// Act - Perform multiple resizes
|
|
var sizes = new[]
|
|
{
|
|
new Size (100, 30),
|
|
new Size (80, 25),
|
|
new Size (120, 40),
|
|
new Size (60, 20),
|
|
new Size (100, 30)
|
|
};
|
|
|
|
foreach (Size size in sizes)
|
|
{
|
|
AutoInitShutdownAttribute.FakeResize (size);
|
|
AutoInitShutdownAttribute.RunIteration ();
|
|
|
|
// Assert - Buffer should be properly sized after each resize
|
|
Assert.Equal (size.Width, Application.Driver!.Cols);
|
|
Assert.Equal (size.Height, Application.Driver.Rows);
|
|
Assert.NotNull (Application.Driver.Contents);
|
|
Assert.Equal (size.Height, Application.Driver.Contents.GetLength (0));
|
|
Assert.Equal (size.Width, Application.Driver.Contents.GetLength (1));
|
|
|
|
// Verify the view is still properly laid out
|
|
Assert.True (label.IsInitialized);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|