瀏覽代碼

Fixing unit tests

Tig 9 月之前
父節點
當前提交
9275163198

+ 2 - 4
Terminal.Gui/View/View.Drawing.cs

@@ -235,10 +235,7 @@ public partial class View // Drawing APIs
             return;
         }
 
-        if (NeedsDisplay)
-        {
-            OnDrawAdornments ();
-        }
+        OnDrawAdornments ();
 
         if (ColorScheme is { })
         {
@@ -486,6 +483,7 @@ public partial class View // Drawing APIs
 
         // Each of these renders lines to either this View's LineCanvas 
         // Those lines will be finally rendered in OnRenderLineCanvas
+        // QUESTION: Why are we not calling Draw here?
         Margin?.OnDrawContent (Margin.Viewport);
         Border?.OnDrawContent (Border.Viewport);
         Padding?.OnDrawContent (Padding.Viewport);

+ 4 - 3
Terminal.Gui/View/View.Layout.cs

@@ -707,12 +707,13 @@ public partial class View // Layout APIs
         }
 
         // If the 'to' is rooted to 'from' it's a special-case.
-        // Use LayoutSubview with the Frame of the 'from'.
-        if (SuperView is { } && GetTopSuperView () is { } && IsLayoutNeeded () && edges.Count > 0)
+        // Use Layout with the ContentSize of the 'from'.
+        // See the Nested_SubViews_Ref_Topmost_SuperView unit test
+        if (edges.Count > 0 && GetTopSuperView () is { })
         {
             foreach ((View from, View to) in edges)
             {
-                Debug.Fail ("This is dead code?");
+                // QUESTION: Do we test this with adornments well enough?
                 to.Layout (from.GetContentSize ());
             }
         }

+ 19 - 15
UnitTests/TestHelpers.cs

@@ -111,10 +111,10 @@ public class AutoInitShutdownAttribute : BeforeAfterTestAttribute
 
         // Reset to defaults
         Locations = ConfigLocations.DefaultOnly;
-        Reset();
+        Reset ();
 
         // Enable subsequent tests that call Init to get all config files (the default).
-       //Locations = ConfigLocations.All;
+        //Locations = ConfigLocations.All;
     }
 
     public override void Before (MethodInfo methodUnderTest)
@@ -244,10 +244,12 @@ internal partial class TestHelpers
     ///     Numbers between 0 and 9 for each row/col of the console.  Must be valid indexes into
     ///     <paramref name="expectedAttributes"/>.
     /// </param>
+    /// <param name="output"></param>
     /// <param name="driver">The ConsoleDriver to use. If null <see cref="Application.Driver"/> will be used.</param>
     /// <param name="expectedAttributes"></param>
     public static void AssertDriverAttributesAre (
         string expectedLook,
+        ITestOutputHelper output,
         ConsoleDriver driver = null,
         params Attribute [] expectedAttributes
     )
@@ -277,12 +279,14 @@ internal partial class TestHelpers
                 switch (match.Count)
                 {
                     case 0:
-                        throw new (
-                                   $"{Application.ToString (driver)}\n"
-                                   + $"Expected Attribute {val} (PlatformColor = {val.Value.PlatformColor}) at Contents[{line},{c}] {contents [line, c]} ((PlatformColor = {contents [line, c].Attribute.Value.PlatformColor}) was not found.\n"
-                                   + $"  Expected: {string.Join (",", expectedAttributes.Select (c => c))}\n"
-                                   + $"  But Was: <not found>"
-                                  );
+                        output.WriteLine (
+                                     $"{Application.ToString (driver)}\n"
+                                     + $"Expected Attribute {val} (PlatformColor = {val.Value.PlatformColor}) at Contents[{line},{c}] {contents [line, c]} ((PlatformColor = {contents [line, c].Attribute.Value.PlatformColor}) was not found.\n"
+                                     + $" Expected: {string.Join (",", expectedAttributes.Select (c => c))}\n"
+                                     + $"  But Was: <not found>"
+                                    );
+                        Assert.Empty (match);
+                        return;
                     case > 1:
                         throw new ArgumentException (
                                                      $"Bad value for expectedColors, {match.Count} Attributes had the same Value"
@@ -294,12 +298,12 @@ internal partial class TestHelpers
 
                 if (colorUsed != userExpected)
                 {
-                    throw new (
-                               $"{Application.ToString (driver)}\n"
-                               + $"Unexpected Attribute at Contents[{line},{c}] {contents [line, c]}.\n"
-                               + $"  Expected: {userExpected} ({expectedAttributes [int.Parse (userExpected.ToString ())]})\n"
-                               + $"  But Was:   {colorUsed} ({val})\n"
-                              );
+                    output.WriteLine ($"{Application.ToString (driver)}");
+                    output.WriteLine ($"Unexpected Attribute at Contents[{line},{c}] {contents [line, c]}.");
+                    output.WriteLine ($" Expected: {userExpected} ({expectedAttributes [int.Parse (userExpected.ToString ())]})");
+                    output.WriteLine ($"  But Was:   {colorUsed} ({val})");
+                    Assert.Equal (userExpected, colorUsed);
+                    return;
                 }
             }
 
@@ -735,7 +739,7 @@ public class TestsAllViews
     public static IEnumerable<object []> AllViewTypes =>
         typeof (View).Assembly
                      .GetTypes ()
-                     .Where (type => type.IsClass && !type.IsAbstract && type.IsPublic && (type.IsSubclassOf (typeof (View)) || type == typeof(View)))
+                     .Where (type => type.IsClass && !type.IsAbstract && type.IsPublic && (type.IsSubclassOf (typeof (View)) || type == typeof (View)))
                      .Select (type => new object [] { type });
 
     public static View CreateInstanceIfNotGeneric (Type type)

+ 2 - 0
UnitTests/Text/TextFormatterTests.cs

@@ -4187,6 +4187,7 @@ ssb
 011111111100000000000
 011111111111111000000
 000000000000000000000",
+                                               _output,
                                                null,
                                                attrs);
 
@@ -4204,6 +4205,7 @@ ssb
 011111111111111111110
 011111111111111111110
 000000000000000000000",
+                                               _output,
                                                null,
                                                attrs);
     }

+ 3 - 0
UnitTests/View/Adornment/AdornmentSubViewTests.cs

@@ -30,6 +30,7 @@ public class AdornmentSubViewTests (ITestOutputHelper output)
         };
         subView.Margin.Thickness = new Thickness (subViewMargin);
         Application.Top.Margin.Add (subView);
+        Application.Top.Layout ();
 
         var foundView = View.GetViewsUnderMouse (new Point(0, 0)).LastOrDefault ();
 
@@ -58,6 +59,7 @@ public class AdornmentSubViewTests (ITestOutputHelper output)
             Visible = false
         };
         Application.Top.Padding.Add (subView);
+        Application.Top.Layout ();
 
         Assert.Equal (Application.Top.Padding, View.GetViewsUnderMouse (new Point(0, 0)).LastOrDefault ());
         Application.Top?.Dispose ();
@@ -76,6 +78,7 @@ public class AdornmentSubViewTests (ITestOutputHelper output)
 
         subView.LayoutStarted += LayoutStarted;
         view.Margin.Thickness = new Thickness (1, 2, 3, 4);
+        view.Layout ();
         Assert.True (raised);
 
         return;

+ 16 - 10
UnitTests/View/Adornment/AdornmentTests.cs

@@ -335,13 +335,16 @@ public class AdornmentTests (ITestOutputHelper output)
     [Fact]
     public void Setting_Thickness_Causes_Parent_Layout ()
     {
-        var view = new View ();
+        var parent = new View ();
         var raised = false;
-        view.BeginInit ();
-        view.EndInit ();
+        parent.BeginInit ();
+        parent.EndInit ();
 
-        view.LayoutStarted += LayoutStarted;
-        view.Margin.Thickness = new Thickness (1, 2, 3, 4);
+        parent.LayoutStarted += LayoutStarted;
+        parent.Margin.Thickness = new Thickness (1, 2, 3, 4);
+        Assert.True (parent.IsLayoutNeeded());
+        Assert.True (parent.Margin.IsLayoutNeeded ());
+        parent.Layout ();
         Assert.True (raised);
 
         return;
@@ -355,13 +358,16 @@ public class AdornmentTests (ITestOutputHelper output)
     [Fact]
     public void Setting_Thickness_Causes_Adornment_Layout ()
     {
-        var view = new View ();
+        var parent = new View ();
         var raised = false;
-        view.BeginInit ();
-        view.EndInit ();
+        parent.BeginInit ();
+        parent.EndInit ();
 
-        view.Margin.LayoutStarted += LayoutStarted;
-        view.Margin.Thickness = new Thickness (1, 2, 3, 4);
+        parent.Margin.LayoutStarted += LayoutStarted;
+        parent.Margin.Thickness = new Thickness (1, 2, 3, 4);
+        Assert.True (parent.IsLayoutNeeded ());
+        Assert.True (parent.Margin.IsLayoutNeeded ());
+        parent.Layout ();
         Assert.True (raised);
 
         return;

+ 7 - 3
UnitTests/View/Adornment/BorderTests.cs

@@ -34,7 +34,7 @@ public class BorderTests (ITestOutputHelper output)
 
         var expected = @"─┤A├─";
         TestHelpers.AssertDriverContentsAre (expected, output);
-        TestHelpers.AssertDriverAttributesAre ("00000", null, view.ColorScheme.Normal);
+        TestHelpers.AssertDriverAttributesAre ("00000", output, null, view.ColorScheme.Normal);
 
         view.CanFocus = true;
         view.SetFocus ();
@@ -42,7 +42,7 @@ public class BorderTests (ITestOutputHelper output)
         Assert.Equal (view.GetFocusColor (), view.Border.GetFocusColor ());
         Assert.Equal (view.ColorScheme.Focus.Foreground, view.Border.GetFocusColor ().Foreground);
         Assert.Equal (view.ColorScheme.Normal.Foreground, view.Border.GetNormalColor ().Foreground);
-        TestHelpers.AssertDriverAttributesAre ("00100", null, view.ColorScheme.Normal, view.GetFocusColor ());
+        TestHelpers.AssertDriverAttributesAre ("00100", output, null, view.ColorScheme.Normal, view.GetFocusColor ());
     }
 
     [Fact]
@@ -68,7 +68,7 @@ public class BorderTests (ITestOutputHelper output)
 
         var expected = @"─┤A├─";
         TestHelpers.AssertDriverContentsAre (expected, output);
-        TestHelpers.AssertDriverAttributesAre ("00000", null, view.ColorScheme.Normal);
+        TestHelpers.AssertDriverAttributesAre ("00000", output, null, view.ColorScheme.Normal);
     }
 
     [Theory]
@@ -677,6 +677,8 @@ public class BorderTests (ITestOutputHelper output)
 
         var view = new View { X = frameX, Y = frameY, Width = 10, Height = 10 };
         super.Add (view);
+        superSuper.Layout ();
+
         var expected = new Rectangle (expectedScreenX, expectedScreenY, 10, 10);
         Rectangle actual = view.FrameToScreen ();
         Assert.Equal (expected, actual);
@@ -709,6 +711,8 @@ public class BorderTests (ITestOutputHelper output)
 
         var view = new View { X = frameX, Y = frameY, Width = 10, Height = 10 };
         super.Add (view);
+        super.Layout ();
+
         var expected = new Rectangle (expectedScreenX, expectedScreenY, 10, 10);
         Rectangle actual = view.FrameToScreen ();
         Assert.Equal (expected, actual);

+ 2 - 1
UnitTests/View/Adornment/MarginTests.cs

@@ -28,6 +28,7 @@ public class MarginTests (ITestOutputHelper output)
         superView.BeginInit ();
         superView.EndInit ();
         View.Diagnostics = ViewDiagnosticFlags.Padding;
+        view.SetNeedsDisplay();
         view.Draw ();
         View.Diagnostics = ViewDiagnosticFlags.Off;
 
@@ -38,6 +39,6 @@ M M
 MMM",
                                              output
                                             );
-        TestHelpers.AssertDriverAttributesAre ("0", null, superView.GetNormalColor ());
+        TestHelpers.AssertDriverAttributesAre ("0", output, null, superView.GetNormalColor ());
     }
 }

+ 1 - 1
UnitTests/View/Adornment/PaddingTests.cs

@@ -33,6 +33,6 @@ P P
 PPP",
                                              output
                                             );
-        TestHelpers.AssertDriverAttributesAre ("0", null, view.GetNormalColor ());
+        TestHelpers.AssertDriverAttributesAre ("0", output, null, view.GetNormalColor ());
     }
 }

+ 3 - 3
UnitTests/View/Adornment/ShadowStyletests.cs

@@ -2,7 +2,7 @@
 
 namespace Terminal.Gui.ViewTests;
 
-public class ShadowStyleTests (ITestOutputHelper _output)
+public class ShadowStyleTests (ITestOutputHelper output)
 {
     [Fact]
     public void Default_None ()
@@ -150,7 +150,7 @@ public class ShadowStyleTests (ITestOutputHelper _output)
         superView.EndInit ();
 
         superView.Draw ();
-        TestHelpers.AssertDriverAttributesAre (expectedAttrs, Application.Driver, attributes);
+        TestHelpers.AssertDriverAttributesAre (expectedAttrs, output, Application.Driver, attributes);
     }
 
     [Theory]
@@ -218,7 +218,7 @@ public class ShadowStyleTests (ITestOutputHelper _output)
         superView.EndInit ();
         superView.Draw ();
 
-        TestHelpers.AssertDriverContentsWithFrameAre (expected, _output);
+        TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
         view.Dispose ();
     }
 }

+ 1 - 0
UnitTests/View/DrawTests.cs

@@ -525,6 +525,7 @@ public class DrawTests (ITestOutputHelper _output)
                                                0
                                                0
                                                """,
+                                               _output,
                                                Application.Driver,
                                                Colors.ColorSchemes ["Base"]!.Normal
                                               );

+ 1 - 1
UnitTests/View/Layout/Dim.AutoTests.MinMax.cs

@@ -51,8 +51,8 @@ public partial class DimAutoTests
             BorderStyle = LineStyle.Single, // a 1 thick adornment
             ValidatePosDim = true
         };
-
         view.SetContentSize (new (contentSize, 0));
+        view.Layout ();
 
         Assert.Equal (expected, view.Frame.Width);
     }

+ 11 - 6
UnitTests/View/Layout/Dim.AutoTests.cs

@@ -89,6 +89,7 @@ public partial class DimAutoTests (ITestOutputHelper output)
             Width = Auto (),
             Height = 1
         };
+        view.Layout ();
         Assert.Equal (4, view.TextFormatter.ConstrainToWidth);
         Assert.Equal (1, view.TextFormatter.ConstrainToHeight);
 
@@ -100,6 +101,7 @@ public partial class DimAutoTests (ITestOutputHelper output)
             Width = 1,
             Height = Auto ()
         };
+        view.Layout ();
         Assert.Equal (1, view.TextFormatter.ConstrainToWidth);
         Assert.Equal (4, view.TextFormatter.ConstrainToHeight);
     }
@@ -114,6 +116,7 @@ public partial class DimAutoTests (ITestOutputHelper output)
             Height = 1,
             Width = Auto ()
         };
+        view.Layout ();
         Assert.Equal (4, view.TextFormatter.ConstrainToWidth);
         Assert.Equal (1, view.TextFormatter.ConstrainToHeight);
     }
@@ -272,10 +275,11 @@ public partial class DimAutoTests (ITestOutputHelper output)
             Text = "_1234",
             Width = Auto ()
         };
+        view.Layout ();
         Assert.Equal (new (4, 0), view.Frame.Size);
 
         view.Height = 1;
-        view.SetRelativeLayout (Application.Screen.Size);
+        view.Layout ();
         Assert.Equal (new (4, 1), view.Frame.Size);
         Size lastSize = view.Frame.Size;
 
@@ -288,8 +292,7 @@ public partial class DimAutoTests (ITestOutputHelper output)
             Width = Auto (),
             Height = 1
         };
-        view.SetRelativeLayout (Application.Screen.Size);
-
+        view.Layout ();
         lastSize = view.Frame.Size;
         view.VerticalTextAlignment = Alignment.Center;
         Assert.Equal (lastSize, view.Frame.Size);
@@ -783,13 +786,14 @@ public partial class DimAutoTests (ITestOutputHelper output)
         };
 
         super.Add (view);
+        super.Layout ();
 
         Rectangle expectedViewport = new (0, 0, 8, 1);
         Assert.Equal (expectedViewport.Size, view.GetContentSize ());
         Assert.Equal (expectedViewport, view.Frame);
         Assert.Equal (expectedViewport, view.Viewport);
 
-        super.LayoutSubviews ();
+        super.Layout ();
         Assert.Equal (expectedViewport, view.Viewport);
 
         super.Dispose ();
@@ -845,6 +849,7 @@ public partial class DimAutoTests (ITestOutputHelper output)
         view.Width = Auto (DimAutoStyle.Text, maximumContentDim: maxWidth);
         view.Height = Auto (DimAutoStyle.Text);
         view.Text = text;
+        view.Layout ();
 
         Assert.Equal (new (expectedW, expectedH), view.Frame.Size);
     }
@@ -862,7 +867,7 @@ public partial class DimAutoTests (ITestOutputHelper output)
         view.Height = Auto (DimAutoStyle.Text);
         view.SetContentSize (new (1, 1));
         view.Text = text;
-        view.SetRelativeLayout (Application.Screen.Size);
+        view.Layout ();
         Assert.Equal (new (expectedW, expectedH), view.Frame.Size);
     }
 
@@ -886,7 +891,7 @@ public partial class DimAutoTests (ITestOutputHelper output)
         view.Text = text;
         superView.Add (view);
 
-        superView.SetRelativeLayout (Application.Screen.Size);
+        superView.Layout ();
         Assert.Equal (new (expectedW, expectedH), view.Frame.Size);
     }
 

+ 0 - 104
UnitTests/View/Layout/Dim.CombineTests.cs

@@ -19,110 +19,6 @@ public class DimCombineTests (ITestOutputHelper output)
     }
 
 
-    // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
-    // TODO: A new test that calls SetRelativeLayout directly is needed.
-    [Fact]
-    [TestRespondersDisposed]
-    public void DimCombine_ObtuseScenario_Does_Not_Throw_If_Two_SubViews_Refs_The_Same_SuperView ()
-    {
-        var t = new View { Width = 80, Height = 25, Text = "top" };
-
-        var w = new Window
-        {
-            Width = Dim.Width (t) - 2, // 78
-            Height = Dim.Height (t) - 2 // 23
-        };
-        var f = new FrameView ();
-
-        var v1 = new View
-        {
-            Width = Dim.Width (w) - 2, // 76
-            Height = Dim.Height (w) - 2 // 21
-        };
-
-        var v2 = new View
-        {
-            Width = Dim.Width (v1) - 2, // 74
-            Height = Dim.Height (v1) - 2 // 19
-        };
-
-        f.Add (v1, v2);
-        w.Add (f);
-        t.Add (w);
-        t.BeginInit ();
-        t.EndInit ();
-
-        f.Width = Dim.Width (t) - Dim.Width (w) + 4; // 80 - 74 = 6
-        f.Height = Dim.Height (t) - Dim.Height (w) + 4; // 25 - 19 = 6
-
-        // BUGBUG: v2 - f references t and w here; t is f's super-superview and w is f's superview. This is supported!
-        Exception exception = Record.Exception (t.LayoutSubviews);
-        Assert.Null (exception);
-        Assert.Equal (80, t.Frame.Width);
-        Assert.Equal (25, t.Frame.Height);
-        Assert.Equal (78, w.Frame.Width);
-        Assert.Equal (23, w.Frame.Height);
-        Assert.Equal (6, f.Frame.Width);
-        Assert.Equal (6, f.Frame.Height);
-        Assert.Equal (76, v1.Frame.Width);
-        Assert.Equal (21, v1.Frame.Height);
-        Assert.Equal (74, v2.Frame.Width);
-        Assert.Equal (19, v2.Frame.Height);
-        t.Dispose ();
-    }
-
-    // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
-    // TODO: A new test that calls SetRelativeLayout directly is needed.
-
-    /// <summary>This is an intentionally obtuse test. See https://github.com/gui-cs/Terminal.Gui/issues/2461</summary>
-    [Fact]
-    [TestRespondersDisposed]
-    public void DimCombine_ObtuseScenario_Throw_If_SuperView_Refs_SubView ()
-    {
-        var t = new View { Width = 80, Height = 25 };
-
-        var w = new Window
-        {
-            Width = Dim.Width (t) - 2, // 78
-            Height = Dim.Height (t) - 2 // 23
-        };
-        var f = new FrameView ();
-
-        var v1 = new View
-        {
-            Width = Dim.Width (w) - 2, // 76
-            Height = Dim.Height (w) - 2 // 21
-        };
-
-        var v2 = new View
-        {
-            Width = Dim.Width (v1) - 2, // 74
-            Height = Dim.Height (v1) - 2 // 19
-        };
-
-        f.Add (v1, v2);
-        w.Add (f);
-        t.Add (w);
-        t.BeginInit ();
-        t.EndInit ();
-
-        f.Width = Dim.Width (t) - Dim.Width (v2); // 80 - 74 = 6
-        f.Height = Dim.Height (t) - Dim.Height (v2); // 25 - 19 = 6
-
-        Assert.Throws<InvalidOperationException> (t.LayoutSubviews);
-        Assert.Equal (80, t.Frame.Width);
-        Assert.Equal (25, t.Frame.Height);
-        Assert.Equal (78, w.Frame.Width);
-        Assert.Equal (23, w.Frame.Height);
-        Assert.Equal (6, f.Frame.Width);
-        Assert.Equal (6, f.Frame.Height);
-        Assert.Equal (76, v1.Frame.Width);
-        Assert.Equal (21, v1.Frame.Height);
-        Assert.Equal (74, v2.Frame.Width);
-        Assert.Equal (19, v2.Frame.Height);
-        t.Dispose ();
-    }
-
     // TODO: This actually a SetRelativeLayout/LayoutSubViews test and should be moved
     // TODO: A new test that calls SetRelativeLayout directly is needed.
     [Fact]

+ 139 - 0
UnitTests/View/Layout/LayoutTests.cs

@@ -608,4 +608,143 @@ public class LayoutTests (ITestOutputHelper output)
         v.Dispose ();
     }
 
+    /// <summary>
+    /// This tests the special case in LayoutSubviews. See https://github.com/gui-cs/Terminal.Gui/issues/2461</summary>
+    [Fact]
+    public void Nested_SubViews_Ref_Topmost_SuperView ()
+    {
+        var superView = new View { Width = 80, Height = 25, Text = "superView" };
+
+        var subView1 = new View
+        {
+            Id = "subView1 - refs superView",
+            Width = Dim.Width (superView) - 2, // 78
+            Height = Dim.Height (superView) - 2 // 23
+        };
+        superView.Add (subView1);
+
+        var subView1OfSubView1 = new View ()
+        {
+            Id = "subView1OfSubView1 - refs superView",
+            Width = Dim.Width (superView) - 4, // 76
+            Height = Dim.Height (superView) - 4 // 21
+        };
+        subView1.Add (subView1OfSubView1);
+
+        superView.Layout ();
+
+        Assert.Equal (80, superView.Frame.Width);
+        Assert.Equal (25, superView.Frame.Height);
+        Assert.Equal (78, subView1.Frame.Width);
+        Assert.Equal (23, subView1.Frame.Height);
+        //Assert.Equal (76, subView2.Frame.Width);
+        //Assert.Equal (21, subView2.Frame.Height);
+
+        Assert.Equal (76, subView1OfSubView1.Frame.Width);
+        Assert.Equal (21, subView1OfSubView1.Frame.Height);
+
+        superView.Dispose ();
+    }
+
+    /// <summary>This is an intentionally obtuse test. See https://github.com/gui-cs/Terminal.Gui/issues/2461</summary>
+    [Fact]
+    public void Does_Not_Throw_If_Nested_SubViews_Ref_Topmost_SuperView ()
+    {
+        var t = new View { Width = 80, Height = 25, Text = "top" };
+
+        var w = new Window
+        {
+            Width = Dim.Width (t) - 2, // 78
+            Height = Dim.Height (t) - 2 // 23
+        };
+        var f = new FrameView ();
+
+        var v1 = new View
+        {
+            Width = Dim.Width (w) - 2, // 76
+            Height = Dim.Height (w) - 2 // 21
+        };
+
+        var v2 = new View
+        {
+            Width = Dim.Width (v1) - 2, // 74
+            Height = Dim.Height (v1) - 2 // 19
+        };
+
+        f.Width = Dim.Width (t) - Dim.Width (w) + 4; // 80 - 74 = 6
+        f.Height = Dim.Height (t) - Dim.Height (w) + 4; // 25 - 19 = 6
+
+        f.Add (v1, v2);
+        w.Add (f);
+        t.Add (w);
+        t.BeginInit ();
+        t.EndInit ();
+
+        // f references t and w here; t is f's super-superview and w is f's superview. This is supported!
+        Exception exception = Record.Exception (() => t.Layout ());
+        Assert.Null (exception);
+        Assert.Equal (80, t.Frame.Width);
+        Assert.Equal (25, t.Frame.Height);
+        Assert.Equal (78, w.Frame.Width);
+        Assert.Equal (23, w.Frame.Height);
+        Assert.Equal (6, f.Frame.Width);
+        Assert.Equal (6, f.Frame.Height);
+        Assert.Equal (76, v1.Frame.Width);
+        Assert.Equal (21, v1.Frame.Height);
+        Assert.Equal (74, v2.Frame.Width);
+        Assert.Equal (19, v2.Frame.Height);
+        t.Dispose ();
+    }
+
+
+    /// <summary>This is an intentionally obtuse test. See https://github.com/gui-cs/Terminal.Gui/issues/2461</summary>
+    [Fact]
+    [TestRespondersDisposed]
+    public void Throw_If_SuperView_Refs_SubView ()
+    {
+        var topSuperView = new View { Width = 80, Height = 25 };
+
+        var superViewRefsTopSuperView = new Window
+        {
+            Width = Dim.Width (topSuperView) - 2, // 78
+            Height = Dim.Height (topSuperView) - 2 // 23
+        };
+
+        var v1 = new View
+        {
+            Width = Dim.Width (superViewRefsTopSuperView) - 2, // 76
+            Height = Dim.Height (superViewRefsTopSuperView) - 2 // 21
+        };
+
+        var v2 = new View
+        {
+            Width = Dim.Width (v1) - 2, // 74
+            Height = Dim.Height (v1) - 2 // 19
+        };
+
+        var superView = new FrameView ();
+        superView.Width = Dim.Width (topSuperView) - Dim.Width (v2); // 80 - 74 = 6
+        superView.Height = Dim.Height (topSuperView) - Dim.Height (v2); // 25 - 19 = 6
+        superView.Add (v1, v2);
+
+        superViewRefsTopSuperView.Add (superView);
+
+        topSuperView.Add (superViewRefsTopSuperView);
+
+        topSuperView.SetRelativeLayout (new (100, 100));
+
+        Assert.Throws<InvalidOperationException> (() => topSuperView.LayoutSubviews());
+        Assert.Equal (80, topSuperView.Frame.Width);
+        Assert.Equal (25, topSuperView.Frame.Height);
+        Assert.Equal (78, superViewRefsTopSuperView.Frame.Width);
+        Assert.Equal (23, superViewRefsTopSuperView.Frame.Height);
+        Assert.Equal (6, superView.Frame.Width);
+        Assert.Equal (6, superView.Frame.Height);
+        Assert.Equal (76, v1.Frame.Width);
+        Assert.Equal (21, v1.Frame.Height);
+        Assert.Equal (74, v2.Frame.Width);
+        Assert.Equal (19, v2.Frame.Height);
+        topSuperView.Dispose ();
+    }
+
 }

+ 10 - 0
UnitTests/View/Layout/ScreenToTests.cs

@@ -31,6 +31,7 @@ public class ScreenToTests
             Height = 10,
             BorderStyle = LineStyle.Single
         };
+        view.Layout ();
 
         Point actual = view.ScreenToViewport (new (x, y));
         Assert.Equal (expectedX, actual.X);
@@ -53,6 +54,7 @@ public class ScreenToTests
     public void ScreenToViewport_NoSuper_NoAdornments (int viewX, int viewY, int x, int y, int expectedX, int expectedY)
     {
         var view = new View { X = viewX, Y = viewY, Width = 10, Height = 10 };
+        view.Layout ();
 
         Point actual = view.ScreenToViewport (new (x, y));
         Assert.Equal (expectedX, actual.X);
@@ -81,6 +83,7 @@ public class ScreenToTests
         };
         var view = new View { X = viewX, Y = viewY, Width = 5, Height = 5 };
         super.Add (view);
+        super.Layout ();
 
         Point actual = view.ScreenToViewport (new (x, y));
         Assert.Equal (expectedX, actual.X);
@@ -110,6 +113,7 @@ public class ScreenToTests
         var view = new View { X = viewX, Y = viewY, Width = 5, Height = 5 };
         view.SetContentSize (new (6, 6));
         super.Add (view);
+        super.Layout ();
 
         view.Viewport = new (1, 1, 5, 5);
 
@@ -133,6 +137,7 @@ public class ScreenToTests
         var super = new View { X = 0, Y = 0, Width = 10, Height = 10 };
         var view = new View { X = viewX, Y = viewY, Width = 5, Height = 5 };
         super.Add (view);
+        super.Layout ();
 
         Point actual = view.ScreenToViewport (new (x, y));
         Assert.Equal (expectedX, actual.X);
@@ -166,6 +171,7 @@ public class ScreenToTests
         };
         view.SetContentSize (new (10, 10));
         super.Add (view);
+        super.Layout ();
 
         view.Viewport = view.Viewport with { Location = new (1, 1) };
 
@@ -197,6 +203,7 @@ public class ScreenToTests
             Height = 10,
             BorderStyle = LineStyle.Single
         };
+        view.Layout ();
 
         Point actual = view.ScreenToFrame (new (x, y));
         Assert.Equal (expectedX, actual.X);
@@ -219,6 +226,7 @@ public class ScreenToTests
     public void ScreenToFrame_NoSuper_NoAdornments (int viewX, int viewY, int x, int y, int expectedX, int expectedY)
     {
         var view = new View { X = viewX, Y = viewY, Width = 10, Height = 10 };
+        view.Layout ();
 
         Point actual = view.ScreenToFrame (new (x, y));
         Assert.Equal (expectedX, actual.X);
@@ -247,6 +255,7 @@ public class ScreenToTests
         };
         var view = new View { X = viewX, Y = viewY, Width = 5, Height = 5 };
         super.Add (view);
+        super.Layout ();
 
         Point actual = view.ScreenToFrame (new (x, y));
         Assert.Equal (expectedX, actual.X);
@@ -268,6 +277,7 @@ public class ScreenToTests
         var super = new View { X = 0, Y = 0, Width = 10, Height = 10 };
         var view = new View { X = viewX, Y = viewY, Width = 5, Height = 5 };
         super.Add (view);
+        super.Layout ();
 
         Point actual = view.ScreenToFrame (new (x, y));
         Assert.Equal (expectedX, actual.X);

+ 3 - 0
UnitTests/View/Layout/SetRelativeLayoutTests.cs

@@ -429,4 +429,7 @@ public class SetRelativeLayoutTests
         Assert.Equal (26, tf.Frame.Width);
         Assert.Equal (1, tf.Frame.Height);
     }
+
+
+
 }

+ 3 - 0
UnitTests/View/ViewTests.cs

@@ -187,6 +187,7 @@ cccccccccccccccccccc",
                                                    @"
 111111111111111111110
 111111111111111111110",
+                                                   output,
                                                    Application.Driver,
                                                    attributes
                                                   );
@@ -197,6 +198,7 @@ cccccccccccccccccccc",
                                                    @"
 222222222222222222220
 111111111111111111110",
+                                                   output,
                                                    Application.Driver,
                                                    attributes
                                                   );
@@ -215,6 +217,7 @@ cccccccccccccccccccc",
                                                    @"
 222222222222222222220
 111111111111111111110",
+                                                   output,
                                                    Application.Driver,
                                                    attributes
                                                   );

+ 6 - 0
UnitTests/Views/ComboBoxTests.cs

@@ -551,6 +551,7 @@ Three ",
 222222
 222222
 222222",
+                                               output,
                                                Application.Driver,
                                                attributes
                                               );
@@ -568,6 +569,7 @@ Three ",
 222222
 000002
 222222",
+                                               output,
                                                Application.Driver,
                                                attributes
                                               );
@@ -585,6 +587,7 @@ Three ",
 222222
 222222
 000002",
+                                               output,
                                                Application.Driver,
                                                attributes
                                               );
@@ -608,6 +611,7 @@ Three ",
 222222
 222222
 000002",
+                                               output,
                                                Application.Driver,
                                                attributes
                                               );
@@ -625,6 +629,7 @@ Three ",
 222222
 000002
 111112",
+                                               output,
                                                Application.Driver,
                                                attributes
                                               );
@@ -642,6 +647,7 @@ Three ",
 000002
 222222
 111112",
+                                               output,
                                                Application.Driver,
                                                attributes
                                               );

+ 4 - 0
UnitTests/Views/MenuBarTests.cs

@@ -380,6 +380,7 @@ public class MenuBarTests (ITestOutputHelper output)
         TestHelpers.AssertDriverAttributesAre (
                                                @"
 00000000000000",
+                                               output,
                                                Application.Driver,
                                                attributes
                                               );
@@ -400,6 +401,7 @@ public class MenuBarTests (ITestOutputHelper output)
 00000000000000
 00000000000000
 00000000000000",
+                                               output,
                                                Application.Driver,
                                                attributes
                                               );
@@ -421,6 +423,7 @@ public class MenuBarTests (ITestOutputHelper output)
 00000000000000
 00000000000000
 00000000000000",
+                                               output,
                                                Application.Driver,
                                                attributes
                                               );
@@ -442,6 +445,7 @@ public class MenuBarTests (ITestOutputHelper output)
 00000000000000
 00000000000000
 00000000000000",
+                                               output,
                                                Application.Driver,
                                                attributes
                                               );

+ 4 - 0
UnitTests/Views/ScrollViewTests.cs

@@ -239,6 +239,7 @@ public class ScrollViewTests (ITestOutputHelper output)
 00000000000000000000000
 00000000000000000000000
 00000000000000000000000",
+                                               output,
                                                null,
                                                attributes
                                               );
@@ -286,6 +287,7 @@ public class ScrollViewTests (ITestOutputHelper output)
 00000000000000000000000
 00000000000000000000000
 00000000000000000000000",
+                                               output,
                                                null,
                                                attributes
                                               );
@@ -332,6 +334,7 @@ public class ScrollViewTests (ITestOutputHelper output)
 00000000000000000000000
 00000000000000000000000
 00000000000000000000000",
+                                               output,
                                                null,
                                                attributes
                                               );
@@ -432,6 +435,7 @@ public class ScrollViewTests (ITestOutputHelper output)
 022222222210
 011111111110
 000000000000",
+                                               output,
                                                null,
                                                attrs
                                               );

+ 10 - 4
UnitTests/Views/TableViewTests.cs

@@ -115,7 +115,7 @@ public class TableViewTests (ITestOutputHelper output)
 00000000000000000000
 01111101101111111110
 ";
-        TestHelpers.AssertDriverAttributesAre (expected, Application.Driver, tv.ColorScheme.Normal, color);
+        TestHelpers.AssertDriverAttributesAre (expected, output, Application.Driver, tv.ColorScheme.Normal, color);
         top.Dispose ();
     }
 
@@ -1094,6 +1094,7 @@ public class TableViewTests (ITestOutputHelper output)
 
         TestHelpers.AssertDriverAttributesAre (
                                                expectedColors,
+                                               output,
                                                Application.Driver,
                                                tv.ColorScheme.Normal,
                                                focused ? tv.ColorScheme.Focus : tv.ColorScheme.HotNormal,
@@ -1129,6 +1130,7 @@ public class TableViewTests (ITestOutputHelper output)
         // (now that the cell value is 5 - which does not match the conditional)
         TestHelpers.AssertDriverAttributesAre (
                                                expectedColors,
+                                               output,
                                                Application.Driver,
                                                tv.ColorScheme.Normal,
                                                focused ? tv.ColorScheme.Focus : tv.ColorScheme.HotNormal
@@ -1187,6 +1189,7 @@ public class TableViewTests (ITestOutputHelper output)
 
         TestHelpers.AssertDriverAttributesAre (
                                                expectedColors,
+                                               output,
                                                Application.Driver,
                                                tv.ColorScheme.Normal,
                                                focused ? rowHighlight.Focus : rowHighlight.HotNormal,
@@ -1222,6 +1225,7 @@ public class TableViewTests (ITestOutputHelper output)
         // (now that the cell value is 5 - which does not match the conditional)
         TestHelpers.AssertDriverAttributesAre (
                                                expectedColors,
+                                               output,
                                                Application.Driver,
                                                tv.ColorScheme.Normal,
                                                focused ? tv.ColorScheme.Focus : tv.ColorScheme.HotNormal
@@ -1267,6 +1271,7 @@ public class TableViewTests (ITestOutputHelper output)
 
         TestHelpers.AssertDriverAttributesAre (
                                                expectedColors,
+                                               output,
                                                Application.Driver,
                                                tv.ColorScheme.Normal,
                                                focused ? tv.ColorScheme.Focus : tv.ColorScheme.HotNormal
@@ -1312,6 +1317,7 @@ public class TableViewTests (ITestOutputHelper output)
 
         TestHelpers.AssertDriverAttributesAre (
                                                expectedColors,
+                                               output,
                                                Application.Driver,
                                                tv.ColorScheme.Normal,
                                                focused ? invertFocus : invertHotNormal
@@ -2291,7 +2297,7 @@ public class TableViewTests (ITestOutputHelper output)
 0101010
 0000000";
 
-        TestHelpers.AssertDriverAttributesAre (expected, Application.Driver, normal, focus);
+        TestHelpers.AssertDriverAttributesAre (expected, output, Application.Driver, normal, focus);
     }
 
     [Fact]
@@ -2344,7 +2350,7 @@ A B C
 000000
 111111";
 
-        TestHelpers.AssertDriverAttributesAre (expected, Application.Driver, normal, focus);
+        TestHelpers.AssertDriverAttributesAre (expected, output, Application.Driver, normal, focus);
     }
 
     [Fact]
@@ -2400,7 +2406,7 @@ A B C
 0111110
 0000000";
 
-        TestHelpers.AssertDriverAttributesAre (expected, Application.Driver, normal, focus);
+        TestHelpers.AssertDriverAttributesAre (expected, output, Application.Driver, normal, focus);
     }
 
     [Theory]

+ 2 - 2
UnitTests/Views/TextFieldTests.cs

@@ -1074,7 +1074,7 @@ public class TextFieldTests (ITestOutputHelper output)
         };
 
         //                                             TAB to jump between text fields.
-        TestHelpers.AssertDriverAttributesAre ("0000000", Application.Driver, attributes);
+        TestHelpers.AssertDriverAttributesAre ("0000000", output, Application.Driver, attributes);
 
         // Cursor is at the end
         Assert.Equal (32, _textField.CursorPosition);
@@ -1085,7 +1085,7 @@ public class TextFieldTests (ITestOutputHelper output)
         Assert.Equal (4, _textField.CursorPosition);
 
         //                                             TAB to jump between text fields.
-        TestHelpers.AssertDriverAttributesAre ("1111000", Application.Driver, attributes);
+        TestHelpers.AssertDriverAttributesAre ("1111000", output, Application.Driver, attributes);
         top.Dispose ();
     }
 

+ 6 - 6
UnitTests/Views/TextViewTests.cs

@@ -6359,7 +6359,7 @@ This is the second line.
         };
 
         //                                             TAB to jump between text fields.
-        TestHelpers.AssertDriverAttributesAre ("0000000", Application.Driver, attributes);
+        TestHelpers.AssertDriverAttributesAre ("0000000", _output, Application.Driver, attributes);
         Assert.Empty (_textView.SelectedCellsList);
 
         _textView.NewKeyDownEvent (Key.CursorRight.WithCtrl.WithShift);
@@ -6368,7 +6368,7 @@ This is the second line.
         Assert.Equal (new Point (4, 0), _textView.CursorPosition);
 
         //                                             TAB to jump between text fields.
-        TestHelpers.AssertDriverAttributesAre ("1111000", Application.Driver, attributes);
+        TestHelpers.AssertDriverAttributesAre ("1111000", _output, Application.Driver, attributes);
         Assert.Equal ("TAB ", Cell.ToString (_textView.SelectedCellsList [^1]));
         top.Dispose ();
     }
@@ -8993,12 +8993,12 @@ Error   ";
 2222225555
 3333555555
 4444455555";
-        TestHelpers.AssertDriverAttributesAre (expectedColor, Application.Driver, attributes);
+        TestHelpers.AssertDriverAttributesAre (expectedColor, _output, Application.Driver, attributes);
 
         tv.WordWrap = true;
         Application.Refresh ();
         TestHelpers.AssertDriverContentsWithFrameAre (expectedText, _output);
-        TestHelpers.AssertDriverAttributesAre (expectedColor, Application.Driver, attributes);
+        TestHelpers.AssertDriverAttributesAre (expectedColor, _output, Application.Driver, attributes);
 
         tv.CursorPosition = new (6, 2);
         tv.SelectionStartColumn = 0;
@@ -9028,7 +9028,7 @@ Dialogror ";
 4400000000
 1111555555
 2222224445";
-        TestHelpers.AssertDriverAttributesAre (expectedColor, Application.Driver, attributes);
+        TestHelpers.AssertDriverAttributesAre (expectedColor, _output, Application.Driver, attributes);
 
         tv.Undo ();
         tv.CursorPosition = new (0, 3);
@@ -9065,7 +9065,7 @@ ror       ";
 1111555555
 2222225555
 4445555555";
-        TestHelpers.AssertDriverAttributesAre (expectedColor, Application.Driver, attributes);
+        TestHelpers.AssertDriverAttributesAre (expectedColor, _output, Application.Driver, attributes);
 
         Application.End (rs);
         top.Dispose ();

+ 2 - 0
UnitTests/Views/TreeViewTests.cs

@@ -1229,6 +1229,7 @@ oot two
 0000000000
 0000000000
 ",
+                                               _output,
                                                Application.Driver,
                                                tv.ColorScheme.Normal,
                                                pink
@@ -1265,6 +1266,7 @@ oot two
 0000000000
 001111
 ",
+                                               _output,
                                                Application.Driver,
                                                tv.ColorScheme.Normal,
                                                pink