mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
* touching publish.yml
* Fixed UICatalog bugs. Added fluent tests.
* marked v1 menu stuff as obsolte
* Tweaks.
Added View.GetSubMenus<type>().
* fixed unit tests
* general messing around
* general messing around
* Playing with Fluent
* ColorScheme tweaks
* WIP: ColorScheme tweaks
* Playing with Fluent
* Merged from laptop2
* Hacky-ish fixes to:
- #4016
- #4014
* Fixed Region bug preventing menus without borders from working
* Tweaks
* Fixed a bunch of CM issues
* Fixed OoptionSelector
* ip
* FixedCM issues
* Fixed CM issues2
* Revert "FixedCM issues"
This reverts commit dd6c6a70a3.
* Reverted stuff
* Found and fixed bug in AllViews_Center_Properly
* Fixed CM issues2
* removed menuv2 onapplied.
Changed how UICatalog Applys CM
* changed test time out to see if it helkps with ubuntu fails
* reset app on fail?
* back to 1500ms
* Made StatusBar nullable.
* Code Cleanup.
* HexEditor Code Cleanup.
* HexEditor Code Cleanup.
* Back to 3000ms. Sigh.
* Trying different logic
* Trying different logic2
* Fixed potential crash in runlop
* Fixed potential crash in runlop2
* Tweaked Spinner stuff
* Removed TabView from TextEffects scenario. Not needed and possible culprit.
* back to 2000ms
* WIP: Revamping menu scenarios
* Menu Scenario refinements.
Fixed a few bugs.
Code cleanup.
* fixed unit test
* Fixed warnings
* Fixed warnings2
* Fixed File.Exit
* WIP: Dealing with QuitKey struggles
* WIP: Dealing with QuitKey struggles 2
* WIP: Dealing with QuitKey struggles 3
* Fixed ListView collection nav bug
* Fixed a bunch of menu stuff.
Fixed Appv2 stuff.
* Lots of refactoring and fixing
* Lots of unit test issues
* Fixed DebugIDisposable issues
* Fixed release build issue
* Fixed release build issue 2
* DebugIDisposable -> EnableDebugIDisposableAsserts and more
* DebugIDisposable -> EnableDebugIDisposableAsserts and more 2
* Fixed Menus scenario - context menu
* Added @bdisp suggested assert. Commented it out as it breaks tests.
* Code cleanup
* Fixed disposed but
* Fixed UICatalog exit
* Fixed Unit test I broke.
Added 'Minimal' Theme that turns off all borders etc...
This commit is contained in:
@@ -783,7 +783,7 @@ public class RegionTests
|
||||
Assert.True (region1.Contains (40, 40));
|
||||
}
|
||||
|
||||
[Fact (Skip = "Union is broken")]
|
||||
[Fact]
|
||||
public void Union_Third_Rect_Covering_Two_Disjoint_Merges ()
|
||||
{
|
||||
var origRegion = new Region ();
|
||||
@@ -791,19 +791,19 @@ public class RegionTests
|
||||
var region1 = new Region (new (0, 0, 1, 1));
|
||||
var region2 = new Region (new (1, 0, 1, 1));
|
||||
|
||||
origRegion.Union(region1);
|
||||
origRegion.Union(region2);
|
||||
origRegion.Union (region1);
|
||||
origRegion.Union (region2);
|
||||
|
||||
Assert.Equal (new Rectangle (0, 0, 2, 1), origRegion.GetBounds ());
|
||||
Assert.Equal (2, origRegion.GetRectangles ().Length);
|
||||
|
||||
origRegion.Union(new Region(new (0, 0, 4, 1)));
|
||||
origRegion.Union (new Region (new (0, 0, 4, 1)));
|
||||
|
||||
Assert.Equal (new Rectangle (0, 1, 4, 1), origRegion.GetBounds ());
|
||||
Assert.Single (origRegion.GetRectangles ());
|
||||
Assert.Equal (new Rectangle (0, 0, 4, 1), origRegion.GetBounds ());
|
||||
Assert.Equal (3, origRegion.GetRectangles ().Length);
|
||||
}
|
||||
|
||||
[Fact (Skip = "MinimalUnion is broken")]
|
||||
[Fact]
|
||||
public void MinimalUnion_Third_Rect_Covering_Two_Disjoint_Merges ()
|
||||
{
|
||||
var origRegion = new Region ();
|
||||
@@ -819,7 +819,7 @@ public class RegionTests
|
||||
|
||||
origRegion.MinimalUnion (new Region (new (0, 0, 4, 1)));
|
||||
|
||||
Assert.Equal (new Rectangle (0, 1, 4, 1), origRegion.GetBounds ());
|
||||
Assert.Equal (new Rectangle (0, 0, 4, 1), origRegion.GetBounds ());
|
||||
Assert.Single (origRegion.GetRectangles ());
|
||||
}
|
||||
|
||||
@@ -928,6 +928,180 @@ public class RegionTests
|
||||
Assert.Contains (new (2, 0, 0, 1), result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MergeRectangles_Sort_Handles_Coincident_Events_Without_Crashing ()
|
||||
{
|
||||
// Arrange: Create rectangles designed to produce coincident start/end events
|
||||
// Rect1 ends at x=10. Rect2 and Rect3 start at x=10.
|
||||
// Rect4 ends at x=15. Rect5 starts at x=15.
|
||||
var rect1 = new Rectangle (0, 0, 10, 10); // Ends at x=10
|
||||
var rect2 = new Rectangle (10, 0, 10, 5); // Starts at x=10
|
||||
var rect3 = new Rectangle (10, 5, 10, 5); // Starts at x=10, adjacent to rect2 vertically
|
||||
var rect4 = new Rectangle (5, 10, 10, 5); // Ends at x=15
|
||||
var rect5 = new Rectangle (15, 10, 5, 5); // Starts at x=15
|
||||
|
||||
var combinedList = new List<Rectangle> { rect1, rect2, rect3, rect4, rect5 };
|
||||
|
||||
// Act & Assert:
|
||||
// The core assertion is that calling MergeRectangles with this list
|
||||
// does *not* throw the ArgumentException related to sorting.
|
||||
var exception = Record.Exception (() => Region.MergeRectangles (combinedList, false));
|
||||
|
||||
// Assert
|
||||
Assert.Null (exception);
|
||||
|
||||
// Optional secondary assertion: Check if the merge produced a reasonable number of rectangles
|
||||
// This isn't strictly necessary for proving the sort fix, but can be useful.
|
||||
// var merged = Region.MergeRectangles(combinedList, false);
|
||||
// Assert.True(merged.Count > 0 && merged.Count <= combinedList.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MergeRectangles_Sort_Handles_Multiple_Coincident_Starts ()
|
||||
{
|
||||
// Arrange: Multiple rectangles starting at the same X
|
||||
var rect1 = new Rectangle (5, 0, 10, 5);
|
||||
var rect2 = new Rectangle (5, 5, 10, 5);
|
||||
var rect3 = new Rectangle (5, 10, 10, 5);
|
||||
var combinedList = new List<Rectangle> { rect1, rect2, rect3 };
|
||||
|
||||
// Act & Assert: Ensure no sorting exception
|
||||
var exception = Record.Exception (() => Region.MergeRectangles (combinedList, false));
|
||||
Assert.Null (exception);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MergeRectangles_Sort_Handles_Multiple_Coincident_Ends ()
|
||||
{
|
||||
// Arrange: Multiple rectangles ending at the same X
|
||||
var rect1 = new Rectangle (0, 0, 10, 5);
|
||||
var rect2 = new Rectangle (0, 5, 10, 5);
|
||||
var rect3 = new Rectangle (0, 10, 10, 5);
|
||||
var combinedList = new List<Rectangle> { rect1, rect2, rect3 };
|
||||
|
||||
// Act & Assert: Ensure no sorting exception
|
||||
var exception = Record.Exception (() => Region.MergeRectangles (combinedList, false));
|
||||
Assert.Null (exception);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MergeRectangles_Sort_Handles_Coincident_Mixed_Events_Without_Crashing ()
|
||||
{
|
||||
// Arrange: Create rectangles specifically designed to produce multiple
|
||||
// Start AND End events at the same x-coordinate (e.g., x=10),
|
||||
// mimicking the pattern observed in the crash log.
|
||||
var rectA = new Rectangle (0, 0, 10, 5); // Ends at x=10, y=[0, 5)
|
||||
var rectB = new Rectangle (0, 10, 10, 5); // Ends at x=10, y=[10, 15)
|
||||
var rectC = new Rectangle (10, 0, 10, 5); // Starts at x=10, y=[0, 5)
|
||||
var rectD = new Rectangle (10, 10, 10, 5); // Starts at x=10, y=[10, 15)
|
||||
|
||||
// Add another set at a different X to increase complexity
|
||||
var rectE = new Rectangle (5, 20, 10, 5); // Ends at x=15, y=[20, 25)
|
||||
var rectF = new Rectangle (5, 30, 10, 5); // Ends at x=15, y=[30, 35)
|
||||
var rectG = new Rectangle (15, 20, 10, 5); // Starts at x=15, y=[20, 25)
|
||||
var rectH = new Rectangle (15, 30, 10, 5); // Starts at x=15, y=[30, 35)
|
||||
|
||||
// Add some unrelated rectangles
|
||||
var rectI = new Rectangle (0, 40, 5, 5);
|
||||
var rectJ = new Rectangle (100, 100, 5, 5);
|
||||
|
||||
|
||||
var combinedList = new List<Rectangle> {
|
||||
rectA, rectB, rectC, rectD,
|
||||
rectE, rectF, rectG, rectH,
|
||||
rectI, rectJ
|
||||
};
|
||||
|
||||
// Act & Assert:
|
||||
// Call MergeRectangles with the current code.
|
||||
// This test *should* fail by throwing ArgumentException due to unstable sort.
|
||||
var exception = Record.Exception (() => Region.MergeRectangles (combinedList, false));
|
||||
|
||||
// Assert that no exception was thrown (this assertion will fail with the current code)
|
||||
Assert.Null (exception);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MergeRectangles_Sort_Reproduces_UICatalog_Crash_Pattern_Directly ()
|
||||
{
|
||||
// Arrange: Rectangles derived *directly* from the events list that caused the crash at x=67
|
||||
// This aims to replicate the exact problematic pattern.
|
||||
var rect_End_67_7_30 = new Rectangle (60, 7, 7, 23); // Ends at x=67, y=[7, 30) -> Event [33]
|
||||
var rect_Start_67_2_30 = new Rectangle (67, 2, 10, 28); // Starts at x=67, y=[2, 30) -> Event [34]
|
||||
var rect_Start_67_1_1 = new Rectangle (67, 1, 10, 0); // Starts at x=67, y=[1, 1) -> Event [49] (Height 0)
|
||||
var rect_End_67_1_1 = new Rectangle (60, 1, 7, 0); // Ends at x=67, y=[1, 1) -> Event [64] (Height 0)
|
||||
|
||||
// Add rectangles for x=94/95 pattern
|
||||
var rect_End_94_1_30 = new Rectangle (90, 1, 4, 29); // Ends at x=94, y=[1, 30) -> Event [55]
|
||||
var rect_Start_94_1_1 = new Rectangle (94, 1, 10, 0); // Starts at x=94, y=[1, 1) -> Event [56]
|
||||
var rect_Start_94_7_30 = new Rectangle (94, 7, 10, 23); // Starts at x=94, y=[7, 30) -> Event [58]
|
||||
|
||||
var rect_End_95_1_1 = new Rectangle (90, 1, 5, 0); // Ends at x=95, y=[1, 1) -> Event [57]
|
||||
var rect_End_95_7_30 = new Rectangle (90, 7, 5, 23); // Ends at x=95, y=[7, 30) -> Event [59]
|
||||
var rect_Start_95_0_30 = new Rectangle (95, 0, 10, 30); // Starts at x=95, y=[0, 30) -> Event [60]
|
||||
|
||||
|
||||
var combinedList = new List<Rectangle> {
|
||||
rect_End_67_7_30, rect_Start_67_2_30, rect_Start_67_1_1, rect_End_67_1_1,
|
||||
rect_End_94_1_30, rect_Start_94_1_1, rect_Start_94_7_30,
|
||||
rect_End_95_1_1, rect_End_95_7_30, rect_Start_95_0_30
|
||||
};
|
||||
|
||||
// Act & Assert:
|
||||
// Call MergeRectangles. This test is specifically designed to fail with the current code.
|
||||
var exception = Record.Exception (() => Region.MergeRectangles (combinedList, false));
|
||||
|
||||
// Assert that no exception was thrown (this assertion *should* fail with the current code)
|
||||
Assert.Null (exception);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MergeRectangles_Sort_Reproduces_UICatalog_Crash_From_Captured_Data ()
|
||||
{
|
||||
// Arrange: The exact list of rectangles captured during the UICatalog crash
|
||||
var rectanglesFromCrash = new List<Rectangle> {
|
||||
new Rectangle(38, 7, 1, 11),
|
||||
new Rectangle(39, 7, 5, 23),
|
||||
new Rectangle(44, 7, 1, 23),
|
||||
new Rectangle(45, 7, 6, 23),
|
||||
new Rectangle(51, 7, 1, 23),
|
||||
new Rectangle(52, 7, 1, 23),
|
||||
new Rectangle(53, 7, 1, 23),
|
||||
new Rectangle(54, 7, 1, 23),
|
||||
new Rectangle(55, 7, 1, 23),
|
||||
new Rectangle(56, 7, 1, 23),
|
||||
new Rectangle(57, 7, 1, 23),
|
||||
new Rectangle(58, 7, 1, 23),
|
||||
new Rectangle(59, 7, 1, 23),
|
||||
new Rectangle(60, 7, 1, 23),
|
||||
new Rectangle(61, 7, 3, 23),
|
||||
new Rectangle(64, 7, 1, 23),
|
||||
new Rectangle(65, 7, 2, 23),
|
||||
new Rectangle(67, 2, 2, 28),
|
||||
new Rectangle(69, 2, 3, 28),
|
||||
new Rectangle(72, 2, 3, 28),
|
||||
new Rectangle(75, 2, 1, 28),
|
||||
new Rectangle(76, 2, 2, 28),
|
||||
new Rectangle(78, 2, 2, 28),
|
||||
new Rectangle(80, 7, 1, 23),
|
||||
new Rectangle(81, 1, 7, 29),
|
||||
new Rectangle(88, 1, 1, 29),
|
||||
new Rectangle(89, 1, 2, 29),
|
||||
new Rectangle(91, 1, 3, 29),
|
||||
new Rectangle(94, 1, 1, 0), // Note: Zero height
|
||||
new Rectangle(94, 7, 1, 23),
|
||||
new Rectangle(95, 0, 1, 30),
|
||||
new Rectangle(96, 0, 23, 30),
|
||||
new Rectangle(67, 1, 0, 0) // Note: Zero width and height
|
||||
};
|
||||
|
||||
// Act & Assert:
|
||||
// Call MergeRectangles with the current code.
|
||||
// This test *should* fail by throwing ArgumentException due to unstable sort.
|
||||
var exception = Record.Exception (() => Region.MergeRectangles (rectanglesFromCrash, false));
|
||||
|
||||
// Assert that no exception was thrown (this assertion will fail with the current code)
|
||||
Assert.Null (exception);
|
||||
}
|
||||
|
||||
}
|
||||
11
Tests/UnitTestsParallelizable/ParallelizableBase.cs
Normal file
11
Tests/UnitTestsParallelizable/ParallelizableBase.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace UnitTests.Parallelizable;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for parallelizable tests. Ensures that tests can run in parallel without interference
|
||||
/// by setting various Terminal.Gui static properties to their default values. E.g. View.EnableDebugIDisposableAsserts.
|
||||
/// </summary>
|
||||
[Collection ("Global Test Setup")]
|
||||
public abstract class ParallelizableBase
|
||||
{
|
||||
// Common setup or utilities for all tests can go here
|
||||
}
|
||||
101
Tests/UnitTestsParallelizable/TestSetup.cs
Normal file
101
Tests/UnitTestsParallelizable/TestSetup.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
namespace UnitTests.Parallelizable;
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that tests can run in parallel without interference
|
||||
/// by setting various Terminal.Gui static properties to their default values. E.g. View.EnableDebugIDisposableAsserts.
|
||||
/// Annotate all test classes with [Collection("Global Test Setup")] or have it inherit from this class.
|
||||
/// </summary>
|
||||
public class GlobalTestSetup : IDisposable
|
||||
{
|
||||
public GlobalTestSetup ()
|
||||
{
|
||||
#if DEBUG_IDISPOSABLE
|
||||
// Ensure EnableDebugIDisposableAsserts is false before tests run
|
||||
View.EnableDebugIDisposableAsserts = false;
|
||||
#endif
|
||||
CheckDefaultState ();
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
// Optionally reset EnableDebugIDisposableAsserts after tests. Don't do this.
|
||||
// View.EnableDebugIDisposableAsserts = true;
|
||||
|
||||
// Reset application state just in case a test changed something.
|
||||
// TODO: Add an Assert to ensure none of the state of Application changed.
|
||||
// TODO: Add an Assert to ensure none of the state of ConfigurationManager changed.
|
||||
CheckDefaultState ();
|
||||
Application.ResetState (true);
|
||||
}
|
||||
|
||||
// IMPORTANT: Ensure this matches the code in Init_ResetState_Resets_Properties
|
||||
// here: .\Tests\UnitTests\Application\ApplicationTests.cs
|
||||
private void CheckDefaultState ()
|
||||
{
|
||||
#if DEBUG_IDISPOSABLE
|
||||
Assert.False (View.EnableDebugIDisposableAsserts, "View.EnableDebugIDisposableAsserts should be false for Parallelizable tests.");
|
||||
#endif
|
||||
|
||||
// Check that all Application fields and properties are set to their default values
|
||||
|
||||
// Public Properties
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MouseGrabView);
|
||||
Assert.Null (Application.WantContinuousButtonPressedView);
|
||||
|
||||
// Don't check Application.ForceDriver
|
||||
// Assert.Empty (Application.ForceDriver);
|
||||
// Don't check Application.Force16Colors
|
||||
//Assert.False (Application.Force16Colors);
|
||||
Assert.Null (Application.Driver);
|
||||
Assert.Null (Application.MainLoop);
|
||||
Assert.False (Application.EndAfterFirstIteration);
|
||||
Assert.Equal (Key.Tab.WithShift, Application.PrevTabKey);
|
||||
Assert.Equal (Key.Tab, Application.NextTabKey);
|
||||
Assert.Equal (Key.F6.WithShift, Application.PrevTabGroupKey);
|
||||
Assert.Equal (Key.F6, Application.NextTabGroupKey);
|
||||
Assert.Equal (Key.Esc, Application.QuitKey);
|
||||
|
||||
// Internal properties
|
||||
Assert.False (Application.Initialized);
|
||||
Assert.Equal (Application.GetSupportedCultures (), Application.SupportedCultures);
|
||||
Assert.Equal (Application.GetAvailableCulturesFromEmbeddedResources (), Application.SupportedCultures);
|
||||
Assert.False (Application._forceFakeConsole);
|
||||
Assert.Equal (-1, Application.MainThreadId);
|
||||
Assert.Empty (Application.TopLevels);
|
||||
Assert.Empty (Application._cachedViewsUnderMouse);
|
||||
|
||||
// Mouse
|
||||
// Do not reset _lastMousePosition
|
||||
//Assert.Null (Application._lastMousePosition);
|
||||
|
||||
// Navigation
|
||||
Assert.Null (Application.Navigation);
|
||||
|
||||
// Popover
|
||||
Assert.Null (Application.Popover);
|
||||
|
||||
// Events - Can't check
|
||||
//Assert.Null (Application.NotifyNewRunState);
|
||||
//Assert.Null (Application.NotifyNewRunState);
|
||||
//Assert.Null (Application.Iteration);
|
||||
//Assert.Null (Application.SizeChanging);
|
||||
//Assert.Null (Application.GrabbedMouse);
|
||||
//Assert.Null (Application.UnGrabbingMouse);
|
||||
//Assert.Null (Application.GrabbedMouse);
|
||||
//Assert.Null (Application.UnGrabbedMouse);
|
||||
//Assert.Null (Application.MouseEvent);
|
||||
//Assert.Null (Application.KeyDown);
|
||||
//Assert.Null (Application.KeyUp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Define a collection for the global setup
|
||||
[CollectionDefinition ("Global Test Setup")]
|
||||
public class GlobalTestSetupCollection : ICollectionFixture<GlobalTestSetup>
|
||||
{
|
||||
// This class has no code and is never instantiated.
|
||||
// Its purpose is to apply the [CollectionDefinition] attribute
|
||||
// and associate the GlobalTestSetup with the test collection.
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<DefineDebug>true</DefineDebug>
|
||||
<DefineConstants>$(DefineConstants)</DefineConstants>
|
||||
<DefineConstants>$(DefineConstants);DEBUG_IDISPOSABLE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<Optimize>true</Optimize>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class AdornmentSubViewTests ()
|
||||
{
|
||||
[Fact]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class AdornmentTests
|
||||
{
|
||||
[Fact]
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
|
||||
public class ShadowStyleTests
|
||||
{
|
||||
[Fact]
|
||||
|
||||
@@ -3,6 +3,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class HotKeyTests
|
||||
{
|
||||
[Theory]
|
||||
@@ -372,46 +373,4 @@ public class HotKeyTests
|
||||
Assert.Equal ("", view.Title);
|
||||
Assert.Equal (KeyCode.Null, view.HotKey);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void HotKey_Raises_HotKeyCommand ()
|
||||
{
|
||||
var hotKeyRaised = false;
|
||||
var acceptRaised = false;
|
||||
var selectRaised = false;
|
||||
Application.Top = new Toplevel ();
|
||||
var view = new View
|
||||
{
|
||||
CanFocus = true,
|
||||
HotKeySpecifier = new Rune ('_'),
|
||||
Title = "_Test"
|
||||
};
|
||||
Application.Top.Add (view);
|
||||
view.HandlingHotKey += (s, e) => hotKeyRaised = true;
|
||||
view.Accepting += (s, e) => acceptRaised = true;
|
||||
view.Selecting += (s, e) => selectRaised = true;
|
||||
|
||||
Assert.Equal (KeyCode.T, view.HotKey);
|
||||
Assert.True (Application.RaiseKeyDownEvent (Key.T));
|
||||
Assert.True (hotKeyRaised);
|
||||
Assert.False (acceptRaised);
|
||||
Assert.False (selectRaised);
|
||||
|
||||
hotKeyRaised = false;
|
||||
Assert.True (Application.RaiseKeyDownEvent (Key.T.WithAlt));
|
||||
Assert.True (hotKeyRaised);
|
||||
Assert.False (acceptRaised);
|
||||
Assert.False (selectRaised);
|
||||
|
||||
hotKeyRaised = false;
|
||||
view.HotKey = KeyCode.E;
|
||||
Assert.True (Application.RaiseKeyDownEvent (Key.E.WithAlt));
|
||||
Assert.True (hotKeyRaised);
|
||||
Assert.False (acceptRaised);
|
||||
Assert.False (selectRaised);
|
||||
|
||||
Application.Top.Dispose ();
|
||||
Application.ResetState (true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class KeyboardEventTests (ITestOutputHelper output) : TestsAllViews
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -6,6 +6,7 @@ using static Terminal.Gui.Dim;
|
||||
|
||||
namespace Terminal.Gui.LayoutTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class DimTests
|
||||
{
|
||||
[Fact]
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
namespace Terminal.Gui.LayoutTests;
|
||||
using UnitTests.Parallelizable;
|
||||
|
||||
public class SetLayoutTests
|
||||
namespace Terminal.Gui.LayoutTests;
|
||||
|
||||
public class SetLayoutTests : GlobalTestSetup
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Does_Not_Call_Layout ()
|
||||
|
||||
@@ -3,6 +3,8 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewMouseTests;
|
||||
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
[Trait ("Category", "Input")]
|
||||
public class MouseTests (ITestOutputHelper output) : TestsAllViews
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class AddRemoveNavigationTests () : TestsAllViews
|
||||
{
|
||||
[Fact]
|
||||
|
||||
@@ -3,6 +3,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class CanFocusTests () : TestsAllViews
|
||||
{
|
||||
[Fact]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class EnabledTests : TestsAllViews
|
||||
{
|
||||
[Fact]
|
||||
|
||||
@@ -3,6 +3,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class HasFocusChangeEventTests () : TestsAllViews
|
||||
{
|
||||
#region HasFocusChanging_NewValue_True
|
||||
|
||||
@@ -3,6 +3,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class HasFocusTests () : TestsAllViews
|
||||
{
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class RestoreFocusTests () : TestsAllViews
|
||||
{
|
||||
[Fact]
|
||||
|
||||
@@ -3,6 +3,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class SetFocusTests () : TestsAllViews
|
||||
{
|
||||
[Fact]
|
||||
|
||||
@@ -3,6 +3,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class VisibleTests () : TestsAllViews
|
||||
{
|
||||
[Fact]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Terminal.Gui.ViewTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class SubViewTests
|
||||
{
|
||||
[Fact]
|
||||
@@ -591,4 +592,70 @@ public class SubViewTests
|
||||
Assert.NotEqual (superView, subView.SuperView);
|
||||
Assert.Empty (superView.SubViews);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveAll_Removes_All_SubViews ()
|
||||
{
|
||||
// Arrange
|
||||
var superView = new View ();
|
||||
var subView1 = new View ();
|
||||
var subView2 = new View ();
|
||||
var subView3 = new View ();
|
||||
|
||||
superView.Add (subView1, subView2, subView3);
|
||||
|
||||
// Act
|
||||
var removedViews = superView.RemoveAll ();
|
||||
|
||||
// Assert
|
||||
Assert.Empty (superView.SubViews);
|
||||
Assert.Equal (3, removedViews.Count);
|
||||
Assert.Contains (subView1, removedViews);
|
||||
Assert.Contains (subView2, removedViews);
|
||||
Assert.Contains (subView3, removedViews);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveAllTView_Removes_All_SubViews_Of_Specific_Type ()
|
||||
{
|
||||
// Arrange
|
||||
var superView = new View ();
|
||||
var subView1 = new View ();
|
||||
var subView2 = new View ();
|
||||
var subView3 = new View ();
|
||||
var subView4 = new Button ();
|
||||
|
||||
superView.Add (subView1, subView2, subView3, subView4);
|
||||
|
||||
// Act
|
||||
var removedViews = superView.RemoveAll<Button> ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (3, superView.SubViews.Count);
|
||||
Assert.DoesNotContain (subView4, superView.SubViews);
|
||||
Assert.Single (removedViews);
|
||||
Assert.Contains (subView4, removedViews);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveAllTView_Does_Not_Remove_Other_Types ()
|
||||
{
|
||||
// Arrange
|
||||
var superView = new View ();
|
||||
var subView1 = new View ();
|
||||
var subView2 = new Button ();
|
||||
var subView3 = new Label ();
|
||||
|
||||
superView.Add (subView1, subView2, subView3);
|
||||
|
||||
// Act
|
||||
var removedViews = superView.RemoveAll<Button> ();
|
||||
|
||||
// Assert
|
||||
Assert.Equal (2, superView.SubViews.Count);
|
||||
Assert.Contains (subView1, superView.SubViews);
|
||||
Assert.Contains (subView3, superView.SubViews);
|
||||
Assert.Single (removedViews);
|
||||
Assert.Contains (subView2, removedViews);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace Terminal.Gui.ViewsTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
public class AllViewsTests (ITestOutputHelper output) : TestsAllViews
|
||||
{
|
||||
[Theory]
|
||||
@@ -25,6 +26,8 @@ public class AllViewsTests (ITestOutputHelper output) : TestsAllViews
|
||||
{
|
||||
Assert.True (type.FullName == view.GetType ().FullName);
|
||||
}
|
||||
|
||||
view?.Dispose ();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -72,11 +75,12 @@ public class AllViewsTests (ITestOutputHelper output) : TestsAllViews
|
||||
Assert.Equal (1, selectingCount);
|
||||
Assert.Equal (0, acceptedCount);
|
||||
}
|
||||
view?.Dispose ();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData (nameof (AllViewTypes))]
|
||||
public void AllViews_Command_Accept_Raises_Accepted (Type viewType)
|
||||
public void AllViews_Command_Accept_Raises_Accepting (Type viewType)
|
||||
{
|
||||
var view = CreateInstanceIfNotGeneric (viewType);
|
||||
|
||||
@@ -95,14 +99,15 @@ public class AllViewsTests (ITestOutputHelper output) : TestsAllViews
|
||||
var selectingCount = 0;
|
||||
view.Selecting += (s, e) => selectingCount++;
|
||||
|
||||
var acceptedCount = 0;
|
||||
view.Accepting += (s, e) => { acceptedCount++; };
|
||||
var acceptingCount = 0;
|
||||
view.Accepting += (s, e) => { acceptingCount++; };
|
||||
|
||||
if (view.InvokeCommand (Command.Accept) == true)
|
||||
{
|
||||
Assert.Equal (0, selectingCount);
|
||||
Assert.Equal (1, acceptedCount);
|
||||
Assert.Equal (1, acceptingCount);
|
||||
}
|
||||
view?.Dispose ();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -138,5 +143,6 @@ public class AllViewsTests (ITestOutputHelper output) : TestsAllViews
|
||||
Assert.Equal (1, handlingHotKeyCount);
|
||||
Assert.Equal (0, acceptedCount);
|
||||
}
|
||||
view?.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,124 +1,214 @@
|
||||
|
||||
namespace Terminal.Gui.ViewsTests;
|
||||
|
||||
public class FlagSelectorTests
|
||||
{
|
||||
[Fact]
|
||||
public void Initialization_ShouldSetDefaults()
|
||||
public void Initialization_ShouldSetDefaults ()
|
||||
{
|
||||
var flagSelector = new FlagSelector();
|
||||
var flagSelector = new FlagSelector ();
|
||||
|
||||
Assert.True(flagSelector.CanFocus);
|
||||
Assert.Equal(Dim.Auto(DimAutoStyle.Content), flagSelector.Width);
|
||||
Assert.Equal(Dim.Auto(DimAutoStyle.Content), flagSelector.Height);
|
||||
Assert.Equal(Orientation.Vertical, flagSelector.Orientation);
|
||||
Assert.True (flagSelector.CanFocus);
|
||||
Assert.Equal (Dim.Auto (DimAutoStyle.Content), flagSelector.Width);
|
||||
Assert.Equal (Dim.Auto (DimAutoStyle.Content), flagSelector.Height);
|
||||
Assert.Equal (Orientation.Vertical, flagSelector.Orientation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetFlags_WithDictionary_ShouldSetFlags()
|
||||
public void SetFlags_WithDictionary_ShouldSetFlags ()
|
||||
{
|
||||
var flagSelector = new FlagSelector();
|
||||
var flagSelector = new FlagSelector ();
|
||||
var flags = new Dictionary<uint, string>
|
||||
{
|
||||
{ 1, "Flag1" },
|
||||
{ 2, "Flag2" }
|
||||
};
|
||||
|
||||
flagSelector.SetFlags(flags);
|
||||
flagSelector.SetFlags (flags);
|
||||
|
||||
Assert.Equal(flags, flagSelector.Flags);
|
||||
Assert.Equal (flags, flagSelector.Flags);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetFlags_WithEnum_ShouldSetFlags()
|
||||
public void SetFlags_WithDictionary_ShouldSetValue ()
|
||||
{
|
||||
var flagSelector = new FlagSelector();
|
||||
var flagSelector = new FlagSelector ();
|
||||
var flags = new Dictionary<uint, string>
|
||||
{
|
||||
{ 1, "Flag1" },
|
||||
{ 2, "Flag2" }
|
||||
};
|
||||
|
||||
flagSelector.SetFlags<FlagSelectorStyles>();
|
||||
flagSelector.SetFlags (flags);
|
||||
|
||||
var expectedFlags = Enum.GetValues<FlagSelectorStyles>()
|
||||
.ToDictionary(f => Convert.ToUInt32(f), f => f.ToString());
|
||||
|
||||
Assert.Equal(expectedFlags, flagSelector.Flags);
|
||||
Assert.Equal ((uint)1, flagSelector.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetFlags_WithEnumAndCustomNames_ShouldSetFlags()
|
||||
public void SetFlags_WithEnum_ShouldSetFlags ()
|
||||
{
|
||||
var flagSelector = new FlagSelector();
|
||||
var flagSelector = new FlagSelector ();
|
||||
|
||||
flagSelector.SetFlags<FlagSelectorStyles>(f => f switch
|
||||
flagSelector.SetFlags<FlagSelectorStyles> ();
|
||||
|
||||
var expectedFlags = Enum.GetValues<FlagSelectorStyles> ()
|
||||
.ToDictionary (f => Convert.ToUInt32 (f), f => f.ToString ());
|
||||
|
||||
Assert.Equal (expectedFlags, flagSelector.Flags);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetFlags_WithEnumAndCustomNames_ShouldSetFlags ()
|
||||
{
|
||||
var flagSelector = new FlagSelector ();
|
||||
|
||||
flagSelector.SetFlags<FlagSelectorStyles> (f => f switch
|
||||
{
|
||||
FlagSelectorStyles.ShowNone => "Show None Value",
|
||||
FlagSelectorStyles.ShowValueEdit => "Show Value Editor",
|
||||
FlagSelectorStyles.All => "Everything",
|
||||
_ => f.ToString()
|
||||
_ => f.ToString ()
|
||||
});
|
||||
|
||||
var expectedFlags = Enum.GetValues<FlagSelectorStyles>()
|
||||
.ToDictionary(f => Convert.ToUInt32(f), f => f switch
|
||||
var expectedFlags = Enum.GetValues<FlagSelectorStyles> ()
|
||||
.ToDictionary (f => Convert.ToUInt32 (f), f => f switch
|
||||
{
|
||||
FlagSelectorStyles.ShowNone => "Show None Value",
|
||||
FlagSelectorStyles.ShowValueEdit => "Show Value Editor",
|
||||
FlagSelectorStyles.All => "Everything",
|
||||
_ => f.ToString()
|
||||
_ => f.ToString ()
|
||||
});
|
||||
|
||||
Assert.Equal(expectedFlags, flagSelector.Flags);
|
||||
Assert.Equal (expectedFlags, flagSelector.Flags);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Value_Set_ShouldUpdateCheckedState()
|
||||
public void Value_Set_ShouldUpdateCheckedState ()
|
||||
{
|
||||
var flagSelector = new FlagSelector();
|
||||
var flagSelector = new FlagSelector ();
|
||||
var flags = new Dictionary<uint, string>
|
||||
{
|
||||
{ 1, "Flag1" },
|
||||
{ 2, "Flag2" }
|
||||
};
|
||||
|
||||
flagSelector.SetFlags(flags);
|
||||
flagSelector.SetFlags (flags);
|
||||
flagSelector.Value = 1;
|
||||
|
||||
var checkBox = flagSelector.SubViews.OfType<CheckBox>().First(cb => (uint)cb.Data == 1);
|
||||
Assert.Equal(CheckState.Checked, checkBox.CheckedState);
|
||||
var checkBox = flagSelector.SubViews.OfType<CheckBox> ().First (cb => (uint)cb.Data == 1);
|
||||
Assert.Equal (CheckState.Checked, checkBox.CheckedState);
|
||||
|
||||
checkBox = flagSelector.SubViews.OfType<CheckBox>().First(cb => (uint)cb.Data == 2);
|
||||
Assert.Equal(CheckState.UnChecked, checkBox.CheckedState);
|
||||
checkBox = flagSelector.SubViews.OfType<CheckBox> ().First (cb => (uint)cb.Data == 2);
|
||||
Assert.Equal (CheckState.UnChecked, checkBox.CheckedState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Styles_Set_ShouldCreateSubViews()
|
||||
public void Styles_Set_ShouldCreateSubViews ()
|
||||
{
|
||||
var flagSelector = new FlagSelector();
|
||||
var flagSelector = new FlagSelector ();
|
||||
var flags = new Dictionary<uint, string>
|
||||
{
|
||||
{ 1, "Flag1" },
|
||||
{ 2, "Flag2" }
|
||||
};
|
||||
|
||||
flagSelector.SetFlags(flags);
|
||||
flagSelector.SetFlags (flags);
|
||||
flagSelector.Styles = FlagSelectorStyles.ShowNone;
|
||||
|
||||
Assert.Contains(flagSelector.SubViews, sv => sv is CheckBox cb && cb.Title == "None");
|
||||
Assert.Contains (flagSelector.SubViews, sv => sv is CheckBox cb && cb.Title == "None");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValueChanged_Event_ShouldBeRaised()
|
||||
public void ValueChanged_Event_ShouldBeRaised ()
|
||||
{
|
||||
var flagSelector = new FlagSelector();
|
||||
var flagSelector = new FlagSelector ();
|
||||
var flags = new Dictionary<uint, string>
|
||||
{
|
||||
{ 1, "Flag1" },
|
||||
{ 2, "Flag2" }
|
||||
};
|
||||
|
||||
flagSelector.SetFlags(flags);
|
||||
flagSelector.SetFlags (flags);
|
||||
bool eventRaised = false;
|
||||
flagSelector.ValueChanged += (sender, args) => eventRaised = true;
|
||||
|
||||
flagSelector.Value = 1;
|
||||
flagSelector.Value = 2;
|
||||
|
||||
Assert.True(eventRaised);
|
||||
Assert.True (eventRaised);
|
||||
}
|
||||
|
||||
// Tests for FlagSelector<TEnum>
|
||||
[Fact]
|
||||
public void GenericInitialization_ShouldSetDefaults ()
|
||||
{
|
||||
var flagSelector = new FlagSelector<FlagSelectorStyles> ();
|
||||
|
||||
Assert.True (flagSelector.CanFocus);
|
||||
Assert.Equal (Dim.Auto (DimAutoStyle.Content), flagSelector.Width);
|
||||
Assert.Equal (Dim.Auto (DimAutoStyle.Content), flagSelector.Height);
|
||||
Assert.Equal (Orientation.Vertical, flagSelector.Orientation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Generic_SetFlags_Methods_Throw ()
|
||||
{
|
||||
var flagSelector = new FlagSelector<FlagSelectorStyles> ();
|
||||
|
||||
Assert.Throws<InvalidOperationException> (() => flagSelector.SetFlags (new Dictionary<uint, string> ()));
|
||||
Assert.Throws<InvalidOperationException> (() => flagSelector.SetFlags<FlagSelectorStyles> ());
|
||||
Assert.Throws<InvalidOperationException> (() => flagSelector.SetFlags<FlagSelectorStyles> (styles => null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenericSetFlagNames_ShouldSetFlagNames ()
|
||||
{
|
||||
var flagSelector = new FlagSelector<FlagSelectorStyles> ();
|
||||
|
||||
flagSelector.SetFlagNames (f => f switch
|
||||
{
|
||||
FlagSelectorStyles.ShowNone => "Show None Value",
|
||||
FlagSelectorStyles.ShowValueEdit => "Show Value Editor",
|
||||
FlagSelectorStyles.All => "Everything",
|
||||
_ => f.ToString ()
|
||||
});
|
||||
|
||||
var expectedFlags = Enum.GetValues<FlagSelectorStyles> ()
|
||||
.ToDictionary (f => Convert.ToUInt32 (f), f => f switch
|
||||
{
|
||||
FlagSelectorStyles.ShowNone => "Show None Value",
|
||||
FlagSelectorStyles.ShowValueEdit => "Show Value Editor",
|
||||
FlagSelectorStyles.All => "Everything",
|
||||
_ => f.ToString ()
|
||||
});
|
||||
|
||||
Assert.Equal (expectedFlags, flagSelector.Flags);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenericValue_Set_ShouldUpdateCheckedState ()
|
||||
{
|
||||
var flagSelector = new FlagSelector<FlagSelectorStyles> ();
|
||||
|
||||
flagSelector.SetFlagNames (f => f.ToString ());
|
||||
flagSelector.Value = FlagSelectorStyles.ShowNone;
|
||||
|
||||
var checkBox = flagSelector.SubViews.OfType<CheckBox> ().First (cb => (uint)cb.Data == Convert.ToUInt32 (FlagSelectorStyles.ShowNone));
|
||||
Assert.Equal (CheckState.Checked, checkBox.CheckedState);
|
||||
|
||||
checkBox = flagSelector.SubViews.OfType<CheckBox> ().First (cb => (uint)cb.Data == Convert.ToUInt32 (FlagSelectorStyles.ShowValueEdit));
|
||||
Assert.Equal (CheckState.UnChecked, checkBox.CheckedState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenericValueChanged_Event_ShouldBeRaised ()
|
||||
{
|
||||
var flagSelector = new FlagSelector<FlagSelectorStyles> ();
|
||||
|
||||
flagSelector.SetFlagNames (f => f.ToString ());
|
||||
bool eventRaised = false;
|
||||
flagSelector.ValueChanged += (sender, args) => eventRaised = true;
|
||||
|
||||
flagSelector.Value = FlagSelectorStyles.ShowNone;
|
||||
|
||||
Assert.True (eventRaised);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Terminal.Gui.ViewsTests;
|
||||
|
||||
[Collection ("Global Test Setup")]
|
||||
|
||||
[TestSubject (typeof (Shortcut))]
|
||||
public class ShortcutTests
|
||||
{
|
||||
@@ -420,7 +422,7 @@ public class ShortcutTests
|
||||
Assert.False (shortcut.CommandView.CanFocus);
|
||||
|
||||
shortcut.CommandView = new () { CanFocus = true };
|
||||
Assert.False (shortcut.CommandView.CanFocus);
|
||||
Assert.True (shortcut.CommandView.CanFocus);
|
||||
|
||||
shortcut.CommandView.CanFocus = true;
|
||||
Assert.True (shortcut.CommandView.CanFocus);
|
||||
|
||||
Reference in New Issue
Block a user