mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
first unit tests
This commit is contained in:
1661
Terminal.Gui/ConsoleDrivers/MockDriver/MockConsole.cs
Normal file
1661
Terminal.Gui/ConsoleDrivers/MockDriver/MockConsole.cs
Normal file
File diff suppressed because it is too large
Load Diff
440
Terminal.Gui/ConsoleDrivers/MockDriver/MockDriver.cs
Normal file
440
Terminal.Gui/ConsoleDrivers/MockDriver/MockDriver.cs
Normal file
@@ -0,0 +1,440 @@
|
||||
//
|
||||
// MockDriver.cs: A mock ConsoleDriver for unit tests.
|
||||
//
|
||||
// Authors:
|
||||
// Charlie Kindel (github.com/tig)
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using NStack;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
public class MockDriver : ConsoleDriver, IMainLoopDriver {
|
||||
int cols, rows;
|
||||
public override int Cols => cols;
|
||||
public override int Rows => rows;
|
||||
|
||||
// The format is rows, columns and 3 values on the last column: Rune, Attribute and Dirty Flag
|
||||
int [,,] contents;
|
||||
bool [] dirtyLine;
|
||||
|
||||
void UpdateOffscreen ()
|
||||
{
|
||||
int cols = Cols;
|
||||
int rows = Rows;
|
||||
|
||||
contents = new int [rows, cols, 3];
|
||||
for (int r = 0; r < rows; r++) {
|
||||
for (int c = 0; c < cols; c++) {
|
||||
contents [r, c, 0] = ' ';
|
||||
contents [r, c, 1] = MakeColor (ConsoleColor.Gray, ConsoleColor.Black);
|
||||
contents [r, c, 2] = 0;
|
||||
}
|
||||
}
|
||||
dirtyLine = new bool [rows];
|
||||
for (int row = 0; row < rows; row++)
|
||||
dirtyLine [row] = true;
|
||||
}
|
||||
|
||||
static bool sync = false;
|
||||
|
||||
public MockDriver ()
|
||||
{
|
||||
cols = MockConsole.WindowWidth;
|
||||
rows = MockConsole.WindowHeight; // - 1;
|
||||
UpdateOffscreen ();
|
||||
}
|
||||
|
||||
bool needMove;
|
||||
// Current row, and current col, tracked by Move/AddCh only
|
||||
int ccol, crow;
|
||||
public override void Move (int col, int row)
|
||||
{
|
||||
ccol = col;
|
||||
crow = row;
|
||||
|
||||
if (Clip.Contains (col, row)) {
|
||||
MockConsole.CursorTop = row;
|
||||
MockConsole.CursorLeft = col;
|
||||
needMove = false;
|
||||
} else {
|
||||
MockConsole.CursorTop = Clip.Y;
|
||||
MockConsole.CursorLeft = Clip.X;
|
||||
needMove = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void AddRune (Rune rune)
|
||||
{
|
||||
if (Clip.Contains (ccol, crow)) {
|
||||
if (needMove) {
|
||||
//MockConsole.CursorLeft = ccol;
|
||||
//MockConsole.CursorTop = crow;
|
||||
needMove = false;
|
||||
}
|
||||
contents [crow, ccol, 0] = (int)(uint)rune;
|
||||
contents [crow, ccol, 1] = currentAttribute;
|
||||
contents [crow, ccol, 2] = 1;
|
||||
dirtyLine [crow] = true;
|
||||
} else
|
||||
needMove = true;
|
||||
ccol++;
|
||||
//if (ccol == Cols) {
|
||||
// ccol = 0;
|
||||
// if (crow + 1 < Rows)
|
||||
// crow++;
|
||||
//}
|
||||
if (sync)
|
||||
UpdateScreen ();
|
||||
}
|
||||
|
||||
public override void AddStr (ustring str)
|
||||
{
|
||||
foreach (var rune in str)
|
||||
AddRune (rune);
|
||||
}
|
||||
|
||||
public override void End ()
|
||||
{
|
||||
MockConsole.ResetColor ();
|
||||
MockConsole.Clear ();
|
||||
}
|
||||
|
||||
static Attribute MakeColor (ConsoleColor f, ConsoleColor b)
|
||||
{
|
||||
// Encode the colors into the int value.
|
||||
return new Attribute () { value = ((((int)f) & 0xffff) << 16) | (((int)b) & 0xffff) };
|
||||
}
|
||||
|
||||
|
||||
public override void Init (Action terminalResized)
|
||||
{
|
||||
Colors.TopLevel = new ColorScheme ();
|
||||
Colors.Base = new ColorScheme ();
|
||||
Colors.Dialog = new ColorScheme ();
|
||||
Colors.Menu = new ColorScheme ();
|
||||
Colors.Error = new ColorScheme ();
|
||||
Clip = new Rect (0, 0, Cols, Rows);
|
||||
|
||||
Colors.TopLevel.Normal = MakeColor (ConsoleColor.Green, ConsoleColor.Black);
|
||||
Colors.TopLevel.Focus = MakeColor (ConsoleColor.White, ConsoleColor.DarkCyan);
|
||||
Colors.TopLevel.HotNormal = MakeColor (ConsoleColor.DarkYellow, ConsoleColor.Black);
|
||||
Colors.TopLevel.HotFocus = MakeColor (ConsoleColor.DarkBlue, ConsoleColor.DarkCyan);
|
||||
|
||||
Colors.Base.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Blue);
|
||||
Colors.Base.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Cyan);
|
||||
Colors.Base.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Blue);
|
||||
Colors.Base.HotFocus = MakeColor (ConsoleColor.Yellow, ConsoleColor.Cyan);
|
||||
|
||||
// Focused,
|
||||
// Selected, Hot: Yellow on Black
|
||||
// Selected, text: white on black
|
||||
// Unselected, hot: yellow on cyan
|
||||
// unselected, text: same as unfocused
|
||||
Colors.Menu.HotFocus = MakeColor (ConsoleColor.Yellow, ConsoleColor.Black);
|
||||
Colors.Menu.Focus = MakeColor (ConsoleColor.White, ConsoleColor.Black);
|
||||
Colors.Menu.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Cyan);
|
||||
Colors.Menu.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Cyan);
|
||||
Colors.Menu.Disabled = MakeColor (ConsoleColor.DarkGray, ConsoleColor.Cyan);
|
||||
|
||||
Colors.Dialog.Normal = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
|
||||
Colors.Dialog.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Cyan);
|
||||
Colors.Dialog.HotNormal = MakeColor (ConsoleColor.Blue, ConsoleColor.Gray);
|
||||
Colors.Dialog.HotFocus = MakeColor (ConsoleColor.Blue, ConsoleColor.Cyan);
|
||||
|
||||
Colors.Error.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Red);
|
||||
Colors.Error.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
|
||||
Colors.Error.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Red);
|
||||
Colors.Error.HotFocus = Colors.Error.HotNormal;
|
||||
|
||||
HLine = '\u2500';
|
||||
VLine = '\u2502';
|
||||
Stipple = '\u2592';
|
||||
Diamond = '\u25c6';
|
||||
ULCorner = '\u250C';
|
||||
LLCorner = '\u2514';
|
||||
URCorner = '\u2510';
|
||||
LRCorner = '\u2518';
|
||||
LeftTee = '\u251c';
|
||||
RightTee = '\u2524';
|
||||
TopTee = '\u22a4';
|
||||
BottomTee = '\u22a5';
|
||||
Checked = '\u221a';
|
||||
UnChecked = ' ';
|
||||
Selected = '\u25cf';
|
||||
UnSelected = '\u25cc';
|
||||
RightArrow = '\u25ba';
|
||||
LeftArrow = '\u25c4';
|
||||
UpArrow = '\u25b2';
|
||||
DownArrow = '\u25bc';
|
||||
LeftDefaultIndicator = '\u25e6';
|
||||
RightDefaultIndicator = '\u25e6';
|
||||
LeftBracket = '[';
|
||||
RightBracket = ']';
|
||||
OnMeterSegment = '\u258c';
|
||||
OffMeterSegement = ' ';
|
||||
|
||||
//MockConsole.Clear ();
|
||||
}
|
||||
|
||||
public override Attribute MakeAttribute (Color fore, Color back)
|
||||
{
|
||||
return MakeColor ((ConsoleColor)fore, (ConsoleColor)back);
|
||||
}
|
||||
|
||||
int redrawColor = -1;
|
||||
void SetColor (int color)
|
||||
{
|
||||
redrawColor = color;
|
||||
IEnumerable<int> values = Enum.GetValues (typeof (ConsoleColor))
|
||||
.OfType<ConsoleColor> ()
|
||||
.Select (s => (int)s);
|
||||
if (values.Contains (color & 0xffff)) {
|
||||
MockConsole.BackgroundColor = (ConsoleColor)(color & 0xffff);
|
||||
}
|
||||
if (values.Contains ((color >> 16) & 0xffff)) {
|
||||
MockConsole.ForegroundColor = (ConsoleColor)((color >> 16) & 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateScreen ()
|
||||
{
|
||||
int rows = Rows;
|
||||
int cols = Cols;
|
||||
|
||||
MockConsole.CursorTop = 0;
|
||||
MockConsole.CursorLeft = 0;
|
||||
for (int row = 0; row < rows; row++) {
|
||||
dirtyLine [row] = false;
|
||||
for (int col = 0; col < cols; col++) {
|
||||
contents [row, col, 2] = 0;
|
||||
var color = contents [row, col, 1];
|
||||
if (color != redrawColor)
|
||||
SetColor (color);
|
||||
MockConsole.Write ((char)contents [row, col, 0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Refresh ()
|
||||
{
|
||||
int rows = Rows;
|
||||
int cols = Cols;
|
||||
|
||||
var savedRow = MockConsole.CursorTop;
|
||||
var savedCol = MockConsole.CursorLeft;
|
||||
for (int row = 0; row < rows; row++) {
|
||||
if (!dirtyLine [row])
|
||||
continue;
|
||||
dirtyLine [row] = false;
|
||||
for (int col = 0; col < cols; col++) {
|
||||
if (contents [row, col, 2] != 1)
|
||||
continue;
|
||||
|
||||
MockConsole.CursorTop = row;
|
||||
MockConsole.CursorLeft = col;
|
||||
for (; col < cols && contents [row, col, 2] == 1; col++) {
|
||||
var color = contents [row, col, 1];
|
||||
if (color != redrawColor)
|
||||
SetColor (color);
|
||||
|
||||
MockConsole.Write ((char)contents [row, col, 0]);
|
||||
contents [row, col, 2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
MockConsole.CursorTop = savedRow;
|
||||
MockConsole.CursorLeft = savedCol;
|
||||
}
|
||||
|
||||
public override void UpdateCursor ()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public override void StartReportingMouseMoves ()
|
||||
{
|
||||
}
|
||||
|
||||
public override void StopReportingMouseMoves ()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Suspend ()
|
||||
{
|
||||
}
|
||||
|
||||
int currentAttribute;
|
||||
public override void SetAttribute (Attribute c)
|
||||
{
|
||||
currentAttribute = c.value;
|
||||
}
|
||||
|
||||
Key MapKey (ConsoleKeyInfo keyInfo)
|
||||
{
|
||||
switch (keyInfo.Key) {
|
||||
case ConsoleKey.Escape:
|
||||
return Key.Esc;
|
||||
case ConsoleKey.Tab:
|
||||
return keyInfo.Modifiers == ConsoleModifiers.Shift ? Key.BackTab : Key.Tab;
|
||||
case ConsoleKey.Home:
|
||||
return Key.Home;
|
||||
case ConsoleKey.End:
|
||||
return Key.End;
|
||||
case ConsoleKey.LeftArrow:
|
||||
return Key.CursorLeft;
|
||||
case ConsoleKey.RightArrow:
|
||||
return Key.CursorRight;
|
||||
case ConsoleKey.UpArrow:
|
||||
return Key.CursorUp;
|
||||
case ConsoleKey.DownArrow:
|
||||
return Key.CursorDown;
|
||||
case ConsoleKey.PageUp:
|
||||
return Key.PageUp;
|
||||
case ConsoleKey.PageDown:
|
||||
return Key.PageDown;
|
||||
case ConsoleKey.Enter:
|
||||
return Key.Enter;
|
||||
case ConsoleKey.Spacebar:
|
||||
return Key.Space;
|
||||
case ConsoleKey.Backspace:
|
||||
return Key.Backspace;
|
||||
case ConsoleKey.Delete:
|
||||
return Key.Delete;
|
||||
|
||||
case ConsoleKey.Oem1:
|
||||
case ConsoleKey.Oem2:
|
||||
case ConsoleKey.Oem3:
|
||||
case ConsoleKey.Oem4:
|
||||
case ConsoleKey.Oem5:
|
||||
case ConsoleKey.Oem6:
|
||||
case ConsoleKey.Oem7:
|
||||
case ConsoleKey.Oem8:
|
||||
case ConsoleKey.Oem102:
|
||||
case ConsoleKey.OemPeriod:
|
||||
case ConsoleKey.OemComma:
|
||||
case ConsoleKey.OemPlus:
|
||||
case ConsoleKey.OemMinus:
|
||||
return (Key)((uint)keyInfo.KeyChar);
|
||||
}
|
||||
|
||||
var key = keyInfo.Key;
|
||||
if (key >= ConsoleKey.A && key <= ConsoleKey.Z) {
|
||||
var delta = key - ConsoleKey.A;
|
||||
if (keyInfo.Modifiers == ConsoleModifiers.Control)
|
||||
return (Key)((uint)Key.ControlA + delta);
|
||||
if (keyInfo.Modifiers == ConsoleModifiers.Alt)
|
||||
return (Key)(((uint)Key.AltMask) | ((uint)'A' + delta));
|
||||
if (keyInfo.Modifiers == ConsoleModifiers.Shift)
|
||||
return (Key)((uint)'A' + delta);
|
||||
else
|
||||
return (Key)((uint)'a' + delta);
|
||||
}
|
||||
if (key >= ConsoleKey.D0 && key <= ConsoleKey.D9) {
|
||||
var delta = key - ConsoleKey.D0;
|
||||
if (keyInfo.Modifiers == ConsoleModifiers.Alt)
|
||||
return (Key)(((uint)Key.AltMask) | ((uint)'0' + delta));
|
||||
if (keyInfo.Modifiers == ConsoleModifiers.Shift)
|
||||
return (Key)((uint)keyInfo.KeyChar);
|
||||
return (Key)((uint)'0' + delta);
|
||||
}
|
||||
if (key >= ConsoleKey.F1 && key <= ConsoleKey.F10) {
|
||||
var delta = key - ConsoleKey.F1;
|
||||
|
||||
return (Key)((int)Key.F1 + delta);
|
||||
}
|
||||
return (Key)(0xffffffff);
|
||||
}
|
||||
|
||||
KeyModifiers keyModifiers = new KeyModifiers ();
|
||||
|
||||
public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
|
||||
{
|
||||
// Note: Net doesn't support keydown/up events and thus any passed keyDown/UpHandlers will never be called
|
||||
(mainLoop.Driver as MockDriver).WindowsKeyPressed = delegate (ConsoleKeyInfo consoleKey) {
|
||||
var map = MapKey (consoleKey);
|
||||
if (map == (Key)0xffffffff)
|
||||
return;
|
||||
keyHandler (new KeyEvent (map, keyModifiers));
|
||||
keyUpHandler (new KeyEvent (map, keyModifiers));
|
||||
};
|
||||
}
|
||||
|
||||
public override void SetColors (ConsoleColor foreground, ConsoleColor background)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
public override void SetColors (short foregroundColorId, short backgroundColorId)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
public override void CookMouse ()
|
||||
{
|
||||
}
|
||||
|
||||
public override void UncookMouse ()
|
||||
{
|
||||
}
|
||||
|
||||
AutoResetEvent keyReady = new AutoResetEvent (false);
|
||||
AutoResetEvent waitForProbe = new AutoResetEvent (false);
|
||||
ConsoleKeyInfo? windowsKeyResult = null;
|
||||
public Action<ConsoleKeyInfo> WindowsKeyPressed;
|
||||
MainLoop mainLoop;
|
||||
|
||||
void WindowsKeyReader ()
|
||||
{
|
||||
while (true) {
|
||||
waitForProbe.WaitOne ();
|
||||
windowsKeyResult = MockConsole.ReadKey (true);
|
||||
keyReady.Set ();
|
||||
}
|
||||
}
|
||||
|
||||
void IMainLoopDriver.Setup (MainLoop mainLoop)
|
||||
{
|
||||
this.mainLoop = mainLoop;
|
||||
Thread readThread = new Thread (WindowsKeyReader);
|
||||
readThread.Start ();
|
||||
}
|
||||
|
||||
void IMainLoopDriver.Wakeup ()
|
||||
{
|
||||
}
|
||||
|
||||
bool IMainLoopDriver.EventsPending (bool wait)
|
||||
{
|
||||
long now = DateTime.UtcNow.Ticks;
|
||||
|
||||
int waitTimeout;
|
||||
if (mainLoop.timeouts.Count > 0) {
|
||||
waitTimeout = (int)((mainLoop.timeouts.Keys [0] - now) / TimeSpan.TicksPerMillisecond);
|
||||
if (waitTimeout < 0)
|
||||
return true;
|
||||
} else
|
||||
waitTimeout = -1;
|
||||
|
||||
if (!wait)
|
||||
waitTimeout = 0;
|
||||
|
||||
windowsKeyResult = null;
|
||||
waitForProbe.Set ();
|
||||
keyReady.WaitOne (waitTimeout);
|
||||
return windowsKeyResult.HasValue;
|
||||
}
|
||||
|
||||
void IMainLoopDriver.MainIteration ()
|
||||
{
|
||||
if (windowsKeyResult.HasValue) {
|
||||
if (WindowsKeyPressed != null)
|
||||
WindowsKeyPressed (windowsKeyResult.Value);
|
||||
windowsKeyResult = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -157,21 +157,28 @@ namespace Terminal.Gui {
|
||||
/// Creates a <see cref="Toplevel"/> and assigns it to <see cref="Top"/> and <see cref="CurrentView"/>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static void Init () => Init (() => Toplevel.Create ());
|
||||
public static void Init (ConsoleDriver driver = null) => Init (() => Toplevel.Create (), driver);
|
||||
|
||||
internal static bool _initialized = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Terminal.Gui application
|
||||
/// </summary>
|
||||
static void Init (Func<Toplevel> topLevelFactory)
|
||||
static void Init (Func<Toplevel> topLevelFactory, ConsoleDriver driver = null)
|
||||
{
|
||||
if (_initialized) return;
|
||||
|
||||
// This supports Unit Tests and the passing of a mock driver/loopdriver
|
||||
if (driver != null) {
|
||||
Driver = driver;
|
||||
Driver.Init (TerminalResized);
|
||||
MainLoop = new MainLoop ((IMainLoopDriver)driver);
|
||||
SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext (MainLoop));
|
||||
}
|
||||
|
||||
if (Driver == null) {
|
||||
var p = Environment.OSVersion.Platform;
|
||||
IMainLoopDriver mainLoopDriver;
|
||||
|
||||
if (UseSystemConsole) {
|
||||
mainLoopDriver = new NetMainLoop ();
|
||||
Driver = new NetDriver ();
|
||||
@@ -199,7 +206,11 @@ namespace Terminal.Gui {
|
||||
public class RunState : IDisposable {
|
||||
internal bool closeDriver = true;
|
||||
|
||||
internal RunState (Toplevel view)
|
||||
/// <summary>
|
||||
/// Initializes a new <see cref="RunState"/> class.
|
||||
/// </summary>
|
||||
/// <param name="view"></param>
|
||||
public RunState (Toplevel view)
|
||||
{
|
||||
Toplevel = view;
|
||||
}
|
||||
@@ -476,7 +487,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shutdown an application initialized with <see cref="Init()"/>
|
||||
/// Shutdown an application initialized with <see cref="Init(ConsoleDriver)"/>
|
||||
/// </summary>
|
||||
/// /// <param name="closeDriver"><c>true</c>Closes the application.<c>false</c>Closes toplevels only.</param>
|
||||
public static void Shutdown (bool closeDriver = true)
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Terminal.Gui {
|
||||
/// been called (which sets the <see cref="Toplevel.Running"/> property to false).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// A Toplevel is created when an application initialzies Terminal.Gui by callling <see cref="Application.Init()"/>.
|
||||
/// A Toplevel is created when an application initialzies Terminal.Gui by callling <see cref="Application.Init(ConsoleDriver)"/>.
|
||||
/// The application Toplevel can be accessed via <see cref="Application.Top"/>. Additional Toplevels can be created
|
||||
/// and run (e.g. <see cref="Dialog"/>s. To run a Toplevel, create the <see cref="Toplevel"/> and
|
||||
/// call <see cref="Application.Run(Toplevel, bool)"/>.
|
||||
|
||||
12
Terminal.sln
12
Terminal.sln
@@ -6,10 +6,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example", "Example\Example.
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Terminal.Gui", "Terminal.Gui\Terminal.Gui.csproj", "{00F366F8-DEE4-482C-B9FD-6DB0200B79E5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Designer", "Designer\Designer.csproj", "{1228D992-C801-49BB-839A-7BD28A3FFF0A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Designer", "Designer\Designer.csproj", "{1228D992-C801-49BB-839A-7BD28A3FFF0A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UICatalog", "UICatalog\UICatalog.csproj", "{88979F89-9A42-448F-AE3E-3060145F6375}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{8B901EDE-8974-4820-B100-5226917E2990}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -50,6 +52,14 @@ Global
|
||||
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8B901EDE-8974-4820-B100-5226917E2990}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8B901EDE-8974-4820-B100-5226917E2990}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8B901EDE-8974-4820-B100-5226917E2990}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8B901EDE-8974-4820-B100-5226917E2990}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8B901EDE-8974-4820-B100-5226917E2990}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8B901EDE-8974-4820-B100-5226917E2990}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8B901EDE-8974-4820-B100-5226917E2990}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8B901EDE-8974-4820-B100-5226917E2990}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
195
UnitTests/ApplicationTests.cs
Normal file
195
UnitTests/ApplicationTests.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Terminal.Gui;
|
||||
using Xunit;
|
||||
|
||||
// Alais Console to MockConsole so we don't accidentally use Console
|
||||
using Console = Terminal.Gui.MockConsole;
|
||||
|
||||
// Since Application is a singleton we can't run tests in parallel
|
||||
[assembly: CollectionBehavior (DisableTestParallelization = true)]
|
||||
|
||||
namespace Terminal.Gui {
|
||||
public class ApplicationTests {
|
||||
[Fact]
|
||||
public void TestInitShutdown ()
|
||||
{
|
||||
Assert.Null (Application.Current);
|
||||
Assert.Null (Application.CurrentView);
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MainLoop);
|
||||
Assert.Null (Application.Driver);
|
||||
|
||||
Application.Init (new MockDriver ());
|
||||
Assert.NotNull (Application.Current);
|
||||
Assert.NotNull (Application.CurrentView);
|
||||
Assert.NotNull (Application.Top);
|
||||
Assert.NotNull (Application.MainLoop);
|
||||
Assert.NotNull (Application.Driver);
|
||||
|
||||
// MockDriver is always 80x25
|
||||
Assert.Equal (80, Application.Driver.Cols);
|
||||
Assert.Equal (25, Application.Driver.Rows);
|
||||
|
||||
Application.Shutdown (true);
|
||||
Assert.Null (Application.Current);
|
||||
Assert.Null (Application.CurrentView);
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MainLoop);
|
||||
Assert.Null (Application.Driver);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestNewRunState ()
|
||||
{
|
||||
var rs = new Application.RunState (null);
|
||||
Assert.NotNull (rs);
|
||||
|
||||
// Should not throw because Toplevel was null
|
||||
rs.Dispose ();
|
||||
|
||||
var top = new Toplevel ();
|
||||
rs = new Application.RunState (top);
|
||||
Assert.NotNull (rs);
|
||||
|
||||
// Should throw because there's no stack
|
||||
Assert.Throws<InvalidOperationException> (() => rs.Dispose ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestBeginEnd ()
|
||||
{
|
||||
// Setup Mock driver
|
||||
Application.Init (new MockDriver ());
|
||||
Assert.NotNull (Application.Driver);
|
||||
|
||||
// Test null Toplevel
|
||||
Assert.Throws<ArgumentNullException> (() => Application.Begin (null));
|
||||
|
||||
var top = new Toplevel ();
|
||||
var rs = Application.Begin (top);
|
||||
Assert.NotNull (rs);
|
||||
Assert.Equal (top, Application.Current);
|
||||
Application.End (rs, true);
|
||||
|
||||
Assert.Null (Application.Current);
|
||||
Assert.Null (Application.CurrentView);
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MainLoop);
|
||||
Assert.Null (Application.Driver);
|
||||
|
||||
Application.Shutdown (true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestRequestStop ()
|
||||
{
|
||||
// Setup Mock driver
|
||||
Application.Init (new MockDriver ());
|
||||
Assert.NotNull (Application.Driver);
|
||||
|
||||
var top = new Toplevel ();
|
||||
var rs = Application.Begin (top);
|
||||
Assert.NotNull (rs);
|
||||
Assert.Equal (top, Application.Current);
|
||||
|
||||
Application.Iteration = () => {
|
||||
Application.RequestStop ();
|
||||
};
|
||||
|
||||
Application.Run (top, true);
|
||||
|
||||
Application.Shutdown (true);
|
||||
Assert.Null (Application.Current);
|
||||
Assert.Null (Application.CurrentView);
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MainLoop);
|
||||
Assert.Null (Application.Driver);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestRunningFalse ()
|
||||
{
|
||||
// Setup Mock driver
|
||||
Application.Init (new MockDriver ());
|
||||
Assert.NotNull (Application.Driver);
|
||||
|
||||
var top = new Toplevel ();
|
||||
var rs = Application.Begin (top);
|
||||
Assert.NotNull (rs);
|
||||
Assert.Equal (top, Application.Current);
|
||||
|
||||
Application.Iteration = () => {
|
||||
top.Running = false;
|
||||
};
|
||||
|
||||
Application.Run (top, true);
|
||||
|
||||
Application.Shutdown (true);
|
||||
Assert.Null (Application.Current);
|
||||
Assert.Null (Application.CurrentView);
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MainLoop);
|
||||
Assert.Null (Application.Driver);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void TestKeyUp ()
|
||||
{
|
||||
// Setup Mock driver
|
||||
Application.Init (new MockDriver ());
|
||||
Assert.NotNull (Application.Driver);
|
||||
|
||||
// Setup some fake kepresses (This)
|
||||
var input = "Tests";
|
||||
|
||||
// Put a control-q in at the end
|
||||
Console.MockKeyPresses.Push (new ConsoleKeyInfo ('q', ConsoleKey.Q, shift: false, alt: false, control: true));
|
||||
foreach (var c in input.Reverse()) {
|
||||
if (char.IsLetter (c)) {
|
||||
Console.MockKeyPresses.Push (new ConsoleKeyInfo (char.ToLower (c), (ConsoleKey)char.ToUpper (c), shift: char.IsUpper (c), alt: false, control: false));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.MockKeyPresses.Push (new ConsoleKeyInfo (c, (ConsoleKey)c, shift: false, alt: false, control: false));
|
||||
}
|
||||
}
|
||||
|
||||
int stackSize = Console.MockKeyPresses.Count;
|
||||
|
||||
int iterations = 0;
|
||||
Application.Iteration = () => {
|
||||
iterations++;
|
||||
};
|
||||
|
||||
int keyUps = 0;
|
||||
var output = string.Empty;
|
||||
Application.Top.KeyUp += (View.KeyEventEventArgs args) => {
|
||||
if (args.KeyEvent.Key != Key.ControlQ) {
|
||||
output += (char)args.KeyEvent.KeyValue;
|
||||
}
|
||||
keyUps++;
|
||||
};
|
||||
|
||||
Application.Run (Application.Top, true);
|
||||
|
||||
// Input string should match output
|
||||
Assert.Equal (input, output);
|
||||
|
||||
// # of key up events should match stack size
|
||||
Assert.Equal (stackSize, keyUps);
|
||||
|
||||
// # of key up events should match # of iterations
|
||||
Assert.Equal (stackSize, iterations);
|
||||
|
||||
Application.Shutdown (true);
|
||||
Assert.Null (Application.Current);
|
||||
Assert.Null (Application.CurrentView);
|
||||
Assert.Null (Application.Top);
|
||||
Assert.Null (Application.MainLoop);
|
||||
Assert.Null (Application.Driver);
|
||||
}
|
||||
}
|
||||
}
|
||||
67
UnitTests/ConsoleDriverTests.cs
Normal file
67
UnitTests/ConsoleDriverTests.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using Terminal.Gui;
|
||||
using Xunit;
|
||||
|
||||
// Alais Console to MockConsole so we don't accidentally use Console
|
||||
using Console = Terminal.Gui.MockConsole;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
public class ConsoleDriverTests {
|
||||
[Fact]
|
||||
public void TestInit ()
|
||||
{
|
||||
var driver = new MockDriver ();
|
||||
driver.Init (() => { });
|
||||
|
||||
Assert.Equal (80, Console.BufferWidth);
|
||||
Assert.Equal (25, Console.BufferHeight);
|
||||
|
||||
// MockDriver is always 80x25
|
||||
Assert.Equal (Console.BufferWidth, driver.Cols);
|
||||
Assert.Equal (Console.BufferHeight, driver.Rows);
|
||||
driver.End ();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestEnd ()
|
||||
{
|
||||
var driver = new MockDriver ();
|
||||
driver.Init (() => { });
|
||||
|
||||
MockConsole.ForegroundColor = ConsoleColor.Red;
|
||||
Assert.Equal (ConsoleColor.Red, Console.ForegroundColor);
|
||||
|
||||
MockConsole.BackgroundColor = ConsoleColor.Green;
|
||||
Assert.Equal (ConsoleColor.Green, Console.BackgroundColor);
|
||||
driver.Move (2, 3);
|
||||
Assert.Equal (2, Console.CursorLeft);
|
||||
Assert.Equal (3, Console.CursorTop);
|
||||
|
||||
driver.End ();
|
||||
Assert.Equal (0, Console.CursorLeft);
|
||||
Assert.Equal (0, Console.CursorTop);
|
||||
Assert.Equal (ConsoleColor.Gray, Console.ForegroundColor);
|
||||
Assert.Equal (ConsoleColor.Black, Console.BackgroundColor);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSetColors ()
|
||||
{
|
||||
var driver = new MockDriver ();
|
||||
driver.Init (() => { });
|
||||
Assert.Equal (ConsoleColor.Gray, Console.ForegroundColor);
|
||||
Assert.Equal (ConsoleColor.Black, Console.BackgroundColor);
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Assert.Equal (ConsoleColor.Red, Console.ForegroundColor);
|
||||
|
||||
Console.BackgroundColor = ConsoleColor.Green;
|
||||
Assert.Equal (ConsoleColor.Green, Console.BackgroundColor);
|
||||
|
||||
Console.ResetColor ();
|
||||
Assert.Equal (ConsoleColor.Gray, Console.ForegroundColor);
|
||||
Assert.Equal (ConsoleColor.Black, Console.BackgroundColor);
|
||||
driver.End ();
|
||||
}
|
||||
}
|
||||
}
|
||||
20
UnitTests/UnitTests.csproj
Normal file
20
UnitTests/UnitTests.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Terminal.Gui\Terminal.Gui.csproj" />
|
||||
<ProjectReference Include="..\UICatalog\UICatalog.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
5
UnitTests/xunit.runner.json
Normal file
5
UnitTests/xunit.runner.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
|
||||
"parallelizeTestCollections": false,
|
||||
"parallelizeAssembly": false
|
||||
}
|
||||
Reference in New Issue
Block a user