Cleans up/Refactors View.Subviews (#3962)

* Subview clean up

* New Add/Remove event pattern

* Using Logging

* cleanup

* Subview -> SubView

* Test code cleanup. Killed many warnings.

* Fix tznind feedback

* Refactored AllViewTest helpers

* Moved keyboard tests to parallel

* Moved mouse tests to parallel

* Moved view tests to parallel

* Test code cleanup. Killed many warnings.

* dupe test

* Some mouse tests can't run in parallel because MouseGrabView

* Made SpinnerView more testable

* Moved more tests

* SubViews to IReadOnlyCollection<View>

* SubViews to IReadOnlyCollection<View> 2

* scrollbar tests

* shortcut tests

* Use InternalSubViews vs. _subviews

* Nuked View.IsAdded.
Added View.SuperViewChanged.

* API doc updats

* Unit Test tweak

* Unit Test tweak
This commit is contained in:
Tig
2025-03-08 15:42:17 -07:00
committed by GitHub
parent 85cf6619ed
commit acb5979e6c
226 changed files with 7235 additions and 7188 deletions

View File

@@ -1,10 +1,9 @@
using UnitTests;
using UnitTests;
using Xunit.Abstractions;
namespace Terminal.Gui.LayoutTests;
public class AllViewsDrawTests (ITestOutputHelper _output) : TestsAllViews
public class AllViewsDrawTests (ITestOutputHelper output) : TestsAllViews
{
[Theory]
[SetupFakeDriver] // Required for spinner view that wants to register timeouts
@@ -19,12 +18,12 @@ public class AllViewsDrawTests (ITestOutputHelper _output) : TestsAllViews
if (view == null)
{
_output.WriteLine ($"Ignoring {viewType} - It's a Generic");
output.WriteLine ($"Ignoring {viewType} - It's a Generic");
return;
}
_output.WriteLine ($"Testing {viewType}");
output.WriteLine ($"Testing {viewType}");
if (view is IDesignable designable)
{
@@ -35,10 +34,10 @@ public class AllViewsDrawTests (ITestOutputHelper _output) : TestsAllViews
view.DrawComplete += (s, e) => drawCompleteCount++;
var layoutStartedCount = 0;
view.SubviewLayout += (s, e) => layoutStartedCount++;
view.SubViewLayout += (s, e) => layoutStartedCount++;
var layoutCompleteCount = 0;
view.SubviewsLaidOut += (s, e) => layoutCompleteCount++;
view.SubViewsLaidOut += (s, e) => layoutCompleteCount++;
view.SetNeedsLayout ();
view.Layout ();

View File

@@ -1,38 +1,36 @@
#nullable enable
using Moq;
using UnitTests;
using UnitTests;
using Xunit.Abstractions;
namespace Terminal.Gui.ViewTests;
[Trait ("Category", "Output")]
public class ClearViewportTests (ITestOutputHelper _output)
public class ClearViewportTests (ITestOutputHelper output)
{
public class TestableView : View
{
public bool TestOnClearingViewport () { return OnClearingViewport (); }
public int OnClearingViewportCalled { get; set; } = 0;
public bool CancelOnClearingViewport { get; set; }
public int OnClearingViewportCalled { get; set; }
public bool CancelOnClearingViewport { get; set; }
protected override bool OnClearingViewport ()
{
OnClearingViewportCalled++;
return CancelOnClearingViewport;
}
public int OnClearedViewportCalled { get; set; } = 0;
protected override void OnClearedViewport ()
{
OnClearedViewportCalled++;
}
public int OnClearedViewportCalled { get; set; }
protected override void OnClearedViewport () { OnClearedViewportCalled++; }
}
[Fact]
public void DoClearViewport_ViewportIsTransparent_DoesNotClear ()
{
// Arrange
Mock<TestableView> view = new Mock<TestableView> { CallBase = true };
Mock<TestableView> view = new () { CallBase = true };
view.Object.ViewportSettings = ViewportSettings.Transparent;
// Act
@@ -47,7 +45,7 @@ public class ClearViewportTests (ITestOutputHelper _output)
public void DoClearViewport_OnClearingViewportReturnsTrue_DoesNotClear ()
{
// Arrange
Mock<TestableView> view = new Mock<TestableView> { CallBase = true };
Mock<TestableView> view = new () { CallBase = true };
view.Object.CancelOnClearingViewport = true;
// Act
@@ -61,7 +59,7 @@ public class ClearViewportTests (ITestOutputHelper _output)
public void DoClearViewport_ClearingViewportEventCancelled_DoesNotClear ()
{
// Arrange
Mock<TestableView> view = new Mock<TestableView> { CallBase = true };
Mock<TestableView> view = new () { CallBase = true };
view.Object.ClearingViewport += (sender, e) => e.Cancel = true;
// Act
@@ -75,7 +73,7 @@ public class ClearViewportTests (ITestOutputHelper _output)
public void DoClearViewport_ClearsViewport ()
{
// Arrange
Mock<TestableView> view = new Mock<TestableView> { CallBase = true };
Mock<TestableView> view = new () { CallBase = true };
// Act
view.Object.DoClearViewport ();
@@ -88,7 +86,7 @@ public class ClearViewportTests (ITestOutputHelper _output)
public void DoClearViewport_RaisesClearingViewportEvent ()
{
// Arrange
Mock<TestableView> view = new Mock<TestableView> { CallBase = true };
Mock<TestableView> view = new () { CallBase = true };
var eventRaised = false;
view.Object.ClearingViewport += (sender, e) => eventRaised = true;
@@ -115,37 +113,37 @@ public class ClearViewportTests (ITestOutputHelper _output)
superView.Add (view);
superView.BeginInit ();
superView.EndInit ();
superView.LayoutSubviews ();
superView.LayoutSubViews ();
superView.Draw ();
DriverAssert.AssertDriverContentsWithFrameAre (
@"
@"
┌─┐
│X│
└─┘",
_output);
output);
// On Draw exit the view is excluded from the clip, so this will do nothing.
view.ClearViewport ();
DriverAssert.AssertDriverContentsWithFrameAre (
@"
@"
┌─┐
│X│
└─┘",
_output);
output);
View.SetClipToScreen ();
view.ClearViewport ();
DriverAssert.AssertDriverContentsWithFrameAre (
@"
@"
┌─┐
│ │
└─┘",
_output);
output);
}
[Fact]
@@ -165,25 +163,25 @@ public class ClearViewportTests (ITestOutputHelper _output)
superView.Add (view);
superView.BeginInit ();
superView.EndInit ();
superView.LayoutSubviews ();
superView.LayoutSubViews ();
superView.Draw ();
DriverAssert.AssertDriverContentsWithFrameAre (
@"
@"
┌─┐
│X│
└─┘",
_output);
output);
View.SetClipToScreen ();
view.ClearViewport ();
DriverAssert.AssertDriverContentsWithFrameAre (
@"
@"
┌─┐
│ │
└─┘",
_output);
output);
}
[Fact]
@@ -194,7 +192,7 @@ public class ClearViewportTests (ITestOutputHelper _output)
view.DrawingContent += (s, e) =>
{
Region savedClip = view.AddViewportToClip ();
Region? savedClip = view.AddViewportToClip ();
for (var row = 0; row < view.Viewport.Height; row++)
{
@@ -228,7 +226,7 @@ public class ClearViewportTests (ITestOutputHelper _output)
"
;
Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, _output);
Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
Assert.Equal (new (0, 0, 20, 10), pos);
view.FillRect (view.Viewport);
@@ -247,7 +245,7 @@ public class ClearViewportTests (ITestOutputHelper _output)
"
;
pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, _output);
pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
top.Dispose ();
}
@@ -259,7 +257,7 @@ public class ClearViewportTests (ITestOutputHelper _output)
view.DrawingContent += (s, e) =>
{
Region savedClip = view.AddViewportToClip ();
Region? savedClip = view.AddViewportToClip ();
for (var row = 0; row < view.Viewport.Height; row++)
{
@@ -293,7 +291,7 @@ public class ClearViewportTests (ITestOutputHelper _output)
"
;
Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, _output);
Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
Assert.Equal (new (0, 0, 20, 10), pos);
view.FillRect (view.Viewport);
@@ -311,7 +309,7 @@ public class ClearViewportTests (ITestOutputHelper _output)
└──────────────────┘
";
pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, _output);
pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
top.Dispose ();
}
@@ -353,39 +351,39 @@ public class ClearViewportTests (ITestOutputHelper _output)
}
DriverAssert.AssertDriverContentsWithFrameAre (
@"
@"
cccccccccccccccccccc",
_output
);
output
);
Attribute [] attributes =
{
Colors.ColorSchemes ["TopLevel"].Normal,
Colors.ColorSchemes ["Base"].Normal,
Colors.ColorSchemes ["Base"].Focus
Colors.ColorSchemes ["TopLevel"]!.Normal,
Colors.ColorSchemes ["Base"]!.Normal,
Colors.ColorSchemes ["Base"]!.Focus
};
if (label)
{
DriverAssert.AssertDriverAttributesAre (
@"
@"
111111111111111111110
111111111111111111110",
_output,
Application.Driver,
attributes
);
output,
Application.Driver,
attributes
);
}
else
{
DriverAssert.AssertDriverAttributesAre (
@"
@"
222222222222222222220
111111111111111111110",
_output,
Application.Driver,
attributes
);
output,
Application.Driver,
attributes
);
}
if (label)
@@ -398,13 +396,13 @@ cccccccccccccccccccc",
Application.LayoutAndDraw ();
DriverAssert.AssertDriverAttributesAre (
@"
@"
222222222222222222220
111111111111111111110",
_output,
Application.Driver,
attributes
);
output,
Application.Driver,
attributes
);
}
Application.End (runState);

View File

@@ -79,7 +79,7 @@ public class ClipTests (ITestOutputHelper _output)
superView.Add (view);
superView.BeginInit ();
superView.EndInit ();
superView.LayoutSubviews ();
superView.LayoutSubViews ();
superView.Draw ();

View File

@@ -6,7 +6,7 @@ using Xunit.Abstractions;
namespace Terminal.Gui.ViewTests;
[Trait ("Category", "Output")]
public class DrawTests (ITestOutputHelper _output)
public class DrawTests (ITestOutputHelper output)
{
[Fact]
@@ -41,9 +41,9 @@ public class DrawTests (ITestOutputHelper _output)
""";
DriverAssert.AssertDriverContentsWithFrameAre (expectedOutput, _output);
DriverAssert.AssertDriverContentsWithFrameAre (expectedOutput, output);
DriverAssert.AssertDriverContentsAre (expectedOutput, _output);
DriverAssert.AssertDriverContentsAre (expectedOutput, output);
// This test has nothing to do with color - removing as it is not relevant and fragile
top.Dispose ();
@@ -91,7 +91,7 @@ public class DrawTests (ITestOutputHelper _output)
s
t
""",
_output
output
);
DriverAssert.AssertDriverAttributesAre (
@@ -105,7 +105,7 @@ public class DrawTests (ITestOutputHelper _output)
0
0
""",
_output,
output,
Application.Driver,
Colors.ColorSchemes ["Base"]!.Normal
);
@@ -133,7 +133,7 @@ public class DrawTests (ITestOutputHelper _output)
""",
_output
output
);
}
@@ -152,7 +152,7 @@ public class DrawTests (ITestOutputHelper _output)
view.Draw ();
DriverAssert.AssertDriverContentsWithFrameAre ("──", _output);
DriverAssert.AssertDriverContentsWithFrameAre ("──", output);
}
[Fact]
@@ -176,7 +176,7 @@ public class DrawTests (ITestOutputHelper _output)
""",
_output
output
);
}
@@ -201,7 +201,7 @@ public class DrawTests (ITestOutputHelper _output)
""",
_output
output
);
}
@@ -223,7 +223,7 @@ public class DrawTests (ITestOutputHelper _output)
DriverAssert.AssertDriverContentsWithFrameAre (
"││",
_output
output
);
}
@@ -300,7 +300,7 @@ public class DrawTests (ITestOutputHelper _output)
3V
4i
""",
_output
output
);
content.X = -1;
@@ -315,12 +315,12 @@ public class DrawTests (ITestOutputHelper _output)
V
i
""",
_output
output
);
content.X = -2;
Application.LayoutAndDraw ();
DriverAssert.AssertDriverContentsWithFrameAre (@"", _output);
DriverAssert.AssertDriverContentsWithFrameAre (@"", output);
content.X = 0;
content.Y = -1;
@@ -335,7 +335,7 @@ public class DrawTests (ITestOutputHelper _output)
4i
5e
""",
_output
output
);
content.Y = -6;
@@ -350,7 +350,7 @@ public class DrawTests (ITestOutputHelper _output)
9
0
""",
_output
output
);
content.Y = -19;
@@ -361,17 +361,17 @@ public class DrawTests (ITestOutputHelper _output)
9
""",
_output
output
);
content.Y = -20;
Application.LayoutAndDraw ();
DriverAssert.AssertDriverContentsWithFrameAre ("", _output);
DriverAssert.AssertDriverContentsWithFrameAre ("", output);
content.X = -2;
content.Y = 0;
Application.LayoutAndDraw ();
DriverAssert.AssertDriverContentsWithFrameAre ("", _output);
DriverAssert.AssertDriverContentsWithFrameAre ("", output);
top.Dispose ();
}
@@ -407,7 +407,7 @@ public class DrawTests (ITestOutputHelper _output)
// BUGBUG: v2 - it's bogus to reference .Frame before BeginInit. And why is the clip being set anyway???
top.SubviewsLaidOut += Top_LayoutComplete;
top.SubViewsLaidOut += Top_LayoutComplete;
Application.Begin (top);
Application.LayoutAndDraw ();
@@ -417,7 +417,7 @@ public class DrawTests (ITestOutputHelper _output)
01234
subVi
""",
_output
output
);
content.X = -1;
@@ -429,7 +429,7 @@ public class DrawTests (ITestOutputHelper _output)
12345
ubVie
""",
_output
output
);
content.Y = -1;
@@ -440,17 +440,17 @@ public class DrawTests (ITestOutputHelper _output)
ubVie
""",
_output
output
);
content.Y = -2;
Application.LayoutAndDraw ();
DriverAssert.AssertDriverContentsWithFrameAre ("", _output);
DriverAssert.AssertDriverContentsWithFrameAre ("", output);
content.X = -20;
content.Y = 0;
Application.LayoutAndDraw ();
DriverAssert.AssertDriverContentsWithFrameAre ("", _output);
DriverAssert.AssertDriverContentsWithFrameAre ("", output);
top.Dispose ();
return;
@@ -507,7 +507,7 @@ public class DrawTests (ITestOutputHelper _output)
3V
4i
""",
_output
output
);
content.X = -1;
@@ -522,12 +522,12 @@ public class DrawTests (ITestOutputHelper _output)
V
i
""",
_output
output
);
content.X = -2;
Application.LayoutAndDraw ();
DriverAssert.AssertDriverContentsWithFrameAre (@"", _output);
DriverAssert.AssertDriverContentsWithFrameAre (@"", output);
content.X = 0;
content.Y = -1;
@@ -542,7 +542,7 @@ public class DrawTests (ITestOutputHelper _output)
4i
5e
""",
_output
output
);
content.Y = -6;
@@ -557,7 +557,7 @@ public class DrawTests (ITestOutputHelper _output)
9
0
""",
_output
output
);
content.Y = -19;
@@ -568,17 +568,17 @@ public class DrawTests (ITestOutputHelper _output)
9
""",
_output
output
);
content.Y = -20;
Application.LayoutAndDraw ();
DriverAssert.AssertDriverContentsWithFrameAre ("", _output);
DriverAssert.AssertDriverContentsWithFrameAre ("", output);
content.X = -2;
content.Y = 0;
Application.LayoutAndDraw ();
DriverAssert.AssertDriverContentsWithFrameAre ("", _output);
DriverAssert.AssertDriverContentsWithFrameAre ("", output);
top.Dispose ();
}
@@ -591,7 +591,7 @@ public class DrawTests (ITestOutputHelper _output)
var view = new View { Width = 10, Height = 1 };
view.DrawHotString (expected, Attribute.Default, Attribute.Default);
DriverAssert.AssertDriverContentsWithFrameAre (expected, _output);
DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
}
// TODO: The tests below that use Label should use View instead.
@@ -626,9 +626,9 @@ public class DrawTests (ITestOutputHelper _output)
𝔹
""";
DriverAssert.AssertDriverContentsWithFrameAre (expected, _output);
DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
DriverAssert.AssertDriverContentsAre (expected, _output);
DriverAssert.AssertDriverContentsAre (expected, output);
top.Dispose ();
// This test has nothing to do with color - removing as it is not relevant and fragile
@@ -695,7 +695,7 @@ At 0,0
A text with some long width
and also with two lines. "
,
_output
output
);
view.Frame = new (3, 3, 10, 1);
@@ -711,7 +711,7 @@ At 0,0
A text wit",
_output
output
);
Application.End (runState);
top.Dispose ();
@@ -744,7 +744,7 @@ At 0,0
A text with some long width
and also with two lines. "
,
_output
output
);
view.X = 3;
@@ -764,7 +764,7 @@ At 0,0
A text wit"
,
_output
output
);
Application.End (runState);
top.Dispose ();
@@ -796,7 +796,7 @@ At 0,0
A text with some long width
and also with two lines. "
,
_output
output
);
view.Frame = new (1, 1, 10, 1);
@@ -810,7 +810,7 @@ At 0,0
At 0,0
A text wit"
,
_output
output
);
Application.End (runState);
top.Dispose ();
@@ -843,7 +843,7 @@ At 0,0
A text with some long width
and also with two lines. "
,
_output
output
);
view.X = 1;
@@ -862,7 +862,7 @@ At 0,0
At 0,0
A text wit"
,
_output
output
);
Application.End (runState);
top.Dispose ();
@@ -873,7 +873,7 @@ At 0,0
public bool IsKeyDown { get; set; }
public bool IsKeyPress { get; set; }
public bool IsKeyUp { get; set; }
public override string Text { get; set; }
public override string Text { get; set; } = null!;
protected override bool OnDrawingContent ()
{

View File

@@ -39,13 +39,13 @@ public class NeedsDrawTests ()
RunState runState = Application.Begin (top);
top.SubviewsLaidOut += (s, e) => { Assert.Equal (new (0, 0, 80, 25), top._needsDrawRect); };
top.SubViewsLaidOut += (s, e) => { Assert.Equal (new (0, 0, 80, 25), top._needsDrawRect); };
frame.SubviewsLaidOut += (s, e) => { Assert.Equal (new (0, 0, 40, 8), frame._needsDrawRect); };
frame.SubViewsLaidOut += (s, e) => { Assert.Equal (new (0, 0, 40, 8), frame._needsDrawRect); };
label.SubviewsLaidOut += (s, e) => { Assert.Equal (new (0, 0, 38, 1), label._needsDrawRect); };
label.SubViewsLaidOut += (s, e) => { Assert.Equal (new (0, 0, 38, 1), label._needsDrawRect); };
view.SubviewsLaidOut += (s, e) => { Assert.Equal (new (0, 0, 13, 1), view._needsDrawRect); };
view.SubViewsLaidOut += (s, e) => { Assert.Equal (new (0, 0, 13, 1), view._needsDrawRect); };
Assert.Equal (new (0, 0, 80, 25), top.Frame);
Assert.Equal (new (20, 8, 40, 8), frame.Frame);

View File

@@ -1,13 +1,11 @@
#nullable enable
using System.Text;
using UnitTests;
using UnitTests;
using Xunit.Abstractions;
namespace Terminal.Gui.ViewTests;
[Trait ("Category", "Output")]
public class TransparentTests (ITestOutputHelper _output)
public class TransparentTests (ITestOutputHelper output)
{
[Fact]
[SetupFakeDriver]
@@ -50,13 +48,13 @@ public class TransparentTests (ITestOutputHelper _output)
░┌─────────────┐░░░░
░│Sub░░░░░░░░░░│░░░░
░└─────────────┘░░░░
░░░░░░░░░░░░░░░░░░░░", _output);
░░░░░░░░░░░░░░░░░░░░", output);
}
[Fact]
[SetupFakeDriver]
public void Transparent_Subview_Occludes ()
public void Transparent_SubView_Occludes ()
{
var super = new View
{
@@ -104,6 +102,6 @@ public class TransparentTests (ITestOutputHelper _output)
░┌─────────────┐░░░░
░│░░░subSub░░░░│░░░░
░└─────────────┘░░░░
░░░░░░░░░░░░░░░░░░░░", _output);
░░░░░░░░░░░░░░░░░░░░", output);
}
}