using System; using System.Linq; using Terminal.Gui; using Terminal.Gui.Graphs; using Xunit; using Xunit.Abstractions; namespace UnitTests { public class TileViewTests { readonly ITestOutputHelper output; public TileViewTests (ITestOutputHelper output) { this.output = output; } [Fact, AutoInitShutdown] public void TestTileView_Vertical () { var tileView = Get11By3TileView (out var line); tileView.Redraw (tileView.Bounds); string looksLike = @" 11111│22222 11111│22222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); // Keyboard movement on splitter should have no effect if it is not focused line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_Vertical_WithBorder () { var tileView = Get11By3TileView (out var line, true); tileView.Redraw (tileView.Bounds); string looksLike = @" ┌────┬────┐ │1111│2222│ └────┴────┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); // Keyboard movement on splitter should have no effect if it is not focused line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_Vertical_Focused () { var tileView = Get11By3TileView (out var line); SetInputFocusLine (tileView); tileView.Redraw (tileView.Bounds); string looksLike = @" 11111│22222 11111◊22222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); // Now while focused move the splitter 1 unit right line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); tileView.Redraw (tileView.Bounds); looksLike = @" 111111│2222 111111◊2222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); // and 2 to the left line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); tileView.Redraw (tileView.Bounds); looksLike = @" 1111│222222 1111◊222222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_Vertical_Focused_WithBorder () { var tileView = Get11By3TileView (out var line, true); SetInputFocusLine (tileView); tileView.Redraw (tileView.Bounds); string looksLike = @" ┌────┬────┐ │1111◊2222│ └────┴────┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); // Now while focused move the splitter 1 unit right line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); tileView.Redraw (tileView.Bounds); looksLike = @" ┌─────┬───┐ │11111◊222│ └─────┴───┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); // and 2 to the left line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); tileView.Redraw (tileView.Bounds); looksLike = @" ┌───┬─────┐ │111◊22222│ └───┴─────┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_Vertical_Focused_50PercentSplit () { var tileView = Get11By3TileView (out var line); SetInputFocusLine (tileView); tileView.SetSplitterPos (0, Pos.Percent (50)); Assert.IsType (tileView.SplitterDistances.ElementAt (0)); tileView.Redraw (tileView.Bounds); string looksLike = @" 11111│22222 11111◊22222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); // Now while focused move the splitter 1 unit right line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); tileView.Redraw (tileView.Bounds); looksLike = @" 111111│2222 111111◊2222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); // Even when moving the splitter location it should stay a Percentage based one Assert.IsType (tileView.SplitterDistances.ElementAt (0)); // and 2 to the left line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); tileView.Redraw (tileView.Bounds); looksLike = @" 1111│222222 1111◊222222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); // Even when moving the splitter location it should stay a Percentage based one Assert.IsType (tileView.SplitterDistances.ElementAt (0)); } [Fact, AutoInitShutdown] public void TestTileView_Horizontal () { var tileView = Get11By3TileView (out var line); tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal; tileView.Redraw (tileView.Bounds); string looksLike = @" 11111111111 ─────────── 22222222222"; TestHelpers.AssertDriverContentsAre (looksLike, output); // Keyboard movement on splitter should have no effect if it is not focused line.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_Vertical_View1MinSize_Absolute () { var tileView = Get11By3TileView (out var line); SetInputFocusLine (tileView); tileView.Tiles.ElementAt (0).MinSize = 6; // distance is too small (below 6) Assert.False(tileView.SetSplitterPos (0, 2)); // Should stay where it was originally at (50%) Assert.Equal (Pos.Percent(50), tileView.SplitterDistances.ElementAt (0)); tileView.Redraw (tileView.Bounds); // so should ignore the 2 distance and stick to 6 string looksLike = @" 11111│22222 11111◊22222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); // Keyboard movement on splitter should have no effect because it // would take us below the minimum splitter size line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); TestHelpers.AssertDriverContentsAre (looksLike, output); // but we can continue to move the splitter right if we want line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); looksLike = @" 111111│2222 111111◊2222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_Vertical_View1MinSize_Absolute_WithBorder () { var tileView = Get11By3TileView (out var line, true); SetInputFocusLine (tileView); tileView.Tiles.ElementAt (0).MinSize = 5; // distance is too small (below 5) Assert.False(tileView.SetSplitterPos (0, 2)); // Should stay where it was originally at (50%) Assert.Equal (Pos.Percent(50), tileView.SplitterDistances.ElementAt (0)); tileView.Redraw (tileView.Bounds); // so should ignore the 2 distance and stick to 5 string looksLike = @" ┌────┬────┐ │1111◊2222│ └────┴────┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); // Keyboard movement on splitter should have no effect because it // would take us below the minimum splitter size line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); TestHelpers.AssertDriverContentsAre (looksLike, output); // but we can continue to move the splitter right if we want line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); looksLike = @" ┌─────┬───┐ │11111◊222│ └─────┴───┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_Vertical_View2MinSize_Absolute () { var tileView = Get11By3TileView (out var line); SetInputFocusLine (tileView); tileView.Tiles.ElementAt (1).MinSize = 6; // distance leaves too little space for view2 (less than 6 would remain) Assert.False(tileView.SetSplitterPos (0, 8)); // Should stay where it was originally at (50%) Assert.Equal (Pos.Percent(50), tileView.SplitterDistances.ElementAt (0)); tileView.Redraw (tileView.Bounds); // so should ignore the 2 distance and stick to 6 string looksLike = @" 11111│22222 11111◊22222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); // Keyboard movement on splitter should have no effect because it // would take us below the minimum splitter size line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); TestHelpers.AssertDriverContentsAre (looksLike, output); // but we can continue to move the splitter left if we want line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); looksLike = @" 1111│222222 1111◊222222 │ "; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_Vertical_View2MinSize_Absolute_WithBorder () { var tileView = Get11By3TileView (out var line, true); SetInputFocusLine (tileView); tileView.Tiles.ElementAt (1).MinSize = 5; // distance leaves too little space for view2 (less than 5 would remain) Assert.False(tileView.SetSplitterPos (0, 8)); // Should stay where it was originally at (50%) Assert.Equal (Pos.Percent(50), tileView.SplitterDistances.ElementAt (0)); tileView.Redraw (tileView.Bounds); // so should ignore the 2 distance and stick to 6 string looksLike = @" ┌────┬────┐ │1111◊2222│ └────┴────┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); // Keyboard movement on splitter should have no effect because it // would take us below the minimum splitter size line.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); TestHelpers.AssertDriverContentsAre (looksLike, output); // but we can continue to move the splitter left if we want line.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())); tileView.SetNeedsDisplay (); tileView.Redraw (tileView.Bounds); looksLike = @" ┌───┬─────┐ │111◊22222│ └───┴─────┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_InsertPanelAtStart () { var tileView = Get11By3TileView (out var line, true); SetInputFocusLine (tileView); tileView.InsertTile (0); tileView.Redraw (tileView.Bounds); // so should ignore the 2 distance and stick to 6 string looksLike = @" ┌──┬───┬──┐ │ │111│22│ └──┴───┴──┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_InsertPanelMiddle () { var tileView = Get11By3TileView (out var line, true); SetInputFocusLine (tileView); tileView.InsertTile (1); tileView.Redraw (tileView.Bounds); // so should ignore the 2 distance and stick to 6 string looksLike = @" ┌──┬───┬──┐ │11│ │22│ └──┴───┴──┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_InsertPanelAtEnd () { var tileView = Get11By3TileView (out var line, true); SetInputFocusLine (tileView); tileView.InsertTile (2); tileView.Redraw (tileView.Bounds); // so should ignore the 2 distance and stick to 6 string looksLike = @" ┌──┬───┬──┐ │11│222│ │ └──┴───┴──┘"; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_Horizontal_Focused () { var tileView = Get11By3TileView (out var line); tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal; SetInputFocusLine (tileView); tileView.Redraw (tileView.Bounds); string looksLike = @" 11111111111 ─────◊───── 22222222222"; TestHelpers.AssertDriverContentsAre (looksLike, output); // Now move splitter line down line.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())); tileView.Redraw (tileView.Bounds); looksLike = @" 11111111111 11111111111 ─────◊─────"; TestHelpers.AssertDriverContentsAre (looksLike, output); // And 2 up line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())); line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())); tileView.Redraw (tileView.Bounds); looksLike = @" ─────◊───── 22222222222 22222222222"; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_Horizontal_View1MinSize_Absolute () { var tileView = Get11By3TileView (out var line); tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal; SetInputFocusLine (tileView); tileView.Tiles.ElementAt (0).MinSize = 1; // 0 should not be allowed because it brings us below minimum size of View1 Assert.False(tileView.SetSplitterPos (0, 0)); // position should remain where it was, at 50% Assert.Equal (Pos.Percent(50f), tileView.SplitterDistances.ElementAt (0)); tileView.Redraw (tileView.Bounds); string looksLike = @" 11111111111 ─────◊───── 22222222222"; TestHelpers.AssertDriverContentsAre (looksLike, output); // Now move splitter line down (allowed line.ProcessKey (new KeyEvent (Key.CursorDown, new KeyModifiers ())); tileView.Redraw (tileView.Bounds); looksLike = @" 11111111111 11111111111 ─────◊─────"; TestHelpers.AssertDriverContentsAre (looksLike, output); // And up 2 (only 1 is allowed because of minimum size of 1 on view1) line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())); line.ProcessKey (new KeyEvent (Key.CursorUp, new KeyModifiers ())); tileView.Redraw (tileView.Bounds); looksLike = @" 11111111111 ─────◊───── 22222222222"; TestHelpers.AssertDriverContentsAre (looksLike, output); } [Fact, AutoInitShutdown] public void TestTileView_CannotSetSplitterPosToFuncEtc () { var tileView = Get11By3TileView (); var ex = Assert.Throws (() => tileView.SetSplitterPos (0, Pos.Right (tileView))); Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosCombine", ex.Message); ex = Assert.Throws (() => tileView.SetSplitterPos (0, Pos.Function (() => 1))); Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosFunc", ex.Message); // Also not allowed because this results in a PosCombine ex = Assert.Throws (() => tileView.SetSplitterPos (0, Pos.Percent (50) - 1)); Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosCombine", ex.Message); } [Fact, AutoInitShutdown] public void TestNestedContainer2LeftAnd1Right_RendersNicely () { var tileView = GetNestedContainer2Left1Right (false); Assert.Equal (20, tileView.Frame.Width); Assert.Equal (10, tileView.Tiles.ElementAt (0).View.Frame.Width); Assert.Equal (9, tileView.Tiles.ElementAt (1).View.Frame.Width); Assert.IsType (tileView.Tiles.ElementAt (0).View); var left = (TileView)tileView.Tiles.ElementAt (0).View; Assert.Same (left.SuperView, tileView); Assert.Equal (2, left.Tiles.ElementAt (0).View.Subviews.Count); Assert.IsType