tznind 4 months ago
parent
commit
266f03daef

+ 91 - 17
TerminalGuiFluentTesting/GuiTestContext.cs

@@ -5,6 +5,10 @@ using Terminal.Gui.ConsoleDrivers;
 
 
 namespace TerminalGuiFluentTesting;
 namespace TerminalGuiFluentTesting;
 
 
+/// <summary>
+/// Fluent API context for testing a Terminal.Gui application. Create
+/// an instance using <see cref="With"/> static class.
+/// </summary>
 public class GuiTestContext : IDisposable
 public class GuiTestContext : IDisposable
 {
 {
     private readonly CancellationTokenSource _cts = new ();
     private readonly CancellationTokenSource _cts = new ();
@@ -130,7 +134,9 @@ public class GuiTestContext : IDisposable
         return this;
         return this;
     }
     }
 
 
-    // Cleanup to avoid state bleed between tests
+    /// <summary>
+    /// Cleanup to avoid state bleed between tests
+    /// </summary>
     public void Dispose ()
     public void Dispose ()
     {
     {
         Stop ();
         Stop ();
@@ -164,6 +170,12 @@ public class GuiTestContext : IDisposable
         return this;
         return this;
     }
     }
 
 
+    /// <summary>
+    /// Simulates changing the console size e.g. by resizing window in your operating system
+    /// </summary>
+    /// <param name="width">new Width for the console.</param>
+    /// <param name="height">new Height for the console.</param>
+    /// <returns></returns>
     public GuiTestContext ResizeConsole (int width, int height)
     public GuiTestContext ResizeConsole (int width, int height)
     {
     {
         _output.Size = new (width, height);
         _output.Size = new (width, height);
@@ -181,6 +193,11 @@ public class GuiTestContext : IDisposable
         return WaitIteration ();
         return WaitIteration ();
     }
     }
 
 
+    /// <summary>
+    /// Writes all Terminal.Gui engine logs collected so far to the <paramref name="writer"/>
+    /// </summary>
+    /// <param name="writer"></param>
+    /// <returns></returns>
     public GuiTestContext WriteOutLogs (TextWriter writer)
     public GuiTestContext WriteOutLogs (TextWriter writer)
     {
     {
         writer.WriteLine (_logsSb.ToString ());
         writer.WriteLine (_logsSb.ToString ());
@@ -188,6 +205,12 @@ public class GuiTestContext : IDisposable
         return WaitIteration ();
         return WaitIteration ();
     }
     }
 
 
+    /// <summary>
+    /// Waits until the end of the current iteration of the main loop. Optionally
+    /// running a given <paramref name="a"/> action on the UI thread at that time.
+    /// </summary>
+    /// <param name="a"></param>
+    /// <returns></returns>
     public GuiTestContext WaitIteration (Action? a = null)
     public GuiTestContext WaitIteration (Action? a = null)
     {
     {
         a ??= () => { };
         a ??= () => { };
@@ -212,6 +235,12 @@ public class GuiTestContext : IDisposable
         return this;
         return this;
     }
     }
 
 
+    /// <summary>
+    /// Performs the supplied <paramref name="doAction"/> immediately.
+    /// Enables running commands without breaking the Fluent API calls.
+    /// </summary>
+    /// <param name="doAction"></param>
+    /// <returns></returns>
     public GuiTestContext Then (Action doAction)
     public GuiTestContext Then (Action doAction)
     {
     {
         doAction ();
         doAction ();
@@ -219,8 +248,24 @@ public class GuiTestContext : IDisposable
         return this;
         return this;
     }
     }
 
 
+    /// <summary>
+    /// Simulates a right click at the given screen coordinates on the current driver.
+    /// This is a raw input event that goes through entire processing pipeline as though
+    /// user had pressed the mouse button physically.
+    /// </summary>
+    /// <param name="screenX">0 indexed screen coordinates</param>
+    /// <param name="screenY">0 indexed screen coordinates</param>
+    /// <returns></returns>
     public GuiTestContext RightClick (int screenX, int screenY) { return Click (WindowsConsole.ButtonState.Button3Pressed, screenX, screenY); }
     public GuiTestContext RightClick (int screenX, int screenY) { return Click (WindowsConsole.ButtonState.Button3Pressed, screenX, screenY); }
 
 
+    /// <summary>
+    /// Simulates a left click at the given screen coordinates on the current driver.
+    /// This is a raw input event that goes through entire processing pipeline as though
+    /// user had pressed the mouse button physically.
+    /// </summary>
+    /// <param name="screenX">0 indexed screen coordinates</param>
+    /// <param name="screenY">0 indexed screen coordinates</param>
+    /// <returns></returns>
     public GuiTestContext LeftClick (int screenX, int screenY) { return Click (WindowsConsole.ButtonState.Button1Pressed, screenX, screenY); }
     public GuiTestContext LeftClick (int screenX, int screenY) { return Click (WindowsConsole.ButtonState.Button1Pressed, screenX, screenY); }
 
 
     private GuiTestContext Click (WindowsConsole.ButtonState btn, int screenX, int screenY)
     private GuiTestContext Click (WindowsConsole.ButtonState btn, int screenX, int screenY)
@@ -297,7 +342,11 @@ public class GuiTestContext : IDisposable
         return this;
         return this;
     }
     }
 
 
-
+    /// <summary>
+    /// Simulates the Right cursor key
+    /// </summary>
+    /// <returns></returns>
+    /// <exception cref="ArgumentOutOfRangeException"></exception>
     public GuiTestContext Right ()
     public GuiTestContext Right ()
     {
     {
         switch (_driver)
         switch (_driver)
@@ -319,6 +368,11 @@ public class GuiTestContext : IDisposable
         return this;
         return this;
     }
     }
 
 
+    /// <summary>
+    /// Simulates the Left cursor key
+    /// </summary>
+    /// <returns></returns>
+    /// <exception cref="ArgumentOutOfRangeException"></exception>
     public GuiTestContext Left ()
     public GuiTestContext Left ()
     {
     {
         switch (_driver)
         switch (_driver)
@@ -340,6 +394,11 @@ public class GuiTestContext : IDisposable
         return this;
         return this;
     }
     }
 
 
+    /// <summary>
+    /// Simulates the up cursor key
+    /// </summary>
+    /// <returns></returns>
+    /// <exception cref="ArgumentOutOfRangeException"></exception>
     public GuiTestContext Up ()
     public GuiTestContext Up ()
     {
     {
         switch (_driver)
         switch (_driver)
@@ -361,6 +420,11 @@ public class GuiTestContext : IDisposable
         return this;
         return this;
     }
     }
 
 
+    /// <summary>
+    /// Simulates pressing the Return/Enter (newline) key.
+    /// </summary>
+    /// <returns></returns>
+    /// <exception cref="ArgumentOutOfRangeException"></exception>
     public GuiTestContext Enter ()
     public GuiTestContext Enter ()
     {
     {
         switch (_driver)
         switch (_driver)
@@ -386,6 +450,31 @@ public class GuiTestContext : IDisposable
         return this;
         return this;
     }
     }
 
 
+    /// <summary>
+    /// Registers a right click handler on the <see cref="LastView"/> added view (or root view) that
+    /// will open the supplied <paramref name="menuItems"/>.
+    /// </summary>
+    /// <param name="ctx"></param>
+    /// <param name="menuItems"></param>
+    /// <returns></returns>
+    public GuiTestContext WithContextMenu (ContextMenu ctx, MenuBarItem menuItems)
+    {
+        LastView.MouseEvent += (s, e) =>
+                               {
+                                   if (e.Flags.HasFlag (MouseFlags.Button3Clicked))
+                                   {
+                                       ctx.Show (menuItems);
+                                   }
+                               };
+
+        return this;
+    }
+
+    /// <summary>
+    /// The last view added (e.g. with <see cref="Add"/>) or the root/current top.
+    /// </summary>
+    public View LastView => _lastView ?? Application.Top ?? throw new ("Could not determine which view to add to");
+
     /// <summary>
     /// <summary>
     ///     Send a full windows OS key including both down and up.
     ///     Send a full windows OS key including both down and up.
     /// </summary>
     /// </summary>
@@ -459,19 +548,4 @@ public class GuiTestContext : IDisposable
 
 
         WaitIteration ();
         WaitIteration ();
     }
     }
-
-    public GuiTestContext WithContextMenu (ContextMenu ctx, MenuBarItem menuItems)
-    {
-        LastView.MouseEvent += (s, e) =>
-                               {
-                                   if (e.Flags.HasFlag (MouseFlags.Button3Clicked))
-                                   {
-                                       ctx.Show (menuItems);
-                                   }
-                               };
-
-        return this;
-    }
-
-    public View LastView => _lastView ?? Application.Top ?? throw new ("Could not determine which view to add to");
 }
 }

+ 1 - 0
TerminalGuiFluentTesting/TerminalGuiFluentTesting.csproj

@@ -4,6 +4,7 @@
 		<TargetFramework>net8.0</TargetFramework>
 		<TargetFramework>net8.0</TargetFramework>
 		<ImplicitUsings>enable</ImplicitUsings>
 		<ImplicitUsings>enable</ImplicitUsings>
 		<Nullable>enable</Nullable>
 		<Nullable>enable</Nullable>
+		<DocumentationFile>bin\$(Configuration)\$(AssemblyName).xml</DocumentationFile>
 	</PropertyGroup>
 	</PropertyGroup>
 
 
 	<ItemGroup>
 	<ItemGroup>

+ 8 - 1
TerminalGuiFluentTesting/V2TestDriver.cs

@@ -7,10 +7,17 @@ using System.Threading.Tasks;
 namespace TerminalGuiFluentTesting;
 namespace TerminalGuiFluentTesting;
 
 
 /// <summary>
 /// <summary>
-/// Which v2 driver should be used
+/// Which v2 driver simulation should be used
 /// </summary>
 /// </summary>
 public enum V2TestDriver
 public enum V2TestDriver
 {
 {
+    /// <summary>
+    /// The v2 windows driver with simulation I/O but core driver classes
+    /// </summary>
     V2Win,
     V2Win,
+
+    /// <summary>
+    /// The v2 net driver with simulation I/O but core driver classes
+    /// </summary>
     V2Net
     V2Net
 }
 }

+ 3 - 2
Tests/IntegrationTests/FluentTests/BasicFluentAssertionTests.cs

@@ -50,9 +50,10 @@ public class BasicFluentAssertionTests
 
 
         using GuiTestContext c = With.A<Window> (40, 10, d)
         using GuiTestContext c = With.A<Window> (40, 10, d)
                                      .Add (lbl)
                                      .Add (lbl)
-                                     .Then (() => Assert.Equal (lbl.Frame.Width, 38)) // Window has 2 border
+                                     .Then (() => Assert.Equal (38, lbl.Frame.Width)) // Window has 2 border
                                      .ResizeConsole (20, 20)
                                      .ResizeConsole (20, 20)
-                                     .Then (() => Assert.Equal (lbl.Frame.Width, 18))
+                                     .Then (() => Assert.Equal (18, lbl.Frame.Width))
+                                     .WriteOutLogs (_out)
                                      .Stop ();
                                      .Stop ();
     }
     }
 
 

+ 2 - 2
Tests/UnitTests/ConsoleDrivers/V2/MainLoopCoordinatorTests.cs

@@ -6,7 +6,7 @@ namespace UnitTests.ConsoleDrivers.V2;
 public class MainLoopCoordinatorTests
 public class MainLoopCoordinatorTests
 {
 {
     [Fact]
     [Fact]
-    public void TestMainLoopCoordinator_InputCrashes_ExceptionSurfacesMainThread ()
+    public async Task TestMainLoopCoordinator_InputCrashes_ExceptionSurfacesMainThread ()
     {
     {
 
 
         var mockLogger = new Mock<ILogger> ();
         var mockLogger = new Mock<ILogger> ();
@@ -26,7 +26,7 @@ public class MainLoopCoordinatorTests
 
 
         // StartAsync boots the main loop and the input thread. But if the input class bombs
         // StartAsync boots the main loop and the input thread. But if the input class bombs
         // on startup it is important that the exception surface at the call site and not lost
         // on startup it is important that the exception surface at the call site and not lost
-        var ex = Assert.ThrowsAsync<AggregateException>(c.StartAsync).Result;
+        var ex = await Assert.ThrowsAsync<AggregateException>(c.StartAsync);
         Assert.Equal ("Crash on boot", ex.InnerExceptions [0].Message);
         Assert.Equal ("Crash on boot", ex.InnerExceptions [0].Message);