using System.Text; using Xunit.Abstractions; namespace UnitTests.DriverTests; /// /// Tests for the FakeDriver to ensure it works properly with the modern component factory architecture. /// 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 (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 Application.Driver?.SetScreenSize (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 (); 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 (); 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 (); 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 IDisposable 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_IConsoleDriver () { Assert.NotNull (Application.Driver); // Should be IConsoleDriver Assert.IsAssignableFrom (Application.Driver); _output.WriteLine ($"Driver type: {Application.Driver.GetType ().Name}"); } [Fact] [SetupFakeDriver] public void SetupFakeDriver_Can_Set_Screen_Size () { IConsoleDriver fakeDriver = Application.Driver; Assert.NotNull (fakeDriver); fakeDriver!.SetScreenSize (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 (); 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 (); var label = new Label { Text = "Iteration Test" }; Application.Top!.Add (label); // Run multiple iterations for (var 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 (); var view = new View { Width = Dim.Fill (), Height = Dim.Fill () }; Application.Top!.Add (view); Application.Begin (Application.Top); AutoInitShutdownAttribute.RunIteration (); // Check initial size Rectangle initialFrame = view.Frame; Assert.Equal (80, initialFrame.Width); Assert.Equal (25, initialFrame.Height); // Resize Application.Driver?.SetScreenSize (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 (); 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 (() => Application.Driver.Clipboard.GetClipboardData ()); } #endregion #region Error Handling Tests [Fact] [AutoInitShutdown] public void FakeDriver_Handles_Invalid_Coordinates_Gracefully () { Application.Top = new (); // 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 () { Size [] sizes = new [] { new Size (80, 25), new Size (100, 30), new Size (60, 20), new Size (120, 40), new Size (80, 25) }; foreach (Size size in sizes) { Application.Driver!.SetScreenSize (size.Width, size.Height); AutoInitShutdownAttribute.RunIteration (); Assert.Equal (size.Width, Application.Driver!.Cols); Assert.Equal (size.Height, Application.Driver.Rows); } } #endregion #region Buffer and Fill Tests [Fact] [AutoInitShutdown] public void FakeDriver_Can_Fill_Rectangle () { // Verify driver is initialized with buffers Assert.NotNull (Application.Driver); Assert.NotNull (Application.Driver!.Contents); // Fill a rectangle var rect = new Rectangle (5, 5, 10, 5); Application.Driver.FillRect (rect, (Rune)'X'); // Verify the rectangle was filled for (int row = rect.Y; row < rect.Y + rect.Height; row++) { for (int col = rect.X; col < rect.X + rect.Width; col++) { Assert.Equal ((Rune)'X', Application.Driver.Contents [row, col].Rune); } } } [Fact] [AutoInitShutdown] public void FakeDriver_Buffer_Integrity_After_Multiple_Resizes () { // Start with default size Assert.Equal (80, Application.Driver!.Cols); Assert.Equal (25, Application.Driver.Rows); // Fill with a pattern Application.Driver.FillRect (new (0, 0, 10, 5), (Rune)'A'); // Resize Application.Driver?.SetScreenSize (100, 30); // Verify new size Assert.Equal (100, Application.Driver.Cols); Assert.Equal (30, Application.Driver.Rows); // Verify buffer is clean (no stale runes from previous size) Assert.NotNull (Application.Driver.Contents); Assert.Equal (30, Application.Driver.Contents!.GetLength (0)); Assert.Equal (100, Application.Driver.Contents.GetLength (1)); // Fill with new pattern Application.Driver.FillRect (new (0, 0, 20, 10), (Rune)'B'); // Resize back Application.Driver?.SetScreenSize (80, 25); // Verify size is back Assert.Equal (80, Application.Driver.Cols); Assert.Equal (25, Application.Driver.Rows); // Verify buffer dimensions match Assert.Equal (25, Application.Driver.Contents.GetLength (0)); Assert.Equal (80, Application.Driver.Contents.GetLength (1)); } #endregion #region ScreenChanged Event Tests [Fact] [AutoInitShutdown] public void ScreenChanged_Event_Fires_On_SetScreenSize () { var screenChangedFired = false; Size? newSize = null; Application.Driver!.SizeChanged += (sender, args) => { screenChangedFired = true; newSize = args.Size; }; // Trigger resize using FakeResize which uses SetScreenSize internally Application.Driver?.SetScreenSize (100, 30); // Verify event fired Assert.True (screenChangedFired); Assert.NotNull (newSize); Assert.Equal (100, newSize!.Value.Width); Assert.Equal (30, newSize.Value.Height); } [Fact] [AutoInitShutdown] public void FakeResize_Triggers_ScreenChanged_And_Updates_Application_Screen () { var screenChangedFired = false; Size? eventSize = null; Application.Driver!.SizeChanged += (sender, args) => { screenChangedFired = true; eventSize = args.Size; }; // Use FakeResize helper Application.Driver?.SetScreenSize (120, 40); // Verify event fired Assert.True (screenChangedFired); Assert.NotNull (eventSize); Assert.Equal (120, eventSize!.Value.Width); Assert.Equal (40, eventSize.Value.Height); // Verify Application.Screen was updated Assert.Equal (new (0, 0, 120, 40), Application.Screen); Assert.Equal (120, Application.Driver.Cols); Assert.Equal (40, Application.Driver.Rows); } [Fact] [AutoInitShutdown] public void SizeChanged_Event_Still_Fires_For_Compatibility () { var sizeChangedFired = false; var screenChangedFired = false; #pragma warning disable CS0618 // Type or member is obsolete Application.Driver!.SizeChanged += (sender, args) => { sizeChangedFired = true; }; #pragma warning restore CS0618 // Type or member is obsolete Application.Driver.SizeChanged += (sender, args) => { screenChangedFired = true; }; // Trigger resize using FakeResize Application.Driver?.SetScreenSize (90, 35); // Both events should fire for compatibility Assert.True (sizeChangedFired); Assert.True (screenChangedFired); } #endregion }