diff --git a/Examples/UICatalog/UICatalog.cs b/Examples/UICatalog/UICatalog.cs
index 6f7a37139..f86dc3489 100644
--- a/Examples/UICatalog/UICatalog.cs
+++ b/Examples/UICatalog/UICatalog.cs
@@ -55,13 +55,31 @@ namespace UICatalog;
///
public class UICatalog
{
- private static string? _forceDriver = null;
+ private static string? _forceDriver;
+ private static bool _forTesting;
+ private static bool _iterationHandlerRemoved;
+ private static string? _uiCatalogDriver;
+ private static string? _scenarioDriver;
public static string LogFilePath { get; set; } = string.Empty;
public static LoggingLevelSwitch LogLevelSwitch { get; } = new ();
public const string LOGFILE_LOCATION = "logs";
public static UICatalogCommandLineOptions Options { get; set; }
+ public static (string? UiCatalogDriver, string? ScenarioDriver) Run (string [] args)
+ {
+ // Flag for testing
+ _forTesting = true;
+
+ // Start app
+ Main (args);
+
+ // Unset testing flag
+ _forTesting = false;
+
+ return new (_uiCatalogDriver, _scenarioDriver);
+ }
+
private static int Main (string [] args)
{
Console.OutputEncoding = Encoding.Default;
@@ -194,6 +212,8 @@ public class UICatalog
UICatalogMain (Options);
+ Debug.Assert (Application.ForceDriver == string.Empty);
+
return 0;
}
@@ -247,6 +267,11 @@ public class UICatalog
///
private static Scenario RunUICatalogTopLevel ()
{
+ if (_iterationHandlerRemoved)
+ {
+ return null!;
+ }
+
// Run UI Catalog UI. When it exits, if _selectedScenario is != null then
// a Scenario was selected. Otherwise, the user wants to quit UI Catalog.
@@ -255,7 +280,22 @@ public class UICatalog
Application.Init (driverName: _forceDriver);
- var top = Application.Run ();
+ Toplevel top;
+
+ if (_forTesting)
+ {
+ top = new UICatalogTop ();
+ SessionToken sessionToken = Application.Begin (top);
+ UICatalogTop.CachedSelectedScenario = Scenario.GetScenarios () [0];
+ Application.End (sessionToken);
+
+ _uiCatalogDriver = Application.Driver!.GetName ();
+ }
+ else
+ {
+ top = Application.Run ();
+ }
+
top.Dispose ();
Application.Shutdown ();
VerifyObjectsWereDisposed ();
@@ -412,6 +452,8 @@ public class UICatalog
Application.InitializedChanged += ApplicationOnInitializedChanged;
#endif
+ Application.ForceDriver = _forceDriver;
+
scenario.Main ();
scenario.Dispose ();
@@ -430,6 +472,43 @@ public class UICatalog
if (e.Value)
{
sw.Start ();
+
+ if (_forTesting)
+ {
+ int iterationCount = 0;
+ Key quitKey;
+
+ Application.Iteration += OnApplicationOnIteration;
+
+ void OnApplicationOnIteration (object? s, IterationEventArgs a)
+ {
+ iterationCount++;
+
+ if (Application.Initialized)
+ {
+ // Press QuitKey
+ quitKey = Application.QuitKey;
+
+ Logging.Trace (
+ $"Attempting to quit with {quitKey} after {iterationCount} iterations.");
+
+ try
+ {
+ Application.RaiseKeyDownEvent (quitKey);
+ }
+ catch (Exception ex)
+ {
+ Logging.Trace (
+ $"Exception raising quit key: {ex.Message}");
+ }
+
+ Application.Iteration -= OnApplicationOnIteration;
+ _iterationHandlerRemoved = true;
+
+ _scenarioDriver = Application.Driver?.GetName ();
+ }
+ }
+ }
}
else
{
diff --git a/Terminal.Gui/App/Application.Driver.cs b/Terminal.Gui/App/Application.Driver.cs
index c08fb879f..87e795746 100644
--- a/Terminal.Gui/App/Application.Driver.cs
+++ b/Terminal.Gui/App/Application.Driver.cs
@@ -26,7 +26,16 @@ public static partial class Application // Driver abstractions
public static string ForceDriver
{
get => ApplicationImpl.Instance.ForceDriver;
- set => ApplicationImpl.Instance.ForceDriver = value;
+ set
+ {
+ if (!string.IsNullOrEmpty (ApplicationImpl.Instance.ForceDriver))
+ {
+ // ForceDriver cannot be changed if it has a valid value
+ return;
+ }
+
+ ApplicationImpl.Instance.ForceDriver = value;
+ }
}
///
diff --git a/Terminal.Gui/App/ApplicationImpl.Driver.cs b/Terminal.Gui/App/ApplicationImpl.Driver.cs
index 36679b2b0..88678b85e 100644
--- a/Terminal.Gui/App/ApplicationImpl.Driver.cs
+++ b/Terminal.Gui/App/ApplicationImpl.Driver.cs
@@ -35,7 +35,7 @@ public partial class ApplicationImpl
bool factoryIsFake = _componentFactory is IComponentFactory;
// Then check driverName
- bool nameIsWindows = driverName?.Contains ("win", StringComparison.OrdinalIgnoreCase) ?? false;
+ bool nameIsWindows = driverName?.Contains ("windows", StringComparison.OrdinalIgnoreCase) ?? false;
bool nameIsDotNet = driverName?.Contains ("dotnet", StringComparison.OrdinalIgnoreCase) ?? false;
bool nameIsUnix = driverName?.Contains ("unix", StringComparison.OrdinalIgnoreCase) ?? false;
bool nameIsFake = driverName?.Contains ("fake", StringComparison.OrdinalIgnoreCase) ?? false;
diff --git a/Terminal.Gui/App/ApplicationImpl.Lifecycle.cs b/Terminal.Gui/App/ApplicationImpl.Lifecycle.cs
index 0a7795833..2be859831 100644
--- a/Terminal.Gui/App/ApplicationImpl.Lifecycle.cs
+++ b/Terminal.Gui/App/ApplicationImpl.Lifecycle.cs
@@ -231,7 +231,10 @@ public partial class ApplicationImpl
// === 9. Clear graphics ===
Sixel.Clear ();
- // === 10. Reset synchronization context ===
+ // === 10. Reset ForceDriver ===
+ ForceDriver = string.Empty;
+
+ // === 11. Reset synchronization context ===
// IMPORTANT: Always reset sync context, even if not initialized
// This ensures cleanup works correctly even if Shutdown is called without Init
// Reset synchronization context to allow the user to run async/await,
diff --git a/Tests/IntegrationTests/UICatalog/ScenarioTests.cs b/Tests/IntegrationTests/UICatalog/ScenarioTests.cs
index a7943d4e5..ba54736a6 100644
--- a/Tests/IntegrationTests/UICatalog/ScenarioTests.cs
+++ b/Tests/IntegrationTests/UICatalog/ScenarioTests.cs
@@ -665,4 +665,19 @@ public class ScenarioTests : TestsAllViews
void LayoutCompleteHandler (object? sender, LayoutEventArgs args) { UpdateTitle (curView); }
}
+
+ [Fact]
+ public void ForceDriver_persists_On_Open_Scenario_With_Args ()
+ {
+ string driverName = "fake";
+
+ string [] args = ["-d", driverName];
+
+ (string? UiCatalogDriver, string? ScenarioDriver) driverNames = global::UICatalog.UICatalog.Run (args);
+
+ Assert.Equal (string.Empty, Application.ForceDriver);
+ Assert.Equal (driverName, driverNames.UiCatalogDriver);
+ Assert.Equal (driverName, driverNames.ScenarioDriver);
+ Assert.Equal (driverNames.UiCatalogDriver, driverNames.ScenarioDriver);
+ }
}