mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 07:47:54 +01:00
Fixed all modelusage bugs?
Replaced static `Application` references with instance-based `App` context across the codebase. Updated calls to `Application.RequestStop()` and `Application.Screen` to use `App?.RequestStop()` and `App?.Screen` for better encapsulation and flexibility. Refactored test infrastructure to align with the new context, including reintroducing `FakeApplicationFactory` and `FakeApplicationLifecycle` for testing purposes. Improved logging, error handling, and test clarity by adding `logWriter` support and simplifying test setup. Removed redundant or obsolete code, such as `NetSequences` and the old `FakeApplicationFactory` implementation. Updated documentation to reflect the new `IApplication.RequestStop()` usage.
This commit is contained in:
@@ -266,7 +266,7 @@ public class Dialogs : Scenario
|
||||
{
|
||||
Title = titleEdit.Text,
|
||||
Text = "Dialog Text",
|
||||
ButtonAlignment = (Alignment)Enum.Parse (typeof (Alignment), alignmentGroup.Labels! [(int)alignmentGroup.Value!.Value] [1..]),
|
||||
ButtonAlignment = (Alignment)Enum.Parse (typeof (Alignment), alignmentGroup.Labels! [(int)alignmentGroup.Value!.Value] [0..]),
|
||||
|
||||
Buttons = buttons.ToArray ()
|
||||
};
|
||||
|
||||
@@ -200,7 +200,7 @@ public class DynamicStatusBar : Scenario
|
||||
TextTitle.Text = string.Empty;
|
||||
Application.RequestStop ();
|
||||
};
|
||||
var dialog = new Dialog { Title = "Enter the menu details.", Buttons = [btnOk, btnCancel], Height = Dim.Auto (DimAutoStyle.Content, 17, Application.Screen.Height) };
|
||||
var dialog = new Dialog { Title = "Enter the menu details.", Buttons = [btnOk, btnCancel], Height = Dim.Auto (DimAutoStyle.Content, 17, App?.Screen.Height) };
|
||||
|
||||
Width = Dim.Fill ();
|
||||
Height = Dim.Fill () - 2;
|
||||
|
||||
@@ -37,7 +37,7 @@ public partial class ColorPicker
|
||||
{
|
||||
accept = true;
|
||||
e.Handled = true;
|
||||
Application.RequestStop ();
|
||||
(s as View)?.App?.RequestStop ();
|
||||
};
|
||||
|
||||
var btnCancel = new Button
|
||||
@@ -51,7 +51,7 @@ public partial class ColorPicker
|
||||
btnCancel.Accepting += (s, e) =>
|
||||
{
|
||||
e.Handled = true;
|
||||
Application.RequestStop ();
|
||||
(s as View)?.App ?.RequestStop ();
|
||||
};
|
||||
|
||||
d.Add (btnOk);
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Terminal.Gui.Views;
|
||||
/// <see cref="IApplication.Run(Toplevel, Func{Exception, bool})"/>. This will execute the dialog until
|
||||
/// it terminates via the <see cref="Application.QuitKey"/> (`Esc` by default),
|
||||
/// or when one of the views or buttons added to the dialog calls
|
||||
/// <see cref="Application.RequestStop"/>.
|
||||
/// <see cref="IApplication.RequestStop()"/>.
|
||||
/// </remarks>
|
||||
public class Dialog : Window
|
||||
{
|
||||
|
||||
@@ -138,7 +138,7 @@ public class DefaultFileOperations : IFileOperations
|
||||
btnOk.Accepting += (s, e) =>
|
||||
{
|
||||
confirm = true;
|
||||
Application.RequestStop ();
|
||||
(s as View)?.App?.RequestStop ();
|
||||
// When Accepting is handled, set e.Handled to true to prevent further processing.
|
||||
e.Handled = true;
|
||||
};
|
||||
@@ -147,7 +147,7 @@ public class DefaultFileOperations : IFileOperations
|
||||
btnCancel.Accepting += (s, e) =>
|
||||
{
|
||||
confirm = false;
|
||||
Application.RequestStop ();
|
||||
(s as View)?.App?.RequestStop ();
|
||||
// When Accepting is handled, set e.Handled to true to prevent further processing.
|
||||
e.Handled = true;
|
||||
};
|
||||
|
||||
@@ -108,7 +108,7 @@ public class FileDialog : Dialog, IDesignable
|
||||
|
||||
if (Modal)
|
||||
{
|
||||
Application.RequestStop ();
|
||||
(s as View)?.App?.RequestStop ();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -468,7 +468,6 @@ public class FileDialog : Dialog, IDesignable
|
||||
Style.IconProvider.IsOpenGetter = _treeView.IsExpanded;
|
||||
|
||||
_treeView.AddObjects (_treeRoots.Keys);
|
||||
#if MENU_V1
|
||||
|
||||
// if filtering on file type is configured then create the ComboBox and establish
|
||||
// initial filtering by extension(s)
|
||||
@@ -479,6 +478,7 @@ public class FileDialog : Dialog, IDesignable
|
||||
// Fiddle factor
|
||||
int width = AllowedTypes.Max (a => a.ToString ()!.Length) + 6;
|
||||
|
||||
#if MENU_V1
|
||||
_allowedTypeMenu = new (
|
||||
"<placeholder>",
|
||||
_allowedTypeMenuItems = AllowedTypes.Select (
|
||||
@@ -512,8 +512,8 @@ public class FileDialog : Dialog, IDesignable
|
||||
};
|
||||
|
||||
Add (_allowedTypeMenuBar);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// if no path has been provided
|
||||
if (_tbPath.Text.Length <= 0)
|
||||
@@ -879,7 +879,7 @@ public class FileDialog : Dialog, IDesignable
|
||||
|
||||
if (Modal)
|
||||
{
|
||||
Application.RequestStop ();
|
||||
App?.RequestStop ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -360,7 +360,7 @@ public static class MessageBox
|
||||
if (count == defaultButton)
|
||||
{
|
||||
b.IsDefault = true;
|
||||
b.Accepting += (_, e) =>
|
||||
b.Accepting += (s, e) =>
|
||||
{
|
||||
if (e?.Context?.Source is Button button)
|
||||
{
|
||||
@@ -376,7 +376,7 @@ public static class MessageBox
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
Application.RequestStop ();
|
||||
(s as View)?.App?.RequestStop ();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1534,7 +1534,7 @@ public class TableView : View, IDesignable
|
||||
/// <param name="width"></param>
|
||||
private void ClearLine (int row, int width)
|
||||
{
|
||||
if (Application.Screen.Height == 0)
|
||||
if (App?.Screen.Height == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1810,7 +1810,7 @@ public class TableView : View, IDesignable
|
||||
}
|
||||
}
|
||||
|
||||
if (Application.Screen.Height > 0)
|
||||
if (App?.Screen.Height > 0)
|
||||
{
|
||||
AddRuneAt (c, row, rune);
|
||||
}
|
||||
|
||||
@@ -458,7 +458,7 @@ public class Wizard : Dialog
|
||||
|
||||
if (IsCurrentTop)
|
||||
{
|
||||
Application.RequestStop (this);
|
||||
(sender as View)?.App?.RequestStop (this);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,10 +60,10 @@ public class FileDialogFluentTests
|
||||
public void CancelFileDialog_QuitKey_Quits (TestDriver d)
|
||||
{
|
||||
SaveDialog? sd = null;
|
||||
using var c = With.A (() => NewSaveDialog (out sd), 100, 20, d)
|
||||
.ScreenShot ("Save dialog", _out)
|
||||
.EnqueueKeyEvent (Application.QuitKey)
|
||||
.AssertTrue (sd!.Canceled);
|
||||
using GuiTestContext c = With.A (() => NewSaveDialog (out sd), 100, 20, d, logWriter: _out)
|
||||
.ScreenShot ("Save dialog", _out)
|
||||
.EnqueueKeyEvent (Application.QuitKey)
|
||||
.AssertTrue (sd!.Canceled);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -93,7 +93,7 @@ public class FileDialogFluentTests
|
||||
public void CancelFileDialog_UsingCancelButton_AltC (TestDriver d)
|
||||
{
|
||||
SaveDialog? sd = null;
|
||||
using var c = With.A (() => NewSaveDialog (out sd), 100, 20, d)
|
||||
using var c = With.A (() => NewSaveDialog (out sd), 100, 20, d, _out)
|
||||
.ScreenShot ("Save dialog", _out)
|
||||
.EnqueueKeyEvent (Key.C.WithAlt)
|
||||
.AssertTrue (sd!.Canceled);
|
||||
@@ -132,12 +132,13 @@ public class FileDialogFluentTests
|
||||
{
|
||||
SaveDialog? sd = null;
|
||||
MockFileSystem? fs = null;
|
||||
using var c = With.A (() => NewSaveDialog (out sd, out fs, modal: false), 100, 20, d)
|
||||
.ScreenShot ("Save dialog", _out)
|
||||
.Focus<Button> (b => b.Text == "_Save")
|
||||
.EnqueueKeyEvent (Key.Enter)
|
||||
.AssertFalse (sd!.Canceled)
|
||||
.AssertEqual (GetFileSystemRoot (fs!), sd!.FileName);
|
||||
using GuiTestContext c = With.A (() => NewSaveDialog (out sd, out fs, modal: false), 100, 20, d)
|
||||
.ScreenShot ("Save dialog", _out)
|
||||
.Focus<Button> (b => b.Text == "_Save")
|
||||
.EnqueueKeyEvent (Key.Enter)
|
||||
.AssertFalse (sd!.Canceled)
|
||||
.AssertEqual (GetFileSystemRoot (fs!), sd!.FileName)
|
||||
;
|
||||
}
|
||||
|
||||
private string GetFileSystemRoot (IFileSystem fs)
|
||||
|
||||
@@ -18,7 +18,7 @@ public class GuiTestContextTests (ITestOutputHelper outputHelper)
|
||||
{
|
||||
using var context = new GuiTestContext (d, _out, TimeSpan.FromSeconds (10));
|
||||
|
||||
Assert.NotEqual (Rectangle.Empty, Application.Screen);
|
||||
Assert.NotEqual (Rectangle.Empty, context.App?.Screen);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
||||
@@ -205,11 +205,6 @@ public partial class GuiTestContext
|
||||
App.Driver.EnqueueKeyEvent (key);
|
||||
WaitUntil (() => keyReceived);
|
||||
}
|
||||
else
|
||||
{
|
||||
Fail ("Expected Application.Driver to be non-null.");
|
||||
}
|
||||
|
||||
|
||||
return this;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ public partial class GuiTestContext : IDisposable
|
||||
|
||||
try
|
||||
{
|
||||
InitializeApplication ();
|
||||
App?.Init (GetDriverName ());
|
||||
_booting.Release ();
|
||||
|
||||
// After Init, Application.Screen should be set by the driver
|
||||
@@ -119,21 +119,36 @@ public partial class GuiTestContext : IDisposable
|
||||
{
|
||||
try
|
||||
{
|
||||
InitializeApplication ();
|
||||
try
|
||||
{
|
||||
App?.Init (GetDriverName ());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error(e.Message);
|
||||
_runCancellationTokenSource.Cancel ();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_booting.Release ();
|
||||
}
|
||||
|
||||
_booting.Release ();
|
||||
if (App is { Initialized: true })
|
||||
{
|
||||
Toplevel t = topLevelBuilder ();
|
||||
t.Closed += (s, e) => { Finished = true; };
|
||||
App?.Run (t); // This will block, but it's on a background thread now
|
||||
|
||||
Toplevel t = topLevelBuilder ();
|
||||
t.Closed += (s, e) => { Finished = true; };
|
||||
App?.Run (t); // This will block, but it's on a background thread now
|
||||
|
||||
t.Dispose ();
|
||||
Logging.Trace ("Application.Run completed");
|
||||
App?.Shutdown ();
|
||||
_runCancellationTokenSource.Cancel ();
|
||||
t.Dispose ();
|
||||
Logging.Trace ("Application.Run completed");
|
||||
App?.Shutdown ();
|
||||
_runCancellationTokenSource.Cancel ();
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{ }
|
||||
{
|
||||
Logging.Trace ("OperationCanceledException");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_backgroundException = ex;
|
||||
@@ -142,7 +157,6 @@ public partial class GuiTestContext : IDisposable
|
||||
finally
|
||||
{
|
||||
CleanupApplication ();
|
||||
|
||||
if (_logWriter != null)
|
||||
{
|
||||
WriteOutLogs (_logWriter);
|
||||
@@ -165,11 +179,6 @@ public partial class GuiTestContext : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeApplication ()
|
||||
{
|
||||
App?.Init (GetDriverName ());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Common initialization for both constructors.
|
||||
@@ -316,7 +325,7 @@ public partial class GuiTestContext : IDisposable
|
||||
throw new NotSupportedException ("Cannot WaitIteration during Invoke");
|
||||
}
|
||||
|
||||
Logging.Trace ($"WaitIteration started");
|
||||
//Logging.Trace ($"WaitIteration started");
|
||||
if (action is null)
|
||||
{
|
||||
action = (app) => { };
|
||||
@@ -358,8 +367,9 @@ public partial class GuiTestContext : IDisposable
|
||||
GuiTestContext? c = null;
|
||||
var sw = Stopwatch.StartNew ();
|
||||
|
||||
//Logging.Trace ($"WaitUntil started with timeout {_timeout}");
|
||||
Logging.Trace ($"WaitUntil started with timeout {_timeout}");
|
||||
|
||||
int count = 0;
|
||||
while (!condition ())
|
||||
{
|
||||
if (sw.Elapsed > _timeout)
|
||||
@@ -368,8 +378,10 @@ public partial class GuiTestContext : IDisposable
|
||||
}
|
||||
|
||||
c = WaitIteration ();
|
||||
count++;
|
||||
}
|
||||
|
||||
Logging.Trace ($"WaitUntil completed after {sw.ElapsedMilliseconds}ms and {count} iterations");
|
||||
return c ?? this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
namespace TerminalGuiFluentTesting;
|
||||
class NetSequences
|
||||
{
|
||||
public static ConsoleKeyInfo [] Down = new []
|
||||
{
|
||||
new ConsoleKeyInfo('\x1B', ConsoleKey.Enter, false, false, false),
|
||||
new ConsoleKeyInfo('[', ConsoleKey.None, false, false, false),
|
||||
new ConsoleKeyInfo('B', ConsoleKey.None, false, false, false),
|
||||
};
|
||||
|
||||
public static ConsoleKeyInfo [] Up = new []
|
||||
{
|
||||
new ConsoleKeyInfo('\x1B', ConsoleKey.Enter, false, false, false),
|
||||
new ConsoleKeyInfo('[', ConsoleKey.None, false, false, false),
|
||||
new ConsoleKeyInfo('A', ConsoleKey.None, false, false, false),
|
||||
};
|
||||
|
||||
public static ConsoleKeyInfo [] Left = new []
|
||||
{
|
||||
new ConsoleKeyInfo('\x1B', ConsoleKey.Enter, false, false, false),
|
||||
new ConsoleKeyInfo('[', ConsoleKey.None, false, false, false),
|
||||
new ConsoleKeyInfo('D', ConsoleKey.None, false, false, false),
|
||||
};
|
||||
|
||||
public static ConsoleKeyInfo [] Right = new []
|
||||
{
|
||||
new ConsoleKeyInfo('\x1B', ConsoleKey.Enter, false, false, false),
|
||||
new ConsoleKeyInfo('[', ConsoleKey.None, false, false, false),
|
||||
new ConsoleKeyInfo('C', ConsoleKey.None, false, false, false),
|
||||
};
|
||||
|
||||
public static IEnumerable<ConsoleKeyInfo> Click (int button, int screenX, int screenY)
|
||||
{
|
||||
// Adjust for 1-based coordinates
|
||||
int adjustedX = screenX + 1;
|
||||
int adjustedY = screenY + 1;
|
||||
|
||||
// Mouse press sequence
|
||||
var sequence = $"\x1B[<{button};{adjustedX};{adjustedY}M";
|
||||
foreach (char c in sequence)
|
||||
{
|
||||
yield return new ConsoleKeyInfo (c, ConsoleKey.None, false, false, false);
|
||||
}
|
||||
|
||||
// Mouse release sequence
|
||||
sequence = $"\x1B[<{button};{adjustedX};{adjustedY}m";
|
||||
foreach (char c in sequence)
|
||||
{
|
||||
yield return new ConsoleKeyInfo (c, ConsoleKey.None, false, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,10 +29,11 @@ public static class With
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="testDriver"></param>
|
||||
/// <param name="logWriter"></param>
|
||||
/// <returns></returns>
|
||||
public static GuiTestContext A (Func<Toplevel> toplevelFactory, int width, int height, TestDriver testDriver)
|
||||
public static GuiTestContext A (Func<Toplevel> toplevelFactory, int width, int height, TestDriver testDriver, TextWriter? logWriter = null)
|
||||
{
|
||||
return new (toplevelFactory, width, height, testDriver, null, Timeout);
|
||||
return new (toplevelFactory, width, height, testDriver, logWriter, Timeout);
|
||||
}
|
||||
/// <summary>
|
||||
/// The global timeout to allow for any given application to run for before shutting down.
|
||||
|
||||
@@ -59,7 +59,7 @@ public class TableViewTests (ITestOutputHelper output)
|
||||
{
|
||||
var tv = new TableView
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver,
|
||||
App = ApplicationImpl.Instance,
|
||||
Width = 20, Height = 4
|
||||
};
|
||||
|
||||
@@ -683,7 +683,7 @@ public class TableViewTests (ITestOutputHelper output)
|
||||
{
|
||||
var tableView = new TableView ()
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver
|
||||
App = ApplicationImpl.Instance
|
||||
};
|
||||
tableView.BeginInit ();
|
||||
tableView.EndInit ();
|
||||
@@ -765,7 +765,7 @@ public class TableViewTests (ITestOutputHelper output)
|
||||
{
|
||||
var tableView = new TableView ()
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver
|
||||
App = ApplicationImpl.Instance
|
||||
};
|
||||
tableView.BeginInit ();
|
||||
tableView.EndInit ();
|
||||
@@ -830,7 +830,7 @@ public class TableViewTests (ITestOutputHelper output)
|
||||
{
|
||||
var tableView = new TableView ()
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver
|
||||
App = ApplicationImpl.Instance
|
||||
};
|
||||
|
||||
tableView.BeginInit ();
|
||||
@@ -1579,7 +1579,7 @@ public class TableViewTests (ITestOutputHelper output)
|
||||
{
|
||||
var tv = new TableView ()
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver
|
||||
App = ApplicationImpl.Instance
|
||||
};
|
||||
tv.SchemeName = "TopLevel";
|
||||
tv.Viewport = new (0, 0, 50, 7);
|
||||
@@ -2226,7 +2226,7 @@ public class TableViewTests (ITestOutputHelper output)
|
||||
ApplicationImpl.Instance.Driver!.SetScreenSize (100, 100);
|
||||
var tv = new TableView ()
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver
|
||||
App = ApplicationImpl.Instance
|
||||
};
|
||||
tv.SchemeName = "TopLevel";
|
||||
tv.Viewport = new (0, 0, 50, 6);
|
||||
@@ -2433,7 +2433,7 @@ A B C
|
||||
|
||||
var tv = new TableView ()
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver
|
||||
App = ApplicationImpl.Instance
|
||||
};
|
||||
|
||||
//tv.BeginInit (); tv.EndInit ();
|
||||
@@ -3441,7 +3441,7 @@ A B C
|
||||
{
|
||||
var tableView = new TableView ()
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver
|
||||
App = ApplicationImpl.Instance
|
||||
};
|
||||
tableView.BeginInit ();
|
||||
tableView.EndInit ();
|
||||
@@ -3473,7 +3473,7 @@ A B C
|
||||
{
|
||||
var tv = new TableView ()
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver,
|
||||
App = ApplicationImpl.Instance,
|
||||
SchemeName = "TopLevel",
|
||||
Viewport = new (0, 0, 25, 6)
|
||||
};
|
||||
@@ -3504,7 +3504,7 @@ A B C
|
||||
{
|
||||
var tableView = new TableView ()
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver
|
||||
App = ApplicationImpl.Instance
|
||||
};
|
||||
tableView.SchemeName = "TopLevel";
|
||||
|
||||
@@ -3537,7 +3537,7 @@ A B C
|
||||
{
|
||||
var tv = new TableView ()
|
||||
{
|
||||
Driver = ApplicationImpl.Instance.Driver
|
||||
App = ApplicationImpl.Instance
|
||||
};
|
||||
tv.BeginInit ();
|
||||
tv.EndInit ();
|
||||
|
||||
Reference in New Issue
Block a user