| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222 |
- using Xunit.Abstractions;
- namespace UnitTests_Parallelizable.ViewTests;
- public class ArrangementTests (ITestOutputHelper output)
- {
- private readonly ITestOutputHelper _output = output;
- #region ViewArrangement Enum Tests
- [Fact]
- public void ViewArrangement_Fixed_IsZero ()
- {
- Assert.Equal (0, (int)ViewArrangement.Fixed);
- }
- [Fact]
- public void ViewArrangement_Flags_HaveCorrectValues ()
- {
- Assert.Equal (1, (int)ViewArrangement.Movable);
- Assert.Equal (2, (int)ViewArrangement.LeftResizable);
- Assert.Equal (4, (int)ViewArrangement.RightResizable);
- Assert.Equal (8, (int)ViewArrangement.TopResizable);
- Assert.Equal (16, (int)ViewArrangement.BottomResizable);
- Assert.Equal (32, (int)ViewArrangement.Overlapped);
- }
- [Fact]
- public void ViewArrangement_Resizable_IsCombinationOfAllResizableFlags ()
- {
- ViewArrangement expected = ViewArrangement.LeftResizable
- | ViewArrangement.RightResizable
- | ViewArrangement.TopResizable
- | ViewArrangement.BottomResizable;
-
- Assert.Equal (ViewArrangement.Resizable, expected);
- }
- [Fact]
- public void ViewArrangement_CanCombineFlags ()
- {
- ViewArrangement arrangement = ViewArrangement.Movable | ViewArrangement.LeftResizable;
-
- Assert.True (arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.False (arrangement.HasFlag (ViewArrangement.RightResizable));
- }
- #endregion
- #region View.Arrangement Property Tests
- [Fact]
- public void View_Arrangement_DefaultsToFixed ()
- {
- var view = new View ();
- Assert.Equal (ViewArrangement.Fixed, view.Arrangement);
- }
- [Fact]
- public void View_Arrangement_CanBeSet ()
- {
- var view = new View { Arrangement = ViewArrangement.Movable };
- Assert.Equal (ViewArrangement.Movable, view.Arrangement);
- }
- [Fact]
- public void View_Arrangement_CanSetMultipleFlags ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Movable | ViewArrangement.Resizable
- };
-
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- }
- [Fact]
- public void View_Arrangement_Overlapped_CanBeSetIndependently ()
- {
- var view = new View { Arrangement = ViewArrangement.Overlapped };
-
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Overlapped));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.Movable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.Resizable));
- }
- [Fact]
- public void View_Arrangement_CanCombineOverlappedWithOtherFlags ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Overlapped | ViewArrangement.Movable
- };
-
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Overlapped));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Movable));
- }
- #endregion
- #region TopResizable and Movable Mutual Exclusivity Tests
- [Fact]
- public void TopResizable_WithoutMovable_IsAllowed ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.TopResizable,
- BorderStyle = LineStyle.Single
- };
-
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.Movable));
- }
- [Fact]
- public void Movable_WithTopResizable_MovableWins ()
- {
- // According to docs and Border.Arrangment.cs line 569:
- // TopResizable is only checked if NOT Movable
- var view = new View
- {
- Arrangement = ViewArrangement.Movable | ViewArrangement.TopResizable,
- BorderStyle = LineStyle.Single
- };
-
- // Both flags can be set on the property
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
-
- // But the behavior in Border.DetermineArrangeModeFromClick
- // will prioritize Movable over TopResizable
- }
- [Fact]
- public void Resizable_WithMovable_IncludesTopResizable ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Resizable | ViewArrangement.Movable,
- BorderStyle = LineStyle.Single
- };
-
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- }
- #endregion
- #region Border Arrangement Tests
- [Fact]
- public void Border_WithNoArrangement_HasNoArrangementOptions ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Fixed,
- BorderStyle = LineStyle.Single
- };
-
- Assert.NotNull (view.Border);
- Assert.Equal (ViewArrangement.Fixed, view.Arrangement);
- }
- [Fact]
- public void Border_WithMovableArrangement_CanEnterArrangeMode ()
- {
- var superView = new View ();
- var view = new View
- {
- Arrangement = ViewArrangement.Movable,
- BorderStyle = LineStyle.Single,
- X = 0,
- Y = 0,
- Width = 10,
- Height = 10
- };
- superView.Add (view);
-
- Assert.NotNull (view.Border);
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Movable));
- }
- [Fact]
- public void Border_WithResizableArrangement_HasResizableOptions ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Resizable,
- BorderStyle = LineStyle.Single
- };
-
- Assert.NotNull (view.Border);
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- }
- [Theory]
- [InlineData (ViewArrangement.LeftResizable)]
- [InlineData (ViewArrangement.RightResizable)]
- [InlineData (ViewArrangement.TopResizable)]
- [InlineData (ViewArrangement.BottomResizable)]
- public void Border_WithSingleResizableDirection_OnlyHasThatOption (ViewArrangement arrangement)
- {
- var view = new View
- {
- Arrangement = arrangement,
- BorderStyle = LineStyle.Single
- };
-
- Assert.NotNull (view.Border);
- Assert.True (view.Arrangement.HasFlag (arrangement));
-
- // Verify other directions are not set
- if (arrangement != ViewArrangement.LeftResizable)
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- if (arrangement != ViewArrangement.RightResizable)
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- if (arrangement != ViewArrangement.TopResizable)
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- if (arrangement != ViewArrangement.BottomResizable)
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- }
- #endregion
- #region Corner Resizing Tests
- [Fact]
- public void Border_BottomRightResizable_CombinesBothFlags ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.BottomResizable | ViewArrangement.RightResizable,
- BorderStyle = LineStyle.Single
- };
-
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- }
- [Fact]
- public void Border_BottomLeftResizable_CombinesBothFlags ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.BottomResizable | ViewArrangement.LeftResizable,
- BorderStyle = LineStyle.Single
- };
-
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- }
- [Fact]
- public void Border_TopRightResizable_CombinesBothFlags ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.TopResizable | ViewArrangement.RightResizable,
- BorderStyle = LineStyle.Single
- };
-
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- }
- [Fact]
- public void Border_TopLeftResizable_CombinesBothFlags ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.TopResizable | ViewArrangement.LeftResizable,
- BorderStyle = LineStyle.Single
- };
-
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- }
- #endregion
- #region Overlapped Layout Tests
- [Theory]
- [InlineData (ViewArrangement.Fixed)]
- [InlineData (ViewArrangement.Overlapped)]
- public void MoveSubViewToEnd_ViewArrangement (ViewArrangement arrangement)
- {
- View superView = new () { Arrangement = arrangement };
- var subview1 = new View { Id = "subview1" };
- var subview2 = new View { Id = "subview2" };
- var subview3 = new View { Id = "subview3" };
- superView.Add (subview1, subview2, subview3);
- superView.MoveSubViewToEnd (subview1);
- Assert.Equal ([subview2, subview3, subview1], superView.SubViews.ToArray ());
- superView.MoveSubViewToEnd (subview2);
- Assert.Equal ([subview3, subview1, subview2], superView.SubViews.ToArray ());
- superView.MoveSubViewToEnd (subview3);
- Assert.Equal ([subview1, subview2, subview3], superView.SubViews.ToArray ());
- }
- [Fact]
- public void Overlapped_AllowsSubViewsToOverlap ()
- {
- var superView = new View
- {
- Arrangement = ViewArrangement.Overlapped,
- Width = 20,
- Height = 20
- };
- var view1 = new View { X = 0, Y = 0, Width = 10, Height = 10 };
- var view2 = new View { X = 5, Y = 5, Width = 10, Height = 10 };
- superView.Add (view1, view2);
- // Both views can exist at overlapping positions
- Assert.Equal (2, superView.SubViews.Count);
- Assert.True (view1.Frame.IntersectsWith (view2.Frame));
- }
- #endregion
- #region Splitter Pattern Tests
- [Fact]
- public void LeftResizable_CanBeUsedForHorizontalSplitter ()
- {
- var container = new View { Width = 80, Height = 25 };
-
- var leftPane = new View
- {
- X = 0,
- Y = 0,
- Width = 40,
- Height = Dim.Fill ()
- };
-
- var rightPane = new View
- {
- X = 40,
- Y = 0,
- Width = Dim.Fill (),
- Height = Dim.Fill (),
- Arrangement = ViewArrangement.LeftResizable,
- BorderStyle = LineStyle.Single
- };
-
- container.Add (leftPane, rightPane);
-
- Assert.True (rightPane.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.NotNull (rightPane.Border);
- }
- [Fact]
- public void TopResizable_CanBeUsedForVerticalSplitter ()
- {
- var container = new View { Width = 80, Height = 25 };
-
- var topPane = new View
- {
- X = 0,
- Y = 0,
- Width = Dim.Fill (),
- Height = 10
- };
-
- var bottomPane = new View
- {
- X = 0,
- Y = 10,
- Width = Dim.Fill (),
- Height = Dim.Fill (),
- Arrangement = ViewArrangement.TopResizable,
- BorderStyle = LineStyle.Single
- };
-
- container.Add (topPane, bottomPane);
-
- Assert.True (bottomPane.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.NotNull (bottomPane.Border);
- }
- #endregion
- #region View Without Border Tests
- [Fact]
- public void View_WithoutBorderStyle_CanHaveArrangement ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Movable
- };
-
- // Arrangement can be set even without a border style
- // Border object still exists but has no visible style
- Assert.Equal (ViewArrangement.Movable, view.Arrangement);
- Assert.NotNull (view.Border);
- Assert.Equal (LineStyle.None, view.BorderStyle);
- }
- [Fact]
- public void View_WithNoBorderStyle_ResizableCanBeSet ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Resizable
- };
-
- // Arrangement is set but has limited effect without a visible border style
- Assert.Equal (ViewArrangement.Resizable, view.Arrangement);
- Assert.NotNull (view.Border);
- Assert.Equal (LineStyle.None, view.BorderStyle);
- }
- #endregion
- #region Integration Tests - Border DetermineArrangeModeFromClick Behavior
- [Fact]
- public void DetermineArrangeModeFromClick_TopResizableIgnoredWhenMovable ()
- {
- // This test verifies the documented behavior that TopResizable is ignored
- // when Movable is also set (line 569 in Border.Arrangment.cs)
- var superView = new View { Width = 80, Height = 25 };
- var view = new View
- {
- Arrangement = ViewArrangement.TopResizable | ViewArrangement.Movable,
- BorderStyle = LineStyle.Single,
- X = 10,
- Y = 10,
- Width = 20,
- Height = 10
- };
- superView.Add (view);
-
- // The view has both flags set
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Movable));
-
- // But Movable takes precedence in Border.DetermineArrangeModeFromClick
- // This is verified by the code at line 569 checking !Parent!.Arrangement.HasFlag(ViewArrangement.Movable)
- }
- [Fact]
- public void DetermineArrangeModeFromClick_TopResizableWorksWithoutMovable ()
- {
- var superView = new View { Width = 80, Height = 25 };
- var view = new View
- {
- Arrangement = ViewArrangement.TopResizable,
- BorderStyle = LineStyle.Single,
- X = 10,
- Y = 10,
- Width = 20,
- Height = 10
- };
- superView.Add (view);
-
- // Only TopResizable is set
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.Movable));
- }
- [Fact]
- public void DetermineArrangeModeFromClick_AllCornerCombinationsSupported ()
- {
- var superView = new View { Width = 80, Height = 25 };
-
- // Test that all 4 corner combinations are recognized
- var cornerCombinations = new[]
- {
- ViewArrangement.BottomResizable | ViewArrangement.RightResizable,
- ViewArrangement.BottomResizable | ViewArrangement.LeftResizable,
- ViewArrangement.TopResizable | ViewArrangement.RightResizable,
- ViewArrangement.TopResizable | ViewArrangement.LeftResizable
- };
-
- foreach (var arrangement in cornerCombinations)
- {
- var view = new View
- {
- Arrangement = arrangement,
- BorderStyle = LineStyle.Single,
- X = 10,
- Y = 10,
- Width = 20,
- Height = 10
- };
- superView.Add (view);
-
- // Verify the flags are set correctly
- Assert.True (view.Arrangement == arrangement);
-
- superView.Remove (view);
- }
- }
- #endregion
- #region ViewArrangement Property Change Tests
- [Fact]
- public void View_Arrangement_CanBeChangedAfterCreation ()
- {
- var view = new View { Arrangement = ViewArrangement.Fixed };
- Assert.Equal (ViewArrangement.Fixed, view.Arrangement);
-
- view.Arrangement = ViewArrangement.Movable;
- Assert.Equal (ViewArrangement.Movable, view.Arrangement);
-
- view.Arrangement = ViewArrangement.Resizable;
- Assert.Equal (ViewArrangement.Resizable, view.Arrangement);
- }
- [Fact]
- public void View_Arrangement_CanAddFlags ()
- {
- var view = new View { Arrangement = ViewArrangement.Movable };
-
- view.Arrangement |= ViewArrangement.LeftResizable;
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- }
- [Fact]
- public void View_Arrangement_CanRemoveFlags ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Movable | ViewArrangement.Resizable
- };
-
- view.Arrangement &= ~ViewArrangement.Movable;
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Resizable));
- }
- #endregion
- #region Multiple SubViews Arrangement Tests
- [Fact]
- public void SuperView_CanHaveMultipleArrangeableSubViews ()
- {
- var superView = new View
- {
- Arrangement = ViewArrangement.Overlapped,
- Width = 80,
- Height = 25
- };
-
- var movableView = new View
- {
- Arrangement = ViewArrangement.Movable,
- BorderStyle = LineStyle.Single,
- X = 0,
- Y = 0,
- Width = 20,
- Height = 10
- };
-
- var resizableView = new View
- {
- Arrangement = ViewArrangement.Resizable,
- BorderStyle = LineStyle.Single,
- X = 25,
- Y = 0,
- Width = 20,
- Height = 10
- };
-
- var fixedView = new View
- {
- Arrangement = ViewArrangement.Fixed,
- BorderStyle = LineStyle.Single,
- X = 50,
- Y = 0,
- Width = 20,
- Height = 10
- };
-
- superView.Add (movableView, resizableView, fixedView);
-
- Assert.Equal (3, superView.SubViews.Count);
- Assert.Equal (ViewArrangement.Movable, movableView.Arrangement);
- Assert.Equal (ViewArrangement.Resizable, resizableView.Arrangement);
- Assert.Equal (ViewArrangement.Fixed, fixedView.Arrangement);
- }
- [Fact]
- public void SubView_ArrangementIndependentOfSuperView ()
- {
- var superView = new View { Arrangement = ViewArrangement.Fixed };
- var subView = new View { Arrangement = ViewArrangement.Movable };
-
- superView.Add (subView);
-
- // SubView arrangement is independent of SuperView arrangement
- Assert.Equal (ViewArrangement.Fixed, superView.Arrangement);
- Assert.Equal (ViewArrangement.Movable, subView.Arrangement);
- }
- #endregion
- #region Border Thickness Tests
- [Fact]
- public void Border_WithDefaultThickness_SupportsArrangement ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Movable,
- BorderStyle = LineStyle.Single
- };
-
- Assert.NotNull (view.Border);
- // Default thickness should be (1,1,1,1) for Single line style
- Assert.True (view.Border.Thickness.Left > 0 || view.Border.Thickness.Right > 0
- || view.Border.Thickness.Top > 0 || view.Border.Thickness.Bottom > 0);
- }
- [Fact]
- public void Border_WithCustomThickness_SupportsArrangement ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.LeftResizable,
- BorderStyle = LineStyle.Single
- };
-
- // Set custom thickness - only left border
- view.Border!.Thickness = new Thickness (2, 0, 0, 0);
-
- Assert.Equal (2, view.Border.Thickness.Left);
- Assert.Equal (0, view.Border.Thickness.Top);
- Assert.Equal (0, view.Border.Thickness.Right);
- Assert.Equal (0, view.Border.Thickness.Bottom);
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- }
- #endregion
- #region View-Specific Arrangement Tests
- [Fact]
- public void Toplevel_DefaultsToOverlapped ()
- {
- var toplevel = new Toplevel ();
- Assert.True (toplevel.Arrangement.HasFlag (ViewArrangement.Overlapped));
- }
- [Fact]
- public void Window_DefaultsToOverlapped ()
- {
- var window = new Window ();
- Assert.True (window.Arrangement.HasFlag (ViewArrangement.Overlapped));
- }
- [Fact]
- public void Dialog_DefaultsToMovableAndOverlapped ()
- {
- var dialog = new Dialog ();
- Assert.True (dialog.Arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (dialog.Arrangement.HasFlag (ViewArrangement.Overlapped));
- }
- [Fact]
- public void View_Navigation_RespectsOverlappedFlag ()
- {
- // View.Navigation.cs checks Arrangement.HasFlag(ViewArrangement.Overlapped)
- var overlappedView = new View { Arrangement = ViewArrangement.Overlapped };
- var tiledView = new View { Arrangement = ViewArrangement.Fixed };
-
- Assert.True (overlappedView.Arrangement.HasFlag (ViewArrangement.Overlapped));
- Assert.False (tiledView.Arrangement.HasFlag (ViewArrangement.Overlapped));
- }
- [Fact]
- public void View_Hierarchy_RespectsOverlappedFlag ()
- {
- // View.Hierarchy.cs checks Arrangement.HasFlag(ViewArrangement.Overlapped)
- var parent = new View { Arrangement = ViewArrangement.Overlapped };
- var child1 = new View { X = 0, Y = 0, Width = 10, Height = 10 };
- var child2 = new View { X = 5, Y = 5, Width = 10, Height = 10 };
-
- parent.Add (child1, child2);
-
- Assert.True (parent.Arrangement.HasFlag (ViewArrangement.Overlapped));
- Assert.Equal (2, parent.SubViews.Count);
- }
- #endregion
- #region Mouse Interaction Tests
- [Fact]
- public void MouseGrabHandler_WorksWithMovableView_UsingNewMouseEvent ()
- {
- // This test proves that MouseGrabHandler works correctly with concurrent unit tests
- // using NewMouseEvent directly on views, without requiring Application.Init
-
- var superView = new View
- {
- Width = 80,
- Height = 25
- };
-
- var movableView = new View
- {
- Arrangement = ViewArrangement.Movable,
- BorderStyle = LineStyle.Single,
- X = 10,
- Y = 10,
- Width = 20,
- Height = 10
- };
-
- superView.Add (movableView);
-
- // Verify initial state
- Assert.NotNull (movableView.Border);
- Assert.Null (Application.Mouse.MouseGrabView);
-
- // Simulate mouse press on the border to start dragging
- var pressEvent = new MouseEventArgs
- {
- Position = new (1, 0), // Top border area
- Flags = MouseFlags.Button1Pressed
- };
-
- bool? result = movableView.Border.NewMouseEvent (pressEvent);
-
- // The border should have grabbed the mouse
- Assert.True (result);
- Assert.Equal (movableView.Border, Application.Mouse.MouseGrabView);
-
- // Simulate mouse drag
- var dragEvent = new MouseEventArgs
- {
- Position = new (5, 2),
- Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
- };
-
- result = movableView.Border.NewMouseEvent (dragEvent);
- Assert.True (result);
-
- // Mouse should still be grabbed
- Assert.Equal (movableView.Border, Application.Mouse.MouseGrabView);
-
- // Simulate mouse release to end dragging
- var releaseEvent = new MouseEventArgs
- {
- Position = new (5, 2),
- Flags = MouseFlags.Button1Released
- };
-
- result = movableView.Border.NewMouseEvent (releaseEvent);
- Assert.True (result);
-
- // Mouse should be released
- Assert.Null (Application.Mouse.MouseGrabView);
- }
- [Fact]
- public void MouseGrabHandler_WorksWithResizableView_UsingNewMouseEvent ()
- {
- // This test proves MouseGrabHandler works for resizing operations
-
- var superView = new View
- {
- Width = 80,
- Height = 25
- };
-
- var resizableView = new View
- {
- Arrangement = ViewArrangement.RightResizable,
- BorderStyle = LineStyle.Single,
- X = 10,
- Y = 10,
- Width = 20,
- Height = 10
- };
-
- superView.Add (resizableView);
-
- // Verify initial state
- Assert.NotNull (resizableView.Border);
- Assert.Null (Application.Mouse.MouseGrabView);
-
- // Calculate position on right border (border is at right edge)
- // Border.Frame.X is relative to parent, so we use coordinates relative to the border
- var pressEvent = new MouseEventArgs
- {
- Position = new (resizableView.Border.Frame.Width - 1, 5), // Right border area
- Flags = MouseFlags.Button1Pressed
- };
-
- bool? result = resizableView.Border.NewMouseEvent (pressEvent);
-
- // The border should have grabbed the mouse for resizing
- Assert.True (result);
- Assert.Equal (resizableView.Border, Application.Mouse.MouseGrabView);
-
- // Simulate dragging to resize
- var dragEvent = new MouseEventArgs
- {
- Position = new (resizableView.Border.Frame.Width + 3, 5),
- Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
- };
-
- result = resizableView.Border.NewMouseEvent (dragEvent);
- Assert.True (result);
- Assert.Equal (resizableView.Border, Application.Mouse.MouseGrabView);
-
- // Simulate mouse release
- var releaseEvent = new MouseEventArgs
- {
- Position = new (resizableView.Border.Frame.Width + 3, 5),
- Flags = MouseFlags.Button1Released
- };
-
- result = resizableView.Border.NewMouseEvent (releaseEvent);
- Assert.True (result);
-
- // Mouse should be released
- Assert.Null (Application.Mouse.MouseGrabView);
- }
- [Fact]
- public void MouseGrabHandler_ReleasesOnMultipleViews ()
- {
- // This test verifies MouseGrabHandler properly releases when switching between views
-
- var superView = new View { Width = 80, Height = 25 };
-
- var view1 = new View
- {
- Arrangement = ViewArrangement.Movable,
- BorderStyle = LineStyle.Single,
- X = 10,
- Y = 10,
- Width = 15,
- Height = 8
- };
-
- var view2 = new View
- {
- Arrangement = ViewArrangement.Movable,
- BorderStyle = LineStyle.Single,
- X = 30,
- Y = 10,
- Width = 15,
- Height = 8
- };
-
- superView.Add (view1, view2);
-
- // Grab mouse on first view
- var pressEvent1 = new MouseEventArgs
- {
- Position = new (1, 0),
- Flags = MouseFlags.Button1Pressed
- };
-
- view1.Border!.NewMouseEvent (pressEvent1);
- Assert.Equal (view1.Border, Application.Mouse.MouseGrabView);
-
- // Release on first view
- var releaseEvent1 = new MouseEventArgs
- {
- Position = new (1, 0),
- Flags = MouseFlags.Button1Released
- };
-
- view1.Border.NewMouseEvent (releaseEvent1);
- Assert.Null (Application.Mouse.MouseGrabView);
-
- // Grab mouse on second view
- var pressEvent2 = new MouseEventArgs
- {
- Position = new (1, 0),
- Flags = MouseFlags.Button1Pressed
- };
-
- view2.Border!.NewMouseEvent (pressEvent2);
- Assert.Equal (view2.Border, Application.Mouse.MouseGrabView);
-
- // Release on second view
- var releaseEvent2 = new MouseEventArgs
- {
- Position = new (1, 0),
- Flags = MouseFlags.Button1Released
- };
-
- view2.Border.NewMouseEvent (releaseEvent2);
- Assert.Null (Application.Mouse.MouseGrabView);
- }
- #endregion
- #region Summary and Limitations
- // NOTE: The original concern that Border.OnMouseEvent depends on Application.Mouse
- // has been addressed. The tests above prove that MouseGrabHandler works correctly in
- // parallelizable tests when using NewMouseEvent directly on views.
- //
- // Remaining functionality that still requires Application.Init:
- // 1. Border.EnterArrangeMode() with keyboard mode - depends on Application.ArrangeKey
- // 2. Border.HandleDragOperation() - depends on Application.Top for screen refresh
- // 3. Application-level mouse event routing through Application.RaiseMouseEvent
- //
- // The tests in this file demonstrate:
- // - ViewArrangement enum and flag behavior
- // - View.Arrangement property behavior
- // - Border existence and configuration with arrangements
- // - MouseGrabHandler interaction with arrangeable views
- // - Logical combinations of arrangement flags
- // - Mutual exclusivity rules (TopResizable vs Movable)
- // - Multiple subview scenarios
- //
- // This provides comprehensive coverage of arrangement functionality using
- // parallelizable tests with NewMouseEvent.
- [Fact]
- public void AllArrangementTests_AreParallelizable ()
- {
- // This test verifies that all the arrangement tests in this file
- // can run without Application.Init, making them parallelizable.
- // If this test passes, it confirms no Application dependencies leaked in.
-
- var view = new View
- {
- Arrangement = ViewArrangement.Movable | ViewArrangement.Resizable,
- BorderStyle = LineStyle.Single
- };
-
- Assert.NotNull (view);
- Assert.NotNull (view.Border);
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Resizable));
- }
- #endregion
- #region ViewArrangement Advanced Flag Tests
- [Fact]
- public void ViewArrangement_CanCombineAllResizableDirections ()
- {
- ViewArrangement arrangement = ViewArrangement.TopResizable
- | ViewArrangement.BottomResizable
- | ViewArrangement.LeftResizable
- | ViewArrangement.RightResizable;
- Assert.True (arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.True (arrangement.HasFlag (ViewArrangement.BottomResizable));
- Assert.True (arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.True (arrangement.HasFlag (ViewArrangement.RightResizable));
- Assert.True (arrangement.HasFlag (ViewArrangement.Resizable)); // Resizable is all four combined
- }
- [Fact]
- public void ViewArrangement_MovableAndResizable_CanCoexist ()
- {
- ViewArrangement arrangement = ViewArrangement.Movable | ViewArrangement.Resizable;
- Assert.True (arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (arrangement.HasFlag (ViewArrangement.Resizable));
- Assert.True (arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.True (arrangement.HasFlag (ViewArrangement.BottomResizable));
- Assert.True (arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.True (arrangement.HasFlag (ViewArrangement.RightResizable));
- }
- [Fact]
- public void ViewArrangement_OverlappedWithMovableAndResizable_AllFlagsWork ()
- {
- ViewArrangement arrangement = ViewArrangement.Overlapped | ViewArrangement.Movable | ViewArrangement.Resizable;
- Assert.True (arrangement.HasFlag (ViewArrangement.Overlapped));
- Assert.True (arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (arrangement.HasFlag (ViewArrangement.Resizable));
- }
- [Fact]
- public void View_Arrangement_CanBeSetToCompositeFlagValue ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Movable | ViewArrangement.Resizable | ViewArrangement.Overlapped
- };
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Movable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Resizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.Overlapped));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- }
- #endregion
- #region View Arrangement Edge Cases
- [Fact]
- public void View_ArrangementWithNoBorder_CanStillHaveArrangementValue ()
- {
- // A view can have Arrangement set even if BorderStyle is None
- var view = new View
- {
- Arrangement = ViewArrangement.Movable | ViewArrangement.Resizable,
- BorderStyle = LineStyle.None
- };
- // Border exists but has no visible style
- Assert.NotNull (view.Border);
- Assert.Equal (LineStyle.None, view.BorderStyle);
- Assert.Equal (ViewArrangement.Movable | ViewArrangement.Resizable, view.Arrangement);
- }
- [Fact]
- public void View_ChangingBorderStyle_PreservesArrangement ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Movable,
- BorderStyle = LineStyle.Single
- };
- Assert.NotNull (view.Border);
- Assert.Equal (ViewArrangement.Movable, view.Arrangement);
- // Change border style
- view.BorderStyle = LineStyle.Double;
- Assert.NotNull (view.Border);
- Assert.Equal (ViewArrangement.Movable, view.Arrangement);
- }
- [Fact]
- public void View_ChangingToNoBorderStyle_PreservesArrangement ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.Movable,
- BorderStyle = LineStyle.Single
- };
- Assert.NotNull (view.Border);
- Assert.Equal (LineStyle.Single, view.BorderStyle);
- // Change to no border style
- view.BorderStyle = LineStyle.None;
- // Border still exists but has no visible style
- Assert.NotNull (view.Border);
- Assert.Equal (LineStyle.None, view.BorderStyle);
- Assert.Equal (ViewArrangement.Movable, view.Arrangement); // Arrangement value is preserved
- }
- [Fact]
- public void View_MultipleSubviewsWithDifferentArrangements_EachIndependent ()
- {
- var container = new View ();
-
- var fixedView = new View { Id = "fixed", Arrangement = ViewArrangement.Fixed };
- var movableView = new View { Id = "movable", Arrangement = ViewArrangement.Movable };
- var resizableView = new View { Id = "resizable", Arrangement = ViewArrangement.Resizable };
- var overlappedView = new View { Id = "overlapped", Arrangement = ViewArrangement.Overlapped };
- container.Add (fixedView, movableView, resizableView, overlappedView);
- Assert.Equal (ViewArrangement.Fixed, fixedView.Arrangement);
- Assert.Equal (ViewArrangement.Movable, movableView.Arrangement);
- Assert.Equal (ViewArrangement.Resizable, resizableView.Arrangement);
- Assert.Equal (ViewArrangement.Overlapped, overlappedView.Arrangement);
- }
- #endregion
- #region Overlapped Layout Advanced Tests
- [Fact]
- public void Overlapped_ViewCanBeMovedToFront ()
- {
- var container = new View { Arrangement = ViewArrangement.Overlapped };
-
- var view1 = new View { Id = "view1" };
- var view2 = new View { Id = "view2" };
- var view3 = new View { Id = "view3" };
- container.Add (view1, view2, view3);
- // Initially view3 is on top (last added)
- Assert.Equal (view3, container.SubViews.ToArray () [^1]);
- // Move view1 to end (top of Z-order)
- container.MoveSubViewToEnd (view1);
- Assert.Equal (view1, container.SubViews.ToArray () [^1]);
- Assert.Equal ([view2, view3, view1], container.SubViews.ToArray ());
- }
- [Fact]
- public void Overlapped_ViewCanBeMovedToBack ()
- {
- var container = new View { Arrangement = ViewArrangement.Overlapped };
-
- var view1 = new View { Id = "view1" };
- var view2 = new View { Id = "view2" };
- var view3 = new View { Id = "view3" };
- container.Add (view1, view2, view3);
- // Initial order: [view1, view2, view3]
- Assert.Equal ([view1, view2, view3], container.SubViews.ToArray ());
-
- // Move view3 to end (top of Z-order)
- container.MoveSubViewToEnd (view3);
- Assert.Equal (view3, container.SubViews.ToArray () [^1]);
- Assert.Equal ([view1, view2, view3], container.SubViews.ToArray ());
-
- // Now move view1 to end (making it on top, pushing view3 down)
- container.MoveSubViewToEnd (view1);
- Assert.Equal ([view2, view3, view1], container.SubViews.ToArray ());
- }
- [Fact]
- public void Fixed_ViewAddOrderMattersForLayout ()
- {
- var container = new View { Arrangement = ViewArrangement.Fixed };
-
- var view1 = new View { Id = "view1", X = 0, Y = 0, Width = 10, Height = 5 };
- var view2 = new View { Id = "view2", X = 5, Y = 2, Width = 10, Height = 5 };
- container.Add (view1, view2);
- // In Fixed arrangement, views don't overlap in the same way
- // The order determines paint/draw order but not logical overlap
- Assert.Equal (view1, container.SubViews.ToArray () [0]);
- Assert.Equal (view2, container.SubViews.ToArray () [1]);
- }
- #endregion
- #region Resizable Edge Cases
- [Fact]
- public void Border_OnlyLeftResizable_OtherDirectionsNotResizable ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.LeftResizable,
- BorderStyle = LineStyle.Single
- };
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- }
- [Fact]
- public void Border_TwoOppositeDirections_CanBeResizable ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.LeftResizable | ViewArrangement.RightResizable,
- BorderStyle = LineStyle.Single
- };
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- }
- [Fact]
- public void Border_ThreeDirections_CanBeResizable ()
- {
- var view = new View
- {
- Arrangement = ViewArrangement.LeftResizable | ViewArrangement.RightResizable | ViewArrangement.BottomResizable,
- BorderStyle = LineStyle.Single
- };
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.LeftResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.RightResizable));
- Assert.False (view.Arrangement.HasFlag (ViewArrangement.TopResizable));
- Assert.True (view.Arrangement.HasFlag (ViewArrangement.BottomResizable));
- }
- #endregion
- }
|