Browse Source

Added Orientation unit tests.
Code cleanup

Tig 1 year ago
parent
commit
74521d831d

+ 12 - 3
Terminal.Gui/View/Orientation/IOrientation.cs

@@ -20,8 +20,8 @@ public interface IOrientation
     /// <summary>
     /// <summary>
     ///     Called when <see cref="Orientation"/> is changing.
     ///     Called when <see cref="Orientation"/> is changing.
     /// </summary>
     /// </summary>
-    /// <param name="currentOrientation">The current orienation.</param>
-    /// <param name="newOrientation">The new orienation.</param>
+    /// <param name="currentOrientation">The current orientation.</param>
+    /// <param name="newOrientation">The new orientation.</param>
     /// <returns><see langword="true"/> to cancel the change.</returns>
     /// <returns><see langword="true"/> to cancel the change.</returns>
     public bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation) { return false; }
     public bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation) { return false; }
 
 
@@ -65,6 +65,11 @@ public class OrientationHelper
         get => _orientation;
         get => _orientation;
         set
         set
         {
         {
+            if (_orientation == value)
+            {
+                return;
+            }
+
             var args = new CancelEventArgs<Orientation> (in _orientation, ref value);
             var args = new CancelEventArgs<Orientation> (in _orientation, ref value);
             OrientationChanging?.Invoke (_owner, args);
             OrientationChanging?.Invoke (_owner, args);
             if (args.Cancel)
             if (args.Cancel)
@@ -81,7 +86,11 @@ public class OrientationHelper
             if (_orientation != value)
             if (_orientation != value)
             {
             {
                 _orientation = value;
                 _orientation = value;
-                _owner.Orientation = value;
+
+                if (_owner is { })
+                {
+                    _owner.Orientation = value;
+                }
             }
             }
 
 
             args = new CancelEventArgs<Orientation> (in old, ref _orientation);
             args = new CancelEventArgs<Orientation> (in old, ref _orientation);

+ 4 - 2
Terminal.Gui/Views/RadioGroup.cs

@@ -380,8 +380,10 @@ public class RadioGroup : View, IDesignable, IOrientation
 
 
                 break;
                 break;
             case Orientation.Horizontal:
             case Orientation.Horizontal:
-                x = _horizontal [_cursor].pos;
-
+                if (_horizontal.Count > 0)
+                {
+                    x = _horizontal [_cursor].pos;
+                }
                 break;
                 break;
 
 
             default:
             default:

+ 7 - 3
UnitTests/UnitTests.csproj

@@ -30,9 +30,10 @@
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <PackageReference Include="JetBrains.Annotations" Version="[2024.2.0,)" PrivateAssets="all" />
     <PackageReference Include="JetBrains.Annotations" Version="[2024.2.0,)" PrivateAssets="all" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="[17.10,18)" />
-    <PackageReference Include="ReportGenerator" Version="[5.3.7,6)" />
-    <PackageReference Include="TestableIO.System.IO.Abstractions.TestingHelpers" Version="[21.0.22,22)" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.0-release-24352-06" />
+    <PackageReference Include="Moq" Version="4.20.70" />
+    <PackageReference Include="ReportGenerator" Version="5.3.8" />
+    <PackageReference Include="TestableIO.System.IO.Abstractions.TestingHelpers" Version="21.0.26" />
     <PackageReference Include="xunit" Version="[2.9.0,3)" />
     <PackageReference Include="xunit" Version="[2.9.0,3)" />
     <PackageReference Include="Xunit.Combinatorial" Version="[1.6.24,2)" />
     <PackageReference Include="Xunit.Combinatorial" Version="[1.6.24,2)" />
     <PackageReference Include="xunit.runner.visualstudio" Version="[2.8.2,3)">
     <PackageReference Include="xunit.runner.visualstudio" Version="[2.8.2,3)">
@@ -58,6 +59,9 @@
     <Using Include="Terminal.Gui" />
     <Using Include="Terminal.Gui" />
     <Using Include="Xunit" />
     <Using Include="Xunit" />
   </ItemGroup>
   </ItemGroup>
+  <ItemGroup>
+    <Folder Include="View\Orientation\" />
+  </ItemGroup>
   <PropertyGroup Label="FineCodeCoverage">
   <PropertyGroup Label="FineCodeCoverage">
     <Enabled>
     <Enabled>
       False
       False

+ 107 - 0
UnitTests/View/Orientation/OrientationHelperTests.cs

@@ -0,0 +1,107 @@
+using Moq;
+
+namespace Terminal.Gui.ViewTests.OrientationTests;
+
+public class OrientationHelperTests
+{
+    [Fact]
+    public void Orientation_Set_NewValue_InvokesChangingAndChangedEvents ()
+    {
+        // Arrange
+        Mock<IOrientation> mockIOrientation = new Mock<IOrientation> ();
+        var orientationHelper = new OrientationHelper (mockIOrientation.Object);
+        var changingEventInvoked = false;
+        var changedEventInvoked = false;
+
+        orientationHelper.OrientationChanging += (sender, e) => { changingEventInvoked = true; };
+        orientationHelper.OrientationChanged += (sender, e) => { changedEventInvoked = true; };
+
+        // Act
+        orientationHelper.Orientation = Orientation.Horizontal;
+
+        // Assert
+        Assert.True (changingEventInvoked, "OrientationChanging event was not invoked.");
+        Assert.True (changedEventInvoked, "OrientationChanged event was not invoked.");
+    }
+
+    [Fact]
+    public void Orientation_Set_NewValue_InvokesOnChangingAndOnChangedOverrides ()
+    {
+        // Arrange
+        Mock<IOrientation> mockIOrientation = new Mock<IOrientation> ();
+        var onChangingOverrideCalled = false;
+        var onChangedOverrideCalled = false;
+
+        mockIOrientation.Setup (x => x.OnOrientationChanging (It.IsAny<Orientation> (), It.IsAny<Orientation> ()))
+                        .Callback (() => onChangingOverrideCalled = true)
+                        .Returns (false); // Ensure it doesn't cancel the change
+
+        mockIOrientation.Setup (x => x.OnOrientationChanged (It.IsAny<Orientation> (), It.IsAny<Orientation> ()))
+                        .Callback (() => onChangedOverrideCalled = true);
+
+        var orientationHelper = new OrientationHelper (mockIOrientation.Object);
+
+        // Act
+        orientationHelper.Orientation = Orientation.Horizontal;
+
+        // Assert
+        Assert.True (onChangingOverrideCalled, "OnOrientationChanging override was not called.");
+        Assert.True (onChangedOverrideCalled, "OnOrientationChanged override was not called.");
+    }
+
+    [Fact]
+    public void Orientation_Set_SameValue_DoesNotInvokeChangingOrChangedEvents ()
+    {
+        // Arrange
+        Mock<IOrientation> mockIOrientation = new Mock<IOrientation> ();
+        var orientationHelper = new OrientationHelper (mockIOrientation.Object);
+        orientationHelper.Orientation = Orientation.Vertical; // Set initial orientation
+        var changingEventInvoked = false;
+        var changedEventInvoked = false;
+
+        orientationHelper.OrientationChanging += (sender, e) => { changingEventInvoked = true; };
+        orientationHelper.OrientationChanged += (sender, e) => { changedEventInvoked = true; };
+
+        // Act
+        orientationHelper.Orientation = Orientation.Vertical; // Set to the same value
+
+        // Assert
+        Assert.False (changingEventInvoked, "OrientationChanging event was invoked.");
+        Assert.False (changedEventInvoked, "OrientationChanged event was invoked.");
+    }
+
+    [Fact]
+    public void Orientation_Set_NewValue_OrientationChanging_CancellationPreventsChange ()
+    {
+        // Arrange
+        Mock<IOrientation> mockIOrientation = new Mock<IOrientation> ();
+        var orientationHelper = new OrientationHelper (mockIOrientation.Object);
+        orientationHelper.OrientationChanging += (sender, e) => { e.Cancel = true; }; // Cancel the change
+
+        // Act
+        orientationHelper.Orientation = Orientation.Horizontal;
+
+        // Assert
+        Assert.Equal (Orientation.Vertical, orientationHelper.Orientation); // Initial orientation is Vertical
+    }
+
+    [Fact]
+    public void Orientation_Set_NewValue_OnOrientationChanging_CancelsChange ()
+    {
+        // Arrange
+        Mock<IOrientation> mockIOrientation = new Mock<IOrientation> ();
+
+        mockIOrientation.Setup (x => x.OnOrientationChanging (It.IsAny<Orientation> (), It.IsAny<Orientation> ()))
+                        .Returns (true); // Override to return true, cancelling the change
+
+        var orientationHelper = new OrientationHelper (mockIOrientation.Object);
+
+        // Act
+        orientationHelper.Orientation = Orientation.Horizontal;
+
+        // Assert
+        Assert.Equal (
+                      Orientation.Vertical,
+                      orientationHelper.Orientation); // Initial orientation is Vertical, and it should remain unchanged due to cancellation
+    }
+}

+ 90 - 0
UnitTests/View/Orientation/OrientationTests.cs

@@ -0,0 +1,90 @@
+namespace Terminal.Gui.ViewTests.OrientationTests;
+
+public class OrientationTests
+{
+    private class CustomView : View, IOrientation
+    {
+        private readonly OrientationHelper _orientationHelper;
+
+        public CustomView ()
+        {
+            _orientationHelper = new (this);
+            Orientation = Orientation.Vertical;
+            _orientationHelper.OrientationChanging += (sender, e) => OrientationChanging?.Invoke (this, e);
+            _orientationHelper.OrientationChanged += (sender, e) => OrientationChanged?.Invoke (this, e);
+        }
+
+        public Orientation Orientation
+        {
+            get => _orientationHelper.Orientation;
+            set => _orientationHelper.Orientation = value;
+        }
+
+        public event EventHandler<CancelEventArgs<Orientation>> OrientationChanging;
+        public event EventHandler<CancelEventArgs<Orientation>> OrientationChanged;
+
+        public bool CancelOnOrientationChanging { get; set; }
+
+        public bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation)
+        {
+            // Custom logic before orientation changes
+            return CancelOnOrientationChanging; // Return true to cancel the change
+        }
+
+        public void OnOrientationChanged (Orientation oldOrientation, Orientation newOrientation)
+        {
+            // Custom logic after orientation has changed
+        }
+    }
+
+    [Fact]
+    public void Orientation_Change_IsSuccessful ()
+    {
+        // Arrange
+        var customView = new CustomView ();
+        var orientationChanged = false;
+        customView.OrientationChanged += (sender, e) => orientationChanged = true;
+
+        // Act
+        customView.Orientation = Orientation.Horizontal;
+
+        // Assert
+        Assert.True (orientationChanged, "OrientationChanged event was not invoked.");
+        Assert.Equal (Orientation.Horizontal, customView.Orientation);
+    }
+
+    [Fact]
+    public void Orientation_Change_OrientationChanging_Set_Cancel_IsCancelled ()
+    {
+        // Arrange
+        var customView = new CustomView ();
+        customView.OrientationChanging += (sender, e) => e.Cancel = true; // Cancel the orientation change
+        var orientationChanged = false;
+        customView.OrientationChanged += (sender, e) => orientationChanged = true;
+
+        // Act
+        customView.Orientation = Orientation.Horizontal;
+
+        // Assert
+        Assert.False (orientationChanged, "OrientationChanged event was invoked despite cancellation.");
+        Assert.Equal (Orientation.Vertical, customView.Orientation); // Assuming Vertical is the default orientation
+    }
+
+    [Fact]
+    public void Orientation_Change_OnOrientationChanging_Return_True_IsCancelled ()
+    {
+        // Arrange
+        var customView = new CustomView ();
+        customView.CancelOnOrientationChanging = true; // Cancel the orientation change
+
+        var orientationChanged = false;
+        customView.OrientationChanged += (sender, e) => orientationChanged = true;
+
+        // Act
+        customView.Orientation = Orientation.Horizontal;
+
+        // Assert
+        Assert.False (orientationChanged, "OrientationChanged event was invoked despite cancellation.");
+        Assert.Equal (Orientation.Vertical, customView.Orientation); // Assuming Vertical is the default orientation
+    }
+}