Browse Source

Investigate fluent assertions for testing v2

tznind 4 months ago
parent
commit
c511101dfe

+ 1 - 0
Terminal.Gui/Terminal.Gui.csproj

@@ -87,6 +87,7 @@
         <InternalsVisibleTo Include="StressTests" />
         <InternalsVisibleTo Include="StressTests" />
         <InternalsVisibleTo Include="IntegrationTests" />
         <InternalsVisibleTo Include="IntegrationTests" />
         <InternalsVisibleTo Include="TerminalGuiDesigner" />
         <InternalsVisibleTo Include="TerminalGuiDesigner" />
+        <InternalsVisibleTo Include="TerminalGuiFluentAssertions" />
         <InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
         <InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
     </ItemGroup>
     </ItemGroup>
     <!-- =================================================================== -->
     <!-- =================================================================== -->

+ 6 - 0
Terminal.sln

@@ -62,6 +62,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StressTests", "Tests\Stress
 EndProject
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests.Parallelizable", "Tests\UnitTestsParallelizable\UnitTests.Parallelizable.csproj", "{DE780834-190A-8277-51FD-750CC666E82D}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests.Parallelizable", "Tests\UnitTestsParallelizable\UnitTests.Parallelizable.csproj", "{DE780834-190A-8277-51FD-750CC666E82D}"
 EndProject
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerminalGuiFluentAssertions", "TerminalGuiFluentAssertions\TerminalGuiFluentAssertions.csproj", "{7C610F03-9E38-409F-9B21-A02D5569E16A}"
+EndProject
 Global
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
 		Debug|Any CPU = Debug|Any CPU
@@ -116,6 +118,10 @@ Global
 		{DE780834-190A-8277-51FD-750CC666E82D}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{DE780834-190A-8277-51FD-750CC666E82D}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{DE780834-190A-8277-51FD-750CC666E82D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{DE780834-190A-8277-51FD-750CC666E82D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{DE780834-190A-8277-51FD-750CC666E82D}.Release|Any CPU.Build.0 = Release|Any CPU
 		{DE780834-190A-8277-51FD-750CC666E82D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7C610F03-9E38-409F-9B21-A02D5569E16A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7C610F03-9E38-409F-9B21-A02D5569E16A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7C610F03-9E38-409F-9B21-A02D5569E16A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7C610F03-9E38-409F-9B21-A02D5569E16A}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 		HideSolutionNode = FALSE

+ 155 - 0
TerminalGuiFluentAssertions/Class1.cs

@@ -0,0 +1,155 @@
+using System.Collections.Concurrent;
+using System.Drawing;
+using Terminal.Gui;
+
+namespace TerminalGuiFluentAssertions;
+
+class FakeInput<T> : IConsoleInput<T>
+{
+    /// <inheritdoc />
+    public void Dispose () { }
+
+    /// <inheritdoc />
+    public void Initialize (ConcurrentQueue<T> inputBuffer) { }
+
+    /// <inheritdoc />
+    public void Run (CancellationToken token)
+    {
+        // Simulate an infinite loop that checks for cancellation
+        token.WaitHandle.WaitOne (); // Blocks until the token is cancelled
+    }
+}
+
+class FakeNetInput : FakeInput<ConsoleKeyInfo>, INetInput
+{
+
+}
+
+class FakeWindowsInput : FakeInput<WindowsConsole.InputRecord>, IWindowsInput
+{
+
+}
+
+class FakeOutput : IConsoleOutput
+{
+    public Size Size { get; set; }
+
+    /// <inheritdoc />
+    public void Dispose ()
+    {
+
+    }
+
+    /// <inheritdoc />
+    public void Write (ReadOnlySpan<char> text)
+    {
+
+    }
+
+    /// <inheritdoc />
+    public void Write (IOutputBuffer buffer)
+    {
+
+    }
+
+    /// <inheritdoc />
+    public Size GetWindowSize ()
+    {
+        return Size;
+    }
+
+    /// <inheritdoc />
+    public void SetCursorVisibility (CursorVisibility visibility)
+    {
+
+    }
+
+    /// <inheritdoc />
+    public void SetCursorPosition (int col, int row)
+    {
+
+    }
+
+}
+/// <summary>
+/// Entry point to fluent assertions.
+/// </summary>
+public static class With
+{
+    /// <summary>
+    /// Entrypoint to fluent assertions
+    /// </summary>
+    /// <param name="width"></param>
+    /// <param name="height"></param>
+    /// <returns></returns>
+    public static GuiTestContext<T> A<T> (int width, int height) where T : Toplevel, new ()
+    {
+        return new GuiTestContext<T> (width,height);
+    }
+}
+public class GuiTestContext<T> where T : Toplevel, new()
+{
+    private readonly CancellationTokenSource _cts;
+    private readonly Task _runTask;
+
+    internal GuiTestContext (int width, int height)
+    {
+        IApplication origApp = ApplicationImpl.Instance;
+
+        var netInput = new FakeNetInput ();
+        var winInput = new FakeWindowsInput ();
+        var output = new FakeOutput ();
+
+        output.Size = new (width, height);
+
+        var v2 = new ApplicationV2(
+                                    () => netInput,
+                                    ()=>output,
+                                    () => winInput,
+                                    () => output);
+
+        // Create a cancellation token
+        _cts = new ();
+
+        // Start the application in a background thread
+        _runTask = Task.Run (() =>
+                             {
+                                 try
+                                 {
+                                     ApplicationImpl.ChangeInstance (v2);
+
+                                     v2.Init ();
+
+                                     Application.Run<T> (); // This will block, but it's on a background thread now
+
+                                     Application.Shutdown ();
+                                 }
+                                 catch (OperationCanceledException)
+                                 {
+
+                                 }
+                                 finally
+                                 {
+                                     ApplicationImpl.ChangeInstance (origApp);
+                                 }
+                             }, _cts.Token);
+
+        Application.Shutdown ();
+    }
+
+    /// <summary>
+    /// Stops the application and waits for the background thread to exit.
+    /// </summary>
+    public void Stop ()
+    {
+        _cts.Cancel ();
+        Application.Invoke (()=>Application.RequestStop());
+        _runTask.Wait (); // Ensure the background thread exits
+    }
+
+    // Cleanup to avoid state bleed between tests
+    public void Dispose ()
+    {
+    }
+}
+

+ 13 - 0
TerminalGuiFluentAssertions/TerminalGuiFluentAssertions.csproj

@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\Terminal.Gui\Terminal.Gui.csproj" />
+  </ItemGroup>
+
+</Project>

+ 1 - 1
Tests/UnitTests/ConsoleDrivers/V2/ApplicationV2Tests.cs

@@ -6,7 +6,7 @@ using Moq;
 namespace UnitTests.ConsoleDrivers.V2;
 namespace UnitTests.ConsoleDrivers.V2;
 public class ApplicationV2Tests
 public class ApplicationV2Tests
 {
 {
-
+    
     private ApplicationV2 NewApplicationV2 ()
     private ApplicationV2 NewApplicationV2 ()
     {
     {
         var netInput = new Mock<INetInput> ();
         var netInput = new Mock<INetInput> ();

+ 35 - 0
Tests/UnitTests/FluentTests/BasicFluentAssertionTests.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TerminalGuiFluentAssertions;
+
+namespace UnitTests.FluentTests;
+public class BasicFluentAssertionTests
+{
+    [Fact]
+    public void GuiTestContext_StartsAndStopsWithoutError ()
+    {
+        var context = With.A<Window> (40, 10);
+
+        // No actual assertions are needed — if no exceptions are thrown, it's working
+        context.Stop ();
+    }
+
+    [Fact]
+    public void Test ()
+    {
+        var myView = new TextField () { Width = 10 };
+
+
+
+        /*
+        using var ctx = With.A<Window> (20, 10)
+                            .Add (myView, 3, 2)
+                            .Focus (myView)
+                            .Type ("Hello");
+
+        Assert.Equal ("Hello", myView.Text);*/
+    }
+}

+ 1 - 0
Tests/UnitTests/UnitTests.csproj

@@ -45,6 +45,7 @@
 	</ItemGroup>
 	</ItemGroup>
 	<ItemGroup>
 	<ItemGroup>
 		<ProjectReference Include="..\..\Terminal.Gui\Terminal.Gui.csproj" />
 		<ProjectReference Include="..\..\Terminal.Gui\Terminal.Gui.csproj" />
+		<ProjectReference Include="..\..\TerminalGuiFluentAssertions\TerminalGuiFluentAssertions.csproj" />
 		<ProjectReference Include="..\..\UICatalog\UICatalog.csproj" />
 		<ProjectReference Include="..\..\UICatalog\UICatalog.csproj" />
 	</ItemGroup>
 	</ItemGroup>
 	<ItemGroup>
 	<ItemGroup>