Quellcode durchsuchen

Merge branch 'gui-cs:v2_develop' into v2_develop

Tig vor 1 Tag
Ursprung
Commit
316588a825
85 geänderte Dateien mit 1787 neuen und 1134 gelöschten Zeilen
  1. 9 11
      Examples/UICatalog/Scenarios/SendKeys.cs
  2. 5 1
      Terminal.Gui/App/Application.Run.cs
  3. 14 0
      Terminal.Gui/App/Application.cs
  4. 47 35
      Terminal.Gui/Drivers/V2/ApplicationV2.cs
  5. 26 0
      Terminal.Gui/Drivers/V2/ComponentFactory.cs
  6. 16 3
      Terminal.Gui/Drivers/V2/ConsoleDriverFacade.cs
  7. 50 0
      Terminal.Gui/Drivers/V2/IComponentFactory.cs
  8. 12 1
      Terminal.Gui/Drivers/V2/IConsoleDriverFacade.cs
  9. 11 0
      Terminal.Gui/Drivers/V2/IInputProcessor.cs
  10. 8 1
      Terminal.Gui/Drivers/V2/IMainLoop.cs
  11. 4 1
      Terminal.Gui/Drivers/V2/IWindowsInput.cs
  12. 18 1
      Terminal.Gui/Drivers/V2/InputProcessor.cs
  13. 16 4
      Terminal.Gui/Drivers/V2/MainLoop.cs
  14. 11 24
      Terminal.Gui/Drivers/V2/MainLoopCoordinator.cs
  15. 29 0
      Terminal.Gui/Drivers/V2/NetComponentFactory.cs
  16. 17 5
      Terminal.Gui/Drivers/V2/NetOutput.cs
  17. 34 2
      Terminal.Gui/Drivers/V2/OutputBase.cs
  18. 2 0
      Terminal.Gui/Drivers/V2/OutputBuffer.cs
  19. 3 0
      Terminal.Gui/Drivers/V2/ToplevelTransitionManager.cs
  20. 29 0
      Terminal.Gui/Drivers/V2/WindowsComponentFactory.cs
  21. 1 1
      Terminal.Gui/Drivers/V2/WindowsOutput.cs
  22. 1 1
      Terminal.Gui/Drivers/WindowsDriver/WindowsConsole.cs
  23. 7 0
      Terminal.Gui/ViewBase/Adornment/ShadowView.cs
  24. 0 6
      Terminal.Gui/Views/Dialog.cs
  25. 48 50
      Tests/IntegrationTests/FluentTests/BasicFluentAssertionTests.cs
  26. 74 62
      Tests/IntegrationTests/FluentTests/FileDialogFluentTests.cs
  27. 41 40
      Tests/IntegrationTests/FluentTests/MenuBarv2Tests.cs
  28. 31 26
      Tests/IntegrationTests/FluentTests/PopverMenuTests.cs
  29. 1 1
      Tests/IntegrationTests/FluentTests/TreeViewFluentTests.cs
  30. 158 0
      Tests/TerminalGuiFluentTesting/FakeDriverV2.cs
  31. 259 129
      Tests/TerminalGuiFluentTesting/GuiTestContext.cs
  32. 31 0
      Tests/TerminalGuiFluentTesting/ThreadSafeStringWriter.cs
  33. 7 7
      Tests/TerminalGuiFluentTesting/With.cs
  34. 2 2
      Tests/TerminalGuiFluentTestingXunit.Generator/TheGenerator.cs
  35. 53 82
      Tests/UnitTests/Application/ApplicationTests.cs
  36. 41 4
      Tests/UnitTests/AutoInitShutdownAttribute.cs
  37. 1 1
      Tests/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs
  38. 32 14
      Tests/UnitTests/ConsoleDrivers/V2/ApplicationV2Tests.cs
  39. 6 6
      Tests/UnitTests/ConsoleDrivers/V2/MainLoopCoordinatorTests.cs
  40. 11 1
      Tests/UnitTests/ConsoleDrivers/V2/MainLoopTTests.cs
  41. 62 67
      Tests/UnitTests/Dialogs/DialogTests.cs
  42. 16 25
      Tests/UnitTests/Dialogs/MessageBoxTests.cs
  43. 5 8
      Tests/UnitTests/Dialogs/WizardTests.cs
  44. 1 1
      Tests/UnitTests/Drawing/RulerTests.cs
  45. 7 6
      Tests/UnitTests/Drawing/ThicknessTests.cs
  46. 17 8
      Tests/UnitTests/FileServices/FileDialogTests.cs
  47. 8 1
      Tests/UnitTests/SetupFakeDriverAttribute.cs
  48. 11 10
      Tests/UnitTests/Text/AutocompleteTests.cs
  49. 2 2
      Tests/UnitTests/Text/TextFormatterTests.cs
  50. 1 0
      Tests/UnitTests/UnitTests.csproj
  51. 15 15
      Tests/UnitTests/View/Adornment/BorderTests.cs
  52. 2 2
      Tests/UnitTests/View/Adornment/MarginTests.cs
  53. 1 1
      Tests/UnitTests/View/Adornment/PaddingTests.cs
  54. 2 2
      Tests/UnitTests/View/Adornment/ShadowStyleTests.cs
  55. 2 2
      Tests/UnitTests/View/Draw/ClearViewportTests.cs
  56. 1 1
      Tests/UnitTests/View/Draw/ClipTests.cs
  57. 2 2
      Tests/UnitTests/View/Draw/DrawEventTests.cs
  58. 27 26
      Tests/UnitTests/View/Draw/DrawTests.cs
  59. 2 0
      Tests/UnitTests/View/Layout/Pos.AnchorEndTests.cs
  60. 4 4
      Tests/UnitTests/View/Layout/Pos.CenterTests.cs
  61. 3 2
      Tests/UnitTests/View/Layout/SetLayoutTests.cs
  62. 1 1
      Tests/UnitTests/View/Mouse/MouseTests.cs
  63. 2 3
      Tests/UnitTests/View/Navigation/CanFocusTests.cs
  64. 2 3
      Tests/UnitTests/View/Navigation/NavigationTests.cs
  65. 23 23
      Tests/UnitTests/View/TextTests.cs
  66. 3 4
      Tests/UnitTests/View/ViewTests.cs
  67. 1 1
      Tests/UnitTests/Views/ButtonTests.cs
  68. 10 10
      Tests/UnitTests/Views/CheckBoxTests.cs
  69. 5 5
      Tests/UnitTests/Views/FrameViewTests.cs
  70. 22 20
      Tests/UnitTests/Views/LabelTests.cs
  71. 18 18
      Tests/UnitTests/Views/ListViewTests.cs
  72. 137 131
      Tests/UnitTests/Views/Menuv1/MenuBarv1Tests.cs
  73. 3 7
      Tests/UnitTests/Views/ProgressBarTests.cs
  74. 3 3
      Tests/UnitTests/Views/RadioGroupTests.cs
  75. 4 4
      Tests/UnitTests/Views/ScrollBarTests.cs
  76. 8 8
      Tests/UnitTests/Views/SpinnerViewTests.cs
  77. 16 16
      Tests/UnitTests/Views/TabViewTests.cs
  78. 12 12
      Tests/UnitTests/Views/TableViewTests.cs
  79. 1 1
      Tests/UnitTests/Views/TextFieldTests.cs
  80. 45 45
      Tests/UnitTests/Views/TextViewTests.cs
  81. 90 88
      Tests/UnitTests/Views/TileViewTests.cs
  82. 18 18
      Tests/UnitTests/Views/ToplevelTests.cs
  83. 2 2
      Tests/UnitTests/Views/TreeTableSourceTests.cs
  84. 1 1
      Tests/UnitTests/Views/ViewDisposalTest.cs
  85. 3 3
      Tests/UnitTests/Views/WindowTests.cs

+ 9 - 11
Examples/UICatalog/Scenarios/SendKeys.cs

@@ -1,4 +1,4 @@
-using System;
+using System.Text;
 
 namespace UICatalog.Scenarios;
 
@@ -39,7 +39,7 @@ public class SendKeys : Scenario
 
         txtResult.KeyDown += (s, e) =>
                              {
-                                 rKeys += (char)e.KeyCode;
+                                 rKeys += e.ToString ();
 
                                  if (!IsShift && e.IsShift)
                                  {
@@ -81,17 +81,15 @@ public class SendKeys : Scenario
 
             foreach (char r in txtInput.Text)
             {
-                ConsoleKey ck = char.IsLetter (r)
-                                    ? (ConsoleKey)char.ToUpper (r)
-                                    : (ConsoleKey)r;
+                ConsoleKeyInfo consoleKeyInfo = EscSeqUtils.MapConsoleKeyInfo (new (r, ConsoleKey.None, false, false, false));
 
                 Application.Driver?.SendKeys (
-                                             r,
-                                             ck,
-                                             ckbShift.CheckedState == CheckState.Checked,
-                                             ckbAlt.CheckedState == CheckState.Checked,
-                                             ckbControl.CheckedState == CheckState.Checked
-                                            );
+                                              r,
+                                              consoleKeyInfo.Key,
+                                              ckbShift.CheckedState == CheckState.Checked || (consoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0,
+                                              ckbAlt.CheckedState == CheckState.Checked || (consoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0,
+                                              ckbControl.CheckedState == CheckState.Checked || (consoleKeyInfo.Modifiers & ConsoleModifiers.Control) != 0
+                                             );
             }
 
             lblShippedKeys.Text = rKeys;

+ 5 - 1
Terminal.Gui/App/Application.Run.cs

@@ -460,7 +460,7 @@ public static partial class Application // Run (Begin, Run, End, Stop)
     /// <summary>This event is raised on each iteration of the main loop.</summary>
     /// <remarks>See also <see cref="Timeout"/></remarks>
     public static event EventHandler<IterationEventArgs>? Iteration;
-
+    
     /// <summary>The <see cref="MainLoop"/> driver for the application</summary>
     /// <value>The main loop.</value>
     internal static MainLoop? MainLoop { get; set; }
@@ -618,4 +618,8 @@ public static partial class Application // Run (Begin, Run, End, Stop)
 
         LayoutAndDraw (true);
     }
+    internal static void RaiseIteration ()
+    {
+        Iteration?.Invoke (null, new ());
+    }
 }

+ 14 - 0
Terminal.Gui/App/Application.cs

@@ -51,6 +51,20 @@ public static partial class Application
     /// </summary>
     public static ITimedEvents? TimedEvents => ApplicationImpl.Instance?.TimedEvents;
 
+    /// <summary>
+    /// Maximum number of iterations of the main loop (and hence draws)
+    /// to allow to occur per second. Defaults to <see cref="DefaultMaximumIterationsPerSecond"/>> which is a 40ms sleep
+    /// after iteration (factoring in how long iteration took to run).
+    /// <remarks>Note that not every iteration draws (see <see cref="View.NeedsDraw"/>).
+    /// Only affects v2 drivers.</remarks>
+    /// </summary>
+    public static ushort MaximumIterationsPerSecond = DefaultMaximumIterationsPerSecond;
+
+    /// <summary>
+    /// Default value for <see cref="MaximumIterationsPerSecond"/>
+    /// </summary>
+    public const ushort DefaultMaximumIterationsPerSecond = 25;
+
     /// <summary>
     ///     Gets a string representation of the Application as rendered by <see cref="Driver"/>.
     /// </summary>

+ 47 - 35
Terminal.Gui/Drivers/V2/ApplicationV2.cs

@@ -1,5 +1,6 @@
 #nullable enable
 using System.Collections.Concurrent;
+using System.ComponentModel;
 using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using Microsoft.Extensions.Logging;
@@ -12,10 +13,7 @@ namespace Terminal.Gui.Drivers;
 /// </summary>
 public class ApplicationV2 : ApplicationImpl
 {
-    private readonly Func<INetInput> _netInputFactory;
-    private readonly Func<IConsoleOutput> _netOutputFactory;
-    private readonly Func<IWindowsInput> _winInputFactory;
-    private readonly Func<IConsoleOutput> _winOutputFactory;
+    private readonly IComponentFactory? _componentFactory;
     private IMainLoopCoordinator? _coordinator;
     private string? _driverName;
 
@@ -24,29 +22,20 @@ public class ApplicationV2 : ApplicationImpl
     /// <inheritdoc/>
     public override ITimedEvents TimedEvents => _timedEvents;
 
+    internal IMainLoopCoordinator? Coordinator => _coordinator;
+
     /// <summary>
     ///     Creates anew instance of the Application backend. The provided
     ///     factory methods will be used on Init calls to get things booted.
     /// </summary>
-    public ApplicationV2 () : this (
-                                    () => new NetInput (),
-                                    () => new NetOutput (),
-                                    () => new WindowsInput (),
-                                    () => new WindowsOutput ()
-                                   )
-    { }
-
-    internal ApplicationV2 (
-        Func<INetInput> netInputFactory,
-        Func<IConsoleOutput> netOutputFactory,
-        Func<IWindowsInput> winInputFactory,
-        Func<IConsoleOutput> winOutputFactory
-    )
+    public ApplicationV2 ()
+    {
+        IsLegacy = false;
+    }
+
+    internal ApplicationV2 (IComponentFactory componentFactory)
     {
-        _netInputFactory = netInputFactory;
-        _netOutputFactory = netOutputFactory;
-        _winInputFactory = winInputFactory;
-        _winOutputFactory = winOutputFactory;
+        _componentFactory = componentFactory;
         IsLegacy = false;
     }
 
@@ -92,8 +81,8 @@ public class ApplicationV2 : ApplicationImpl
     {
         PlatformID p = Environment.OSVersion.Platform;
 
-        bool definetlyWin = driverName?.Contains ("win") ?? false;
-        bool definetlyNet = driverName?.Contains ("net") ?? false;
+        bool definetlyWin = (driverName?.Contains ("win") ?? false )|| _componentFactory is IComponentFactory<WindowsConsole.InputRecord>;
+        bool definetlyNet = (driverName?.Contains ("net") ?? false ) || _componentFactory is IComponentFactory<ConsoleKeyInfo>;
 
         if (definetlyWin)
         {
@@ -125,13 +114,21 @@ public class ApplicationV2 : ApplicationImpl
         ConcurrentQueue<WindowsConsole.InputRecord> inputBuffer = new ();
         MainLoop<WindowsConsole.InputRecord> loop = new ();
 
-        return new MainLoopCoordinator<WindowsConsole.InputRecord> (
-                                                                    _timedEvents,
-                                                                    _winInputFactory,
+        IComponentFactory<WindowsConsole.InputRecord> cf;
+
+        if (_componentFactory != null)
+        {
+            cf = (IComponentFactory<WindowsConsole.InputRecord>)_componentFactory;
+        }
+        else
+        {
+            cf = new WindowsComponentFactory ();
+        }
+
+        return new MainLoopCoordinator<WindowsConsole.InputRecord> (_timedEvents,
                                                                     inputBuffer,
-                                                                    new WindowsInputProcessor (inputBuffer),
-                                                                    _winOutputFactory,
-                                                                    loop);
+                                                                    loop,
+                                                                    cf);
     }
 
     private IMainLoopCoordinator CreateNetSubcomponents ()
@@ -139,13 +136,22 @@ public class ApplicationV2 : ApplicationImpl
         ConcurrentQueue<ConsoleKeyInfo> inputBuffer = new ();
         MainLoop<ConsoleKeyInfo> loop = new ();
 
+        IComponentFactory<ConsoleKeyInfo> cf;
+
+        if (_componentFactory != null)
+        {
+            cf = (IComponentFactory<ConsoleKeyInfo>)_componentFactory;
+        }
+        else
+        {
+            cf = new NetComponentFactory ();
+        }
+
         return new MainLoopCoordinator<ConsoleKeyInfo> (
                                                         _timedEvents,
-                                                        _netInputFactory,
                                                         inputBuffer,
-                                                        new NetInputProcessor (inputBuffer),
-                                                        _netOutputFactory,
-                                                        loop);
+                                                        loop,
+                                                        cf);
     }
 
     /// <inheritdoc/>
@@ -171,6 +177,12 @@ public class ApplicationV2 : ApplicationImpl
             throw new NotInitializedException (nameof (Run));
         }
 
+        if (Application.Driver == null)
+        {
+            // See Run_T_Init_Driver_Cleared_with_TestTopLevel_Throws
+            throw new  InvalidOperationException ("Driver was inexplicably null when trying to Run view");
+        }
+
         Application.Top = view;
 
         RunState rs = Application.Begin (view);
@@ -258,4 +270,4 @@ public class ApplicationV2 : ApplicationImpl
         Application.Top?.SetNeedsDraw();
         Application.Top?.SetNeedsLayout ();
     }
-}
+}

+ 26 - 0
Terminal.Gui/Drivers/V2/ComponentFactory.cs

@@ -0,0 +1,26 @@
+#nullable enable
+using System.Collections.Concurrent;
+
+namespace Terminal.Gui.Drivers;
+
+/// <summary>
+/// Abstract base class implementation of <see cref="IComponentFactory{T}"/>
+/// </summary>
+/// <typeparam name="T"></typeparam>
+public abstract class ComponentFactory<T> : IComponentFactory<T>
+{
+    /// <inheritdoc />
+    public abstract IConsoleInput<T> CreateInput ();
+
+    /// <inheritdoc />
+    public abstract IInputProcessor CreateInputProcessor (ConcurrentQueue<T> inputBuffer);
+
+    /// <inheritdoc />
+    public virtual IWindowSizeMonitor CreateWindowSizeMonitor (IConsoleOutput consoleOutput, IOutputBuffer outputBuffer)
+    {
+        return new WindowSizeMonitor (consoleOutput, outputBuffer);
+    }
+
+    /// <inheritdoc />
+    public abstract IConsoleOutput CreateOutput ();
+}

+ 16 - 3
Terminal.Gui/Drivers/V2/ConsoleDriverFacade.cs

@@ -14,6 +14,10 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
     public event EventHandler<SizeChangedEventArgs> SizeChanged;
 
     public IInputProcessor InputProcessor { get; }
+    public IOutputBuffer OutputBuffer => _outputBuffer;
+
+    public IWindowSizeMonitor WindowSizeMonitor { get; }
+
 
     public ConsoleDriverFacade (
         IInputProcessor inputProcessor,
@@ -36,7 +40,8 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
                                          MouseEvent?.Invoke (s, e);
                                      };
 
-        windowSizeMonitor.SizeChanging += (_, e) => SizeChanged?.Invoke (this, e);
+        WindowSizeMonitor = windowSizeMonitor;
+        windowSizeMonitor.SizeChanging += (_,e) => SizeChanged?.Invoke (this, e);
 
         CreateClipboard ();
     }
@@ -68,7 +73,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
     {
         get
         {
-            if (ConsoleDriver.RunningUnitTests)
+            if (ConsoleDriver.RunningUnitTests && _output is WindowsOutput or NetOutput)
             {
                 // In unit tests, we don't have a real output, so we return an empty rectangle.
                 return Rectangle.Empty;
@@ -384,7 +389,15 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
     /// <param name="ctrl">If <see langword="true"/> simulates the Ctrl key being pressed.</param>
     public void SendKeys (char keyChar, ConsoleKey key, bool shift, bool alt, bool ctrl)
     {
-        // TODO: implement
+        ConsoleKeyInfo consoleKeyInfo = new (keyChar, key, shift, alt, ctrl);
+
+        Key k = EscSeqUtils.MapKey (consoleKeyInfo);
+
+        if (InputProcessor.IsValidInput (k, out k))
+        {
+            InputProcessor.OnKeyDown (k);
+            InputProcessor.OnKeyUp (k);
+        }
     }
 
     /// <summary>

+ 50 - 0
Terminal.Gui/Drivers/V2/IComponentFactory.cs

@@ -0,0 +1,50 @@
+#nullable enable
+using System.Collections.Concurrent;
+
+namespace Terminal.Gui.Drivers;
+
+/// <summary>
+/// Base untyped interface for <see cref="IComponentFactory{T}"/> for methods that are not templated on low level
+/// console input type.
+/// </summary>
+public interface IComponentFactory
+{
+    /// <summary>
+    /// Create the <see cref="IConsoleOutput"/> class for the current driver implementation i.e. the class responsible for
+    /// rendering <see cref="IOutputBuffer"/> into the console.
+    /// </summary>
+    /// <returns></returns>
+    IConsoleOutput CreateOutput ();
+}
+
+/// <summary>
+/// Creates driver specific subcomponent classes (<see cref="IConsoleInput{T}"/>, <see cref="IInputProcessor"/> etc) for a
+/// <see cref="IMainLoopCoordinator"/>.
+/// </summary>
+/// <typeparam name="T"></typeparam>
+public interface IComponentFactory<T> : IComponentFactory
+{
+    /// <summary>
+    /// Create <see cref="IConsoleInput{T}"/> class for the current driver implementation i.e. the class responsible for reading
+    /// user input from the console.
+    /// </summary>
+    /// <returns></returns>
+    IConsoleInput<T> CreateInput ();
+
+    /// <summary>
+    /// Creates the <see cref="InputProcessor{T}"/> class for the current driver implementation i.e. the class responsible for
+    /// translating raw console input into Terminal.Gui common event <see cref="Key"/> and <see cref="MouseEventArgs"/>.
+    /// </summary>
+    /// <param name="inputBuffer"></param>
+    /// <returns></returns>
+    IInputProcessor CreateInputProcessor (ConcurrentQueue<T> inputBuffer);
+
+    /// <summary>
+    /// Creates <see cref="IWindowSizeMonitor"/> class for the current driver implementation i.e. the class responsible for
+    /// reporting the current size of the terminal window.
+    /// </summary>
+    /// <param name="consoleOutput"></param>
+    /// <param name="outputBuffer"></param>
+    /// <returns></returns>
+    IWindowSizeMonitor CreateWindowSizeMonitor (IConsoleOutput consoleOutput, IOutputBuffer outputBuffer);
+}

+ 12 - 1
Terminal.Gui/Drivers/V2/IConsoleDriverFacade.cs

@@ -10,5 +10,16 @@ public interface IConsoleDriverFacade
     ///     e.g. <see cref="ConsoleKeyInfo"/> into <see cref="Key"/> events
     ///     and detecting and processing ansi escape sequences.
     /// </summary>
-    public IInputProcessor InputProcessor { get; }
+    IInputProcessor InputProcessor { get; }
+
+    /// <summary>
+    ///     Describes the desired screen state. Data source for <see cref="IConsoleOutput"/>.
+    /// </summary>
+    IOutputBuffer OutputBuffer { get; }
+
+    /// <summary>
+    ///     Interface for classes responsible for reporting the current
+    ///     size of the terminal window.
+    /// </summary>
+    IWindowSizeMonitor WindowSizeMonitor { get; }
 }

+ 11 - 0
Terminal.Gui/Drivers/V2/IInputProcessor.cs

@@ -58,4 +58,15 @@ public interface IInputProcessor
     /// </summary>
     /// <returns></returns>
     public IAnsiResponseParser GetParser ();
+
+    /// <summary>
+    ///     Handles surrogate pairs in the input stream.
+    /// </summary>
+    /// <param name="key">The key from input.</param>
+    /// <param name="result">Get the surrogate pair or the key.</param>
+    /// <returns>
+    ///     <see langword="true"/> if the result is a valid surrogate pair or a valid key, otherwise
+    ///     <see langword="false"/>.
+    /// </returns>
+    bool IsValidInput (Key key, out Key result);
 }

+ 8 - 1
Terminal.Gui/Drivers/V2/IMainLoop.cs

@@ -48,7 +48,14 @@ public interface IMainLoop<T> : IDisposable
     /// <param name="inputBuffer"></param>
     /// <param name="inputProcessor"></param>
     /// <param name="consoleOutput"></param>
-    void Initialize (ITimedEvents timedEvents, ConcurrentQueue<T> inputBuffer, IInputProcessor inputProcessor, IConsoleOutput consoleOutput);
+    /// <param name="componentFactory"></param>
+    void Initialize (
+        ITimedEvents timedEvents,
+        ConcurrentQueue<T> inputBuffer,
+        IInputProcessor inputProcessor,
+        IConsoleOutput consoleOutput,
+        IComponentFactory<T> componentFactory
+    );
 
     /// <summary>
     ///     Perform a single iteration of the main loop then blocks for a fixed length

+ 4 - 1
Terminal.Gui/Drivers/V2/IWindowsInput.cs

@@ -1,4 +1,7 @@
 namespace Terminal.Gui.Drivers;
 
-internal interface IWindowsInput : IConsoleInput<WindowsConsole.InputRecord>
+/// <summary>
+/// Interface for windows only input which uses low level win32 apis (v2win)
+/// </summary>
+public interface IWindowsInput : IConsoleInput<WindowsConsole.InputRecord>
 { }

+ 18 - 1
Terminal.Gui/Drivers/V2/InputProcessor.cs

@@ -165,7 +165,8 @@ public abstract class InputProcessor<T> : IInputProcessor
 
     internal char _highSurrogate = '\0';
 
-    internal bool IsValidInput (Key key, out Key result)
+    /// <inheritdoc />
+    public bool IsValidInput (Key key, out Key result)
     {
         result = key;
 
@@ -179,6 +180,22 @@ public abstract class InputProcessor<T> : IInputProcessor
         if (_highSurrogate > 0 && char.IsLowSurrogate ((char)key))
         {
             result = (KeyCode)new Rune (_highSurrogate, (char)key).Value;
+
+            if (key.IsAlt)
+            {
+                result = result.WithAlt;
+            }
+
+            if (key.IsCtrl)
+            {
+                result = result.WithCtrl;
+            }
+
+            if (key.IsShift)
+            {
+                result = result.WithShift;
+            }
+
             _highSurrogate = '\0';
 
             return true;

+ 16 - 4
Terminal.Gui/Drivers/V2/MainLoop.cs

@@ -83,7 +83,14 @@ public class MainLoop<T> : IMainLoop<T>
     /// <param name="inputBuffer"></param>
     /// <param name="inputProcessor"></param>
     /// <param name="consoleOutput"></param>
-    public void Initialize (ITimedEvents timedEvents, ConcurrentQueue<T> inputBuffer, IInputProcessor inputProcessor, IConsoleOutput consoleOutput)
+    /// <param name="componentFactory"></param>
+    public void Initialize (
+        ITimedEvents timedEvents,
+        ConcurrentQueue<T> inputBuffer,
+        IInputProcessor inputProcessor,
+        IConsoleOutput consoleOutput,
+        IComponentFactory<T> componentFactory
+    )
     {
         InputBuffer = inputBuffer;
         Out = consoleOutput;
@@ -92,18 +99,22 @@ public class MainLoop<T> : IMainLoop<T>
         TimedEvents = timedEvents;
         AnsiRequestScheduler = new (InputProcessor.GetParser ());
 
-        WindowSizeMonitor = new WindowSizeMonitor (Out, OutputBuffer);
+        WindowSizeMonitor = componentFactory.CreateWindowSizeMonitor (Out, OutputBuffer);
     }
 
     /// <inheritdoc/>
     public void Iteration ()
     {
+
+        Application.RaiseIteration ();
+
         DateTime dt = Now ();
+        int timeAllowed = 1000 / Math.Max(1,(int)Application.MaximumIterationsPerSecond);
 
         IterationImpl ();
 
         TimeSpan took = Now () - dt;
-        TimeSpan sleepFor = TimeSpan.FromMilliseconds (50) - took;
+        TimeSpan sleepFor = TimeSpan.FromMilliseconds (timeAllowed) - took;
 
         Logging.TotalIterationMetric.Record (took.Milliseconds);
 
@@ -123,7 +134,8 @@ public class MainLoop<T> : IMainLoop<T>
         if (Application.Top != null)
         {
             bool needsDrawOrLayout = AnySubViewsNeedDrawn (Application.Popover?.GetActivePopover () as View)
-                                     || AnySubViewsNeedDrawn (Application.Top);
+                                     || AnySubViewsNeedDrawn (Application.Top)
+                                     || (Application.MouseGrabHandler.MouseGrabView != null && AnySubViewsNeedDrawn (Application.MouseGrabHandler.MouseGrabView));
 
             bool sizeChanged = WindowSizeMonitor.Poll ();
 

+ 11 - 24
Terminal.Gui/Drivers/V2/MainLoopCoordinator.cs

@@ -13,12 +13,11 @@ namespace Terminal.Gui.Drivers;
 /// <typeparam name="T"></typeparam>
 internal class MainLoopCoordinator<T> : IMainLoopCoordinator
 {
-    private readonly Func<IConsoleInput<T>> _inputFactory;
     private readonly ConcurrentQueue<T> _inputBuffer;
     private readonly IInputProcessor _inputProcessor;
     private readonly IMainLoop<T> _loop;
+    private readonly IComponentFactory<T> _componentFactory;
     private readonly CancellationTokenSource _tokenSource = new ();
-    private readonly Func<IConsoleOutput> _outputFactory;
     private IConsoleInput<T> _input;
     private IConsoleOutput _output;
     private readonly object _oLockInitialization = new ();
@@ -32,34 +31,22 @@ internal class MainLoopCoordinator<T> : IMainLoopCoordinator
     ///     Creates a new coordinator
     /// </summary>
     /// <param name="timedEvents"></param>
-    /// <param name="inputFactory">
-    ///     Function to create a new input. This must call <see langword="new"/>
-    ///     explicitly and cannot return an existing instance. This requirement arises because Windows
-    ///     console screen buffer APIs are thread-specific for certain operations.
-    /// </param>
     /// <param name="inputBuffer"></param>
-    /// <param name="inputProcessor"></param>
-    /// <param name="outputFactory">
-    ///     Function to create a new output. This must call <see langword="new"/>
-    ///     explicitly and cannot return an existing instance. This requirement arises because Windows
-    ///     console screen buffer APIs are thread-specific for certain operations.
-    /// </param>
     /// <param name="loop"></param>
+    /// <param name="componentFactory">Factory for creating driver components
+    /// (<see cref="IConsoleOutput"/>, <see cref="IConsoleInput{T}"/> etc)</param>
     public MainLoopCoordinator (
         ITimedEvents timedEvents,
-        Func<IConsoleInput<T>> inputFactory,
         ConcurrentQueue<T> inputBuffer,
-        IInputProcessor inputProcessor,
-        Func<IConsoleOutput> outputFactory,
-        IMainLoop<T> loop
+        IMainLoop<T> loop,
+        IComponentFactory<T> componentFactory
     )
     {
         _timedEvents = timedEvents;
-        _inputFactory = inputFactory;
         _inputBuffer = inputBuffer;
-        _inputProcessor = inputProcessor;
-        _outputFactory = outputFactory;
+        _inputProcessor = componentFactory.CreateInputProcessor (_inputBuffer);
         _loop = loop;
+        _componentFactory = componentFactory;
     }
 
     /// <summary>
@@ -89,7 +76,7 @@ internal class MainLoopCoordinator<T> : IMainLoopCoordinator
                 throw _inputTask.Exception;
             }
 
-            throw new ("Input loop exited during startup instead of entering read loop properly (i.e. and blocking)");
+            Logging.Logger.LogCritical("Input loop exited during startup instead of entering read loop properly (i.e. and blocking)");
         }
 
         Logging.Logger.LogInformation ("Main Loop Coordinator booting complete");
@@ -102,7 +89,7 @@ internal class MainLoopCoordinator<T> : IMainLoopCoordinator
             lock (_oLockInitialization)
             {
                 // Instance must be constructed on the thread in which it is used.
-                _input = _inputFactory.Invoke ();
+                _input = _componentFactory.CreateInput ();
                 _input.Initialize (_inputBuffer);
 
                 BuildFacadeIfPossible ();
@@ -142,8 +129,8 @@ internal class MainLoopCoordinator<T> : IMainLoopCoordinator
         lock (_oLockInitialization)
         {
             // Instance must be constructed on the thread in which it is used.
-            _output = _outputFactory.Invoke ();
-            _loop.Initialize (_timedEvents, _inputBuffer, _inputProcessor, _output);
+            _output = _componentFactory.CreateOutput ();
+            _loop.Initialize (_timedEvents, _inputBuffer, _inputProcessor, _output,_componentFactory);
 
             BuildFacadeIfPossible ();
         }

+ 29 - 0
Terminal.Gui/Drivers/V2/NetComponentFactory.cs

@@ -0,0 +1,29 @@
+#nullable enable
+using System.Collections.Concurrent;
+
+namespace Terminal.Gui.Drivers;
+
+/// <summary>
+/// <see cref="IComponentFactory{T}"/> implementation for native csharp console I/O i.e. v2net.
+/// This factory creates instances of internal classes <see cref="NetInput"/>, <see cref="NetOutput"/> etc.
+/// </summary>
+public class NetComponentFactory : ComponentFactory<ConsoleKeyInfo>
+{
+    /// <inheritdoc/>
+    public override IConsoleInput<ConsoleKeyInfo> CreateInput ()
+    {
+        return new NetInput ();
+    }
+
+    /// <inheritdoc />
+    public override IConsoleOutput CreateOutput ()
+    {
+        return new NetOutput ();
+    }
+
+    /// <inheritdoc />
+    public override IInputProcessor CreateInputProcessor (ConcurrentQueue<ConsoleKeyInfo> inputBuffer)
+    {
+        return new NetInputProcessor (inputBuffer);
+    }
+}

+ 17 - 5
Terminal.Gui/Drivers/V2/NetOutput.cs

@@ -28,7 +28,11 @@ public class NetOutput : OutputBase, IConsoleOutput
     }
 
     /// <inheritdoc/>
-    public void Write (ReadOnlySpan<char> text) { Console.Out.Write (text); }
+    public void Write (ReadOnlySpan<char> text)
+    {
+        Console.Out.Write (text);
+    }
+
 
     /// <inheritdoc/>
     public Size GetWindowSize ()
@@ -67,9 +71,14 @@ public class NetOutput : OutputBase, IConsoleOutput
         EscSeqUtils.CSI_AppendTextStyleChange (output, redrawTextStyle, attr.Style);
     }
 
-    /// <inheritdoc/>
-    protected override void Write (StringBuilder output) { Console.Out.Write (output); }
 
+    /// <inheritdoc />
+    protected override void Write (StringBuilder output)
+    {
+        Console.Out.Write (output);
+    }
+
+    /// <inheritdoc />
     protected override bool SetCursorPositionImpl (int col, int row)
     {
         if (_lastCursorPosition is { } && _lastCursorPosition.Value.X == col && _lastCursorPosition.Value.Y == row)
@@ -102,9 +111,12 @@ public class NetOutput : OutputBase, IConsoleOutput
     }
 
     /// <inheritdoc/>
-    public void Dispose () { }
+    public void Dispose ()
+    {
+    }
 
-    /// <inheritdoc/>
+
+    /// <inheritdoc cref="IConsoleOutput.SetCursorVisibility"/>
     public override void SetCursorVisibility (CursorVisibility visibility)
     {
         Console.Out.Write (visibility == CursorVisibility.Default ? EscSeqUtils.CSI_ShowCursor : EscSeqUtils.CSI_HideCursor);

+ 34 - 2
Terminal.Gui/Drivers/V2/OutputBase.cs

@@ -1,5 +1,14 @@
-namespace Terminal.Gui.Drivers;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 
+namespace Terminal.Gui.Drivers;
+
+/// <summary>
+/// Abstract base class to assist with implementing <see cref="IConsoleOutput"/>.
+/// </summary>
 public abstract class OutputBase
 {
     private CursorVisibility? _cachedCursorVisibility;
@@ -7,7 +16,7 @@ public abstract class OutputBase
     // Last text style used, for updating style with EscSeqUtils.CSI_AppendTextStyleChange().
     private TextStyle _redrawTextStyle = TextStyle.None;
 
-    /// <inheritdoc/>
+    /// <inheritdoc cref="IConsoleOutput.Write(IOutputBuffer)"/>
     public virtual void Write (IOutputBuffer buffer)
     {
         if (ConsoleDriver.RunningUnitTests)
@@ -144,6 +153,14 @@ public abstract class OutputBase
         _cachedCursorVisibility = savedVisibility;
     }
 
+    /// <summary>
+    /// Changes the color and text style of the console to the given <paramref name="attr"/> and <paramref name="redrawTextStyle"/>.
+    /// If command can be buffered in line with other output (e.g. CSI sequence) then it should be appended to <paramref name="output"/>
+    /// otherwise the relevant output state should be flushed directly (e.g. by calling relevant win 32 API method)
+    /// </summary>
+    /// <param name="output"></param>
+    /// <param name="attr"></param>
+    /// <param name="redrawTextStyle"></param>
     protected abstract void AppendOrWriteAttribute (StringBuilder output, Attribute attr, TextStyle redrawTextStyle);
 
     private void WriteToConsole (StringBuilder output, ref int lastCol, int row, ref int outputWidth)
@@ -155,9 +172,24 @@ public abstract class OutputBase
         outputWidth = 0;
     }
 
+    /// <summary>
+    /// Output the contents of the <paramref name="output"/> to the console.
+    /// </summary>
+    /// <param name="output"></param>
     protected abstract void Write (StringBuilder output);
 
+    /// <summary>
+    /// When overriden in derived class, positions the terminal output cursor to the specified point on the screen.
+    /// </summary>
+    /// <param name="screenPositionX">Column to move cursor to</param>
+    /// <param name="screenPositionY">Row to move cursor to</param>
+    /// <returns></returns>
     protected abstract bool SetCursorPositionImpl (int screenPositionX, int screenPositionY);
 
+    /// <summary>
+    /// Changes the visibility of the cursor in the terminal to the specified <paramref name="visibility"/> e.g.
+    /// the flashing indicator, invisible, box indicator etc.
+    /// </summary>
+    /// <param name="visibility"></param>
     public abstract void SetCursorVisibility (CursorVisibility visibility);
 }

+ 2 - 0
Terminal.Gui/Drivers/V2/OutputBuffer.cs

@@ -141,6 +141,8 @@ public class OutputBuffer : IOutputBuffer
             return;
         }
 
+        Clip ??= new Region (Screen);
+
         Rectangle clipRect = Clip!.GetBounds ();
 
         if (validLocation)

+ 3 - 0
Terminal.Gui/Drivers/V2/ToplevelTransitionManager.cs

@@ -20,6 +20,9 @@ public class ToplevelTransitionManager : IToplevelTransitionManager
         {
             top.OnReady ();
             _readiedTopLevels.Add (top);
+
+            // Views can be closed and opened and run again multiple times, see End_Does_Not_Dispose
+            top.Closed += (s, e) => _readiedTopLevels.Remove (top);
         }
     }
 

+ 29 - 0
Terminal.Gui/Drivers/V2/WindowsComponentFactory.cs

@@ -0,0 +1,29 @@
+#nullable enable
+using System.Collections.Concurrent;
+
+namespace Terminal.Gui.Drivers;
+
+/// <summary>
+/// <see cref="IComponentFactory{T}"/> implementation for win32 windows only I/O i.e. v2win.
+/// This factory creates instances of internal classes <see cref="WindowsInput"/>, <see cref="WindowsOutput"/> etc.
+/// </summary>
+public class WindowsComponentFactory : ComponentFactory<WindowsConsole.InputRecord>
+{
+    /// <inheritdoc />
+    public override IConsoleInput<WindowsConsole.InputRecord> CreateInput ()
+    {
+        return new WindowsInput ();
+    }
+
+    /// <inheritdoc />
+    public override IInputProcessor CreateInputProcessor (ConcurrentQueue<WindowsConsole.InputRecord> inputBuffer)
+    {
+        return new WindowsInputProcessor (inputBuffer);
+    }
+
+    /// <inheritdoc />
+    public override IConsoleOutput CreateOutput ()
+    {
+        return new WindowsOutput ();
+    }
+}

+ 1 - 1
Terminal.Gui/Drivers/V2/WindowsOutput.cs

@@ -431,7 +431,7 @@ internal partial class WindowsOutput : OutputBase, IConsoleOutput
         return true;
     }
 
-    /// <inheritdoc/>
+    /// <inheritdoc cref="IConsoleOutput.SetCursorVisibility"/>
     public override void SetCursorVisibility (CursorVisibility visibility)
     {
         if (ConsoleDriver.RunningUnitTests)

+ 1 - 1
Terminal.Gui/Drivers/WindowsDriver/WindowsConsole.cs

@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
 
 namespace Terminal.Gui.Drivers;
 
-internal partial class WindowsConsole
+public partial class WindowsConsole
 {
     private CancellationTokenSource? _inputReadyCancellationTokenSource;
     private readonly BlockingCollection<InputRecord> _inputQueue = new (new ConcurrentQueue<InputRecord> ());

+ 7 - 0
Terminal.Gui/ViewBase/Adornment/ShadowView.cs

@@ -151,6 +151,13 @@ internal class ShadowView : View
             return Attribute.Default;
         }
 
+        if (Driver?.Contents == null ||
+            location.Y < 0 || location.Y >= Driver.Contents.GetLength (0) ||
+            location.X < 0 || location.X >= Driver.Contents.GetLength (1))
+        {
+            return Attribute.Default;
+        }
+
         Attribute attr = Driver!.Contents! [location.Y, location.X].Attribute!.Value;
 
         var newAttribute =

+ 0 - 6
Terminal.Gui/Views/Dialog.cs

@@ -109,12 +109,6 @@ public class Dialog : Window
     {
         get
         {
-#if DEBUG_IDISPOSABLE
-            if (EnableDebugIDisposableAsserts && WasDisposed)
-            {
-                throw new ObjectDisposedException (GetType ().FullName);
-            }
-#endif
             return _canceled;
         }
         set

+ 48 - 50
Tests/IntegrationTests/FluentTests/BasicFluentAssertionTests.cs

@@ -1,4 +1,5 @@
 using TerminalGuiFluentTesting;
+using TerminalGuiFluentTestingXunit;
 using Xunit.Abstractions;
 
 namespace IntegrationTests.FluentTests;
@@ -7,16 +8,13 @@ public class BasicFluentAssertionTests
 {
     private readonly TextWriter _out;
 
-    public BasicFluentAssertionTests (ITestOutputHelper outputHelper)
-    {
-        _out = new TestOutputWriter (outputHelper);
-    }
+    public BasicFluentAssertionTests (ITestOutputHelper outputHelper) { _out = new TestOutputWriter (outputHelper); }
 
     [Theory]
     [ClassData (typeof (V2TestDrivers))]
     public void GuiTestContext_NewInstance_Runs (V2TestDriver d)
     {
-        using GuiTestContext context = With.A<Window> (40, 10, d);
+        using GuiTestContext context = With.A<Window> (40, 10, d, _out);
         Assert.True (Application.Top!.Running);
 
         context.WriteOutLogs (_out);
@@ -34,9 +32,6 @@ public class BasicFluentAssertionTests
         context.RaiseKeyDownEvent (Application.QuitKey);
         Assert.False (top!.Running);
 
-        Application.Top?.Dispose ();
-        Application.Shutdown ();
-
         context.WriteOutLogs (_out);
         context.Stop ();
     }
@@ -69,9 +64,10 @@ public class BasicFluentAssertionTests
 
         using GuiTestContext c = With.A<Window> (40, 10, d)
                                      .Add (lbl)
-                                     .Then (() => Assert.Equal (38, lbl.Frame.Width)) // Window has 2 border
+                                     .AssertEqual (38, lbl.Frame.Width) // Window has 2 border
                                      .ResizeConsole (20, 20)
-                                     .Then (() => Assert.Equal (18, lbl.Frame.Width))
+                                     .WaitIteration ()
+                                     .AssertEqual (18, lbl.Frame.Width)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -85,7 +81,7 @@ public class BasicFluentAssertionTests
         MenuItemv2 [] menuItems = [new ("_New File", string.Empty, () => { clicked = true; })];
 
         using GuiTestContext c = With.A<Window> (40, 10, d)
-                                     .WithContextMenu (new PopoverMenu (menuItems))
+                                     .WithContextMenu (new (menuItems))
                                      .ScreenShot ("Before open menu", _out)
 
                                      // Click in main area inside border
@@ -98,7 +94,6 @@ public class BasicFluentAssertionTests
                                                 Assert.NotNull (popover);
                                                 var popoverMenu = popover as PopoverMenu;
                                                 popoverMenu!.Root!.BorderStyle = LineStyle.Single;
-
                                             })
                                      .WaitIteration ()
                                      .ScreenShot ("After open menu", _out)
@@ -114,26 +109,30 @@ public class BasicFluentAssertionTests
     {
         var clicked = false;
 
-        MenuItemv2 [] menuItems = [
-                                      new ("One", "", null),
-                                      new ("Two", "", null),
-                                      new ("Three", "", null),
-                                      new ("Four", "", new (
-                                           [
-                                               new ("SubMenu1", "", null),
-                                               new ("SubMenu2", "", ()=>clicked=true),
-                                               new ("SubMenu3", "", null),
-                                               new ("SubMenu4", "", null),
-                                               new ("SubMenu5", "", null),
-                                               new ("SubMenu6", "", null),
-                                               new ("SubMenu7", "", null)
-                                           ])),
-                                      new  ("Five", "", null),
-                                      new  ("Six", "", null)
-                                  ];
+        MenuItemv2 [] menuItems =
+        [
+            new ("One", "", null),
+            new ("Two", "", null),
+            new ("Three", "", null),
+            new (
+                 "Four",
+                 "",
+                 new (
+                      [
+                          new ("SubMenu1", "", null),
+                          new ("SubMenu2", "", () => clicked = true),
+                          new ("SubMenu3", "", null),
+                          new ("SubMenu4", "", null),
+                          new ("SubMenu5", "", null),
+                          new ("SubMenu6", "", null),
+                          new ("SubMenu7", "", null)
+                      ])),
+            new ("Five", "", null),
+            new ("Six", "", null)
+        ];
 
         using GuiTestContext c = With.A<Window> (40, 10, d)
-                                     .WithContextMenu (new PopoverMenu (menuItems))
+                                     .WithContextMenu (new (menuItems))
                                      .ScreenShot ("Before open menu", _out)
 
                                      // Click in main area inside border
@@ -177,43 +176,43 @@ public class BasicFluentAssertionTests
                                                 Application.Top!.Add (w1, w2, w3);
                                             })
                                      .WaitIteration ()
-                                     .Then (() => Assert.True (v5.HasFocus))
+                                     .AssertTrue (v5.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6)
-                                     .Then (() => Assert.True (v1.HasFocus))
+                                     .AssertTrue (v1.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6)
-                                     .Then (() => Assert.True (v3.HasFocus))
+                                     .AssertTrue (v3.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6.WithShift)
-                                     .Then (() => Assert.True (v1.HasFocus))
+                                     .AssertTrue (v1.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6.WithShift)
-                                     .Then (() => Assert.True (v5.HasFocus))
+                                     .AssertTrue (v5.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6.WithShift)
-                                     .Then (() => Assert.True (v3.HasFocus))
+                                     .AssertTrue (v3.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6)
-                                     .Then (() => Assert.True (v5.HasFocus))
+                                     .AssertTrue (v5.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6)
-                                     .Then (() => Assert.True (v1.HasFocus))
+                                     .AssertTrue (v1.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6)
-                                     .Then (() => Assert.True (v3.HasFocus))
+                                     .AssertTrue (v3.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6.WithShift)
-                                     .Then (() => Assert.True (v1.HasFocus))
+                                     .AssertTrue (v1.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6.WithShift)
-                                     .Then (() => Assert.True (v5.HasFocus))
+                                     .AssertTrue (v5.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6.WithShift)
-                                     .Then (() => Assert.True (v3.HasFocus))
+                                     .AssertTrue (v3.HasFocus)
                                      .RaiseKeyDownEvent (Key.Tab)
-                                     .Then (() => Assert.True (v4.HasFocus))
+                                     .AssertTrue (v4.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6)
-                                     .Then (() => Assert.True (v5.HasFocus))
+                                     .AssertTrue (v5.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6)
-                                     .Then (() => Assert.True (v1.HasFocus))
+                                     .AssertTrue (v1.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6.WithShift)
-                                     .Then (() => Assert.True (v5.HasFocus))
+                                     .AssertTrue (v5.HasFocus)
                                      .RaiseKeyDownEvent (Key.Tab)
-                                     .Then (() => Assert.True (v6.HasFocus))
+                                     .AssertTrue (v6.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6.WithShift)
-                                     .Then (() => Assert.True (v4.HasFocus))
+                                     .AssertTrue (v4.HasFocus)
                                      .RaiseKeyDownEvent (Key.F6)
-                                     .Then (() => Assert.True (v6.HasFocus))
+                                     .AssertTrue (v6.HasFocus)
                                      .WriteOutLogs (_out)
                                      .Stop ();
         Assert.False (v1.HasFocus);
@@ -221,6 +220,5 @@ public class BasicFluentAssertionTests
         Assert.False (v3.HasFocus);
         Assert.False (v4.HasFocus);
         Assert.False (v5.HasFocus);
-        Assert.False (v6.HasFocus);
     }
 }

+ 74 - 62
Tests/IntegrationTests/FluentTests/FileDialogFluentTests.cs

@@ -41,15 +41,28 @@ public class FileDialogFluentTests
         return mockFileSystem;
     }
 
+    private Toplevel NewSaveDialog (out SaveDialog sd, bool modal = true)
+    {
+        return NewSaveDialog (out sd, out _, modal);
+    }
+
+    private Toplevel NewSaveDialog (out SaveDialog sd, out MockFileSystem fs,bool modal = true)
+    {
+        fs = CreateExampleFileSystem ();
+        sd = new SaveDialog (fs) { Modal = modal };
+        return sd;
+    }
+
+
     [Theory]
     [ClassData (typeof (V2TestDrivers))]
     public void CancelFileDialog_UsingEscape (V2TestDriver d)
     {
-        var sd = new SaveDialog (CreateExampleFileSystem ());
-        using var c = With.A (sd, 100, 20, d)
+        SaveDialog? sd = null;
+        using var c = With.A (()=>NewSaveDialog(out sd), 100, 20, d)
             .ScreenShot ("Save dialog", _out)
             .Escape ()
-            .Then (() => Assert.True (sd.Canceled))
+            .AssertTrue (sd!.Canceled)
             .Stop ();
     }
 
@@ -57,11 +70,11 @@ public class FileDialogFluentTests
     [ClassData (typeof (V2TestDrivers))]
     public void CancelFileDialog_UsingCancelButton_TabThenEnter (V2TestDriver d)
     {
-        var sd = new SaveDialog (CreateExampleFileSystem ()) { Modal = false };
-        using var c = With.A (sd, 100, 20, d)
+        SaveDialog? sd = null;
+        using var c = With.A (() => NewSaveDialog (out sd,modal:false), 100, 20, d)
                           .ScreenShot ("Save dialog", _out)
                           .Focus<Button> (b => b.Text == "_Cancel")
-                          .Then (() => Assert.True (sd.Canceled))
+                          .AssertTrue (sd.Canceled)
                           .Enter ()
                           .Stop ();
     }
@@ -70,25 +83,24 @@ public class FileDialogFluentTests
     [ClassData (typeof (V2TestDrivers))]
     public void CancelFileDialog_UsingCancelButton_LeftClickButton (V2TestDriver d)
     {
-        var sd = new SaveDialog (CreateExampleFileSystem ());
-
-        using var c = With.A (sd, 100, 20, d)
+        SaveDialog? sd = null;
+        using var c = With.A (() => NewSaveDialog (out sd), 100, 20, d)
                           .ScreenShot ("Save dialog", _out)
                           .LeftClick<Button> (b => b.Text == "_Cancel")
                           .WriteOutLogs (_out)
-                          .Then (() => Assert.True (sd.Canceled))
+                          .AssertTrue (sd.Canceled)
                           .Stop ();
     }
     [Theory]
     [ClassData (typeof (V2TestDrivers))]
     public void CancelFileDialog_UsingCancelButton_AltC (V2TestDriver d)
     {
-        var sd = new SaveDialog (CreateExampleFileSystem ());
-        using var c = With.A (sd, 100, 20, d)
+        SaveDialog? sd = null;
+        using var c = With.A (() => NewSaveDialog (out sd), 100, 20, d)
                           .ScreenShot ("Save dialog", _out)
                           .Send (Key.C.WithAlt)
                           .WriteOutLogs (_out)
-                          .Then (() => Assert.True (sd.Canceled))
+                          .AssertTrue (sd.Canceled)
                           .Stop ();
     }
 
@@ -96,14 +108,15 @@ public class FileDialogFluentTests
     [ClassData (typeof (V2TestDrivers))]
     public void SaveFileDialog_UsingOkButton_Enter (V2TestDriver d)
     {
-        var fs = CreateExampleFileSystem ();
-        var sd = new SaveDialog (fs);
-        using var c = With.A (sd, 100, 20, d)
+        SaveDialog? sd = null;
+        MockFileSystem? fs = null;
+        using var c = With.A (() => NewSaveDialog (out sd,out fs), 100, 20, d)
                           .ScreenShot ("Save dialog", _out)
                           .LeftClick<Button> (b => b.Text == "_Save")
+                          .WaitIteration ()
                           .WriteOutLogs (_out)
-                          .Then (() => Assert.False (sd.Canceled))
-                          .Then (() => AssertIsFileSystemRoot (fs, sd))
+                          .AssertFalse(sd.Canceled)
+                          .AssertEqual (GetFileSystemRoot (fs), sd.FileName)
                           .Stop ();
     }
 
@@ -111,14 +124,14 @@ public class FileDialogFluentTests
     [ClassData (typeof (V2TestDrivers))]
     public void SaveFileDialog_UsingOkButton_AltS (V2TestDriver d)
     {
-        var fs = CreateExampleFileSystem ();
-        var sd = new SaveDialog (fs);
-        using var c = With.A (sd, 100, 20, d)
+        SaveDialog? sd = null;
+        MockFileSystem? fs = null;
+        using var c = With.A (() => NewSaveDialog (out sd, out fs), 100, 20, d)
                           .ScreenShot ("Save dialog", _out)
                           .Send (Key.S.WithAlt)
                           .WriteOutLogs (_out)
-                          .Then (() => Assert.False (sd.Canceled))
-                          .Then (() => AssertIsFileSystemRoot (fs, sd))
+                          .AssertFalse (sd.Canceled)
+                          .AssertEqual (GetFileSystemRoot (fs), sd.FileName)
                           .Stop ();
 
     }
@@ -127,42 +140,39 @@ public class FileDialogFluentTests
     [ClassData (typeof (V2TestDrivers))]
     public void SaveFileDialog_UsingOkButton_TabEnter (V2TestDriver d)
     {
-        var fs = CreateExampleFileSystem ();
-        var sd = new SaveDialog (fs) { Modal = false };
-        using var c = With.A (sd, 100, 20, d)
+        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")
                           .Enter ()
                           .WriteOutLogs (_out)
-                          .Then (() => Assert.False (sd.Canceled))
-                          .Then (() => AssertIsFileSystemRoot (fs, sd))
+                          .AssertFalse(sd.Canceled)
+                          .AssertEqual (GetFileSystemRoot(fs), sd.FileName)
                           .Stop ();
     }
 
-    private void AssertIsFileSystemRoot (IFileSystem fs, SaveDialog sd)
+    private string GetFileSystemRoot (IFileSystem fs)
     {
-        var expectedPath =
-            RuntimeInformation.IsOSPlatform (OSPlatform.Windows) ?
+        return RuntimeInformation.IsOSPlatform (OSPlatform.Windows) ?
                 $@"C:{fs.Path.DirectorySeparatorChar}" :
                 "/";
-
-        Assert.Equal (expectedPath, sd.FileName);
-
     }
 
     [Theory]
     [ClassData (typeof (V2TestDrivers))]
     public void SaveFileDialog_PressingPopTree_ShouldNotChangeCancel (V2TestDriver d)
     {
-        var sd = new SaveDialog (CreateExampleFileSystem ()) { Modal = false };
-        using var c = With.A (sd, 100, 20, d)
+        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)
-                          .Then (() => Assert.True (sd.Canceled))
+                          .AssertTrue (sd.Canceled)
                           .Focus<Button> (b => b.Text == "►►")
                           .Enter ()
                           .ScreenShot ("After pop tree", _out)
                           .WriteOutLogs (_out)
-                          .Then (() => Assert.True (sd.Canceled))
+                          .AssertTrue (sd.Canceled)
                           .Stop ();
 
     }
@@ -171,11 +181,11 @@ public class FileDialogFluentTests
     [ClassData (typeof (V2TestDrivers))]
     public void SaveFileDialog_PopTree_AndNavigate (V2TestDriver d)
     {
-        var sd = new SaveDialog (CreateExampleFileSystem ()) { Modal = false };
-
-        using var c = With.A (sd, 100, 20, d)
+        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)
-                          .Then (() => Assert.True (sd.Canceled))
+                          .AssertTrue (sd.Canceled)
                           .LeftClick<Button> (b => b.Text == "►►")
                           .ScreenShot ("After pop tree", _out)
                           .Focus<TreeView<IFileSystemInfo>> (_ => true)
@@ -185,7 +195,7 @@ public class FileDialogFluentTests
                           .ScreenShot ("After navigate down in tree", _out)
                           .Enter ()
                           .WaitIteration ()
-                          .Then (() => Assert.False (sd.Canceled))
+                          .AssertFalse (sd.Canceled)
                           .AssertContains ("empty-dir", sd.FileName)
                           .WriteOutLogs (_out)
                           .Stop ();
@@ -195,12 +205,12 @@ public class FileDialogFluentTests
     [ClassData (typeof (V2TestDrivers))]
     public void SaveFileDialog_PopTree_AndNavigate_PreserveFilenameOnDirectoryChanges_True (V2TestDriver d)
     {
-        var sd = new SaveDialog (CreateExampleFileSystem ()) { Modal = false };
-        sd.Style.PreserveFilenameOnDirectoryChanges = true;
-
-        using var c = With.A (sd, 100, 20, d)
+        SaveDialog? sd = null;
+        MockFileSystem? fs = null;
+        using var c = With.A (() => NewSaveDialog (out sd, out fs, modal: false), 100, 20, d)
+                          .Then (()=>sd.Style.PreserveFilenameOnDirectoryChanges=true)
                           .ScreenShot ("Save dialog", _out)
-                          .Then (() => Assert.True (sd.Canceled))
+                          .AssertTrue (sd.Canceled)
                           .Focus<TextField> (_=>true)
                           // Clear selection by pressing right in 'file path' text box
                           .RaiseKeyDownEvent (Key.CursorRight)
@@ -228,7 +238,7 @@ public class FileDialogFluentTests
                           .AssertEndsWith ("hello", sd.Path)
                           .Enter ()
                           .WaitIteration ()
-                          .Then (() => Assert.False (sd.Canceled))
+                          .AssertFalse (sd.Canceled)
                           .AssertContains ("empty-dir", sd.FileName)
                           .WriteOutLogs (_out)
                           .Stop ();
@@ -238,12 +248,12 @@ public class FileDialogFluentTests
     [ClassData (typeof (V2TestDrivers))]
     public void SaveFileDialog_PopTree_AndNavigate_PreserveFilenameOnDirectoryChanges_False (V2TestDriver d)
     {
-        var sd = new SaveDialog (CreateExampleFileSystem ()) { Modal = false };
-        sd.Style.PreserveFilenameOnDirectoryChanges = false;
-
-        using var c = With.A (sd, 100, 20, d)
+        SaveDialog? sd = null;
+        MockFileSystem? fs = null;
+        using var c = With.A (() => NewSaveDialog (out sd, out fs, modal: false), 100, 20, d)
+                          .Then (()=> sd.Style.PreserveFilenameOnDirectoryChanges = false)
                           .ScreenShot ("Save dialog", _out)
-                          .Then (() => Assert.True (sd.Canceled))
+                          .AssertTrue (sd.Canceled)
                           .Focus<TextField> (_ => true)
                           // Clear selection by pressing right in 'file path' text box
                           .RaiseKeyDownEvent (Key.CursorRight)
@@ -269,7 +279,7 @@ public class FileDialogFluentTests
                           .AssertDoesNotContain ("hello", sd.Path)
                           .Enter ()
                           .WaitIteration ()
-                          .Then (() => Assert.False (sd.Canceled))
+                          .AssertFalse (sd.Canceled)
                           .AssertContains ("empty-dir", sd.FileName)
                           .WriteOutLogs (_out)
                           .Stop ();
@@ -279,12 +289,12 @@ public class FileDialogFluentTests
     [ClassData (typeof (V2TestDrivers_WithTrueFalseParameter))]
     public void SaveFileDialog_TableView_UpDown_PreserveFilenameOnDirectoryChanges_True (V2TestDriver d, bool preserve)
     {
-        var sd = new SaveDialog (CreateExampleFileSystem ()) { Modal = false };
-        sd.Style.PreserveFilenameOnDirectoryChanges = preserve;
-
-        using var c = With.A (sd, 100, 20, d)
+        SaveDialog? sd = null;
+        MockFileSystem? fs = null;
+        using var c = With.A (() => NewSaveDialog (out sd, out fs, modal: false), 100, 20, d)
+                          .Then (() => sd.Style.PreserveFilenameOnDirectoryChanges = preserve)
                           .ScreenShot ("Save dialog", _out)
-                          .Then (() => Assert.True (sd.Canceled))
+                          .AssertTrue (sd.Canceled)
                           .Focus<TextField> (_ => true)
                           // Clear selection by pressing right in 'file path' text box
                           .RaiseKeyDownEvent (Key.CursorRight)
@@ -344,6 +354,7 @@ public class FileDialogFluentTests
         }
 
         c.LeftClick<Button> (b => b.Text == "_Save");
+        c.WaitIteration ();
         c.AssertFalse (sd.Canceled);
 
         if (preserve)
@@ -357,7 +368,8 @@ public class FileDialogFluentTests
              .AssertDoesNotContain ("hello", sd.Path);
         }
 
-        c.WriteOutLogs (_out)
-         .Stop ();
+        c.WriteOutLogs (_out);
+        c.WaitIteration ();
+        c.Stop ();
     }
 }

+ 41 - 40
Tests/IntegrationTests/FluentTests/MenuBarv2Tests.cs

@@ -1,6 +1,7 @@
 using System.Globalization;
 using System.Reflection;
 using TerminalGuiFluentTesting;
+using TerminalGuiFluentTestingXunit;
 using Xunit.Abstractions;
 
 namespace IntegrationTests.FluentTests;
@@ -167,15 +168,15 @@ public class MenuBarv2Tests
                                                 Application.Top!.Add (menuBar);
                                             })
                                      .WaitIteration ()
-                                     .Then (() => Assert.IsNotType<MenuItemv2> (Application.Navigation!.GetFocused ()))
+                                     .AssertIsNotType<MenuItemv2> (Application.Navigation!.GetFocused ())
                                      .ScreenShot ("MenuBar initial state", _out)
                                      .RaiseKeyDownEvent (MenuBarv2.DefaultKey)
                                      .WaitIteration ()
                                      .ScreenShot ($"After {MenuBarv2.DefaultKey}", _out)
                                      .WriteOutLogs (_out)
-                                     .Then (() => Assert.Equal ("_New file", Application.Navigation!.GetFocused ()!.Title))
-                                     .Then (() => Assert.True (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.True (menuBar?.IsOpen ()))
+                                     .AssertEqual ("_New file", Application.Navigation!.GetFocused ()!.Title)
+                                     .AssertTrue (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertTrue (menuBar?.IsOpen ())
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -205,14 +206,14 @@ public class MenuBarv2Tests
                                                 Application.Top!.Add (menuBar);
                                             })
                                      .WaitIteration ()
-                                     .Then (() => Assert.IsNotType<MenuItemv2>(Application.Navigation!.GetFocused()))
+                                     .AssertIsNotType<MenuItemv2>(Application.Navigation!.GetFocused())
                                      .ScreenShot ("MenuBar initial state", _out)
                                      .RaiseKeyDownEvent (MenuBarv2.DefaultKey)
                                      .ScreenShot ($"After {MenuBarv2.DefaultKey}", _out)
-                                     .Then (() => Assert.Equal ("_New file", Application.Navigation!.GetFocused ()!.Title))
+                                     .AssertEqual ("_New file", Application.Navigation!.GetFocused ()!.Title)
                                      .RaiseKeyDownEvent (MenuBarv2.DefaultKey)
                                      .ScreenShot ($"After {MenuBarv2.DefaultKey}", _out)
-                                     .Then (() => Assert.IsNotType<MenuItemv2>(Application.Navigation!.GetFocused()))
+                                     .AssertIsNotType<MenuItemv2>(Application.Navigation!.GetFocused())
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -328,24 +329,24 @@ public class MenuBarv2Tests
                                      .WaitIteration ()
                                      .ScreenShot ("MenuBar initial state", _out)
                                      .RaiseKeyDownEvent (MenuBarv2.DefaultKey)
-                                     .Then (() => Assert.True (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.True (menuBar?.IsOpen ()))
-                                     .Then (() => Assert.Equal ("_New file", Application.Navigation?.GetFocused ()!.Title))
+                                     .AssertTrue (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertTrue (menuBar?.IsOpen ())
+                                     .AssertEqual ("_New file", Application.Navigation?.GetFocused ()!.Title)
                                      .ScreenShot ($"After {MenuBarv2.DefaultKey}", _out)
                                      .Right ()
-                                     .Then (() => Assert.True (Application.Popover?.GetActivePopover () is PopoverMenu))
+                                     .AssertTrue (Application.Popover?.GetActivePopover () is PopoverMenu)
                                      .ScreenShot ("After right arrow", _out)
-                                     .Then (() => Assert.Equal ("Cu_t", Application.Navigation?.GetFocused ()!.Title))
+                                     .AssertEqual ("Cu_t", Application.Navigation?.GetFocused ()!.Title)
                                      .Right ()
                                      .ScreenShot ("After second right arrow", _out)
-                                     .Then (() => Assert.Equal ("_Online Help...", Application.Navigation?.GetFocused ()!.Title))
+                                     .AssertEqual ("_Online Help...", Application.Navigation?.GetFocused ()!.Title)
                                      .ScreenShot ("After third right arrow", _out)
                                      .Right ()
                                      .ScreenShot ("After fourth right arrow", _out)
-                                     .Then (() => Assert.Equal ("_New file", Application.Navigation?.GetFocused ()!.Title))
+                                     .AssertEqual ("_New file", Application.Navigation?.GetFocused ()!.Title)
                                      .Left ()
                                      .ScreenShot ("After left arrow", _out)
-                                     .Then (() => Assert.Equal ("_Online Help...", Application.Navigation?.GetFocused ()!.Title))
+                                     .AssertEqual ("_Online Help...", Application.Navigation?.GetFocused ()!.Title)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -375,17 +376,17 @@ public class MenuBarv2Tests
                                                 Application.Top!.Add (menuBar);
                                             })
                                      .WaitIteration ()
-                                     .Then (() => Assert.IsNotType<MenuItemv2>(Application.Navigation!.GetFocused()))
+                                     .AssertIsNotType<MenuItemv2>(Application.Navigation!.GetFocused())
                                      .ScreenShot ("MenuBar initial state", _out)
                                      .RaiseKeyDownEvent (MenuBarv2.DefaultKey)
-                                     .Then (() => Assert.Equal ("_New file", Application.Navigation!.GetFocused ()!.Title))
-                                     .Then (() => Assert.True (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.True (menuBar?.IsOpen ()))
-                                     .Then (() => Assert.Equal ("_New file", Application.Navigation?.GetFocused ()!.Title))
+                                     .AssertEqual ("_New file", Application.Navigation!.GetFocused ()!.Title)
+                                     .AssertTrue (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertTrue (menuBar?.IsOpen ())
+                                     .AssertEqual ("_New file", Application.Navigation?.GetFocused ()!.Title)
                                      .ScreenShot ($"After {MenuBarv2.DefaultKey}", _out)
                                      .RaiseKeyDownEvent (Application.QuitKey)
-                                     .Then (() => Assert.False (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.IsNotType<MenuItemv2> (Application.Navigation!.GetFocused ()))
+                                     .AssertFalse (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertIsNotType<MenuItemv2> (Application.Navigation!.GetFocused ())
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -414,19 +415,19 @@ public class MenuBarv2Tests
                                                 Application.Top!.Add (menuBar);
                                             })
                                      .WaitIteration ()
-                                     .Then (() => Assert.IsNotType<MenuItemv2> (Application.Navigation!.GetFocused ()))
+                                     .AssertIsNotType<MenuItemv2> (Application.Navigation!.GetFocused ())
                                      .ScreenShot ("MenuBar initial state", _out)
                                      .RaiseKeyDownEvent (MenuBarv2.DefaultKey)
                                      .RaiseKeyDownEvent (Key.CursorRight)
-                                     .Then (() => Assert.Equal ("Cu_t", Application.Navigation!.GetFocused ()!.Title))
-                                     .Then (() => Assert.True (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.True (menuBar?.IsOpen ()))
-                                     .Then (() => Assert.Equal ("Cu_t", Application.Navigation?.GetFocused ()!.Title))
+                                     .AssertEqual ("Cu_t", Application.Navigation!.GetFocused ()!.Title)
+                                     .AssertTrue (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertTrue (menuBar?.IsOpen ())
+                                     .AssertEqual ("Cu_t", Application.Navigation?.GetFocused ()!.Title)
                                      .ScreenShot ($"After {MenuBarv2.DefaultKey}", _out)
                                      .RaiseKeyDownEvent (Application.QuitKey)
                                      .WriteOutLogs (_out)
-                                     .Then (() => Assert.False (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.IsNotType<MenuItemv2> (Application.Navigation!.GetFocused ()))
+                                     .AssertFalse (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertIsNotType<MenuItemv2> (Application.Navigation!.GetFocused ())
                                      .Stop ();
     }
 
@@ -454,15 +455,15 @@ public class MenuBarv2Tests
                                                 Application.Top!.Add (menuBar);
                                             })
                                      .WaitIteration ()
-                                     .Then (() => Assert.IsNotType<MenuItemv2> (Application.Navigation!.GetFocused ()))
+                                     .AssertIsNotType<MenuItemv2> (Application.Navigation!.GetFocused ())
                                      .ScreenShot ("MenuBar initial state", _out)
                                      .RaiseKeyDownEvent (MenuBarv2.DefaultKey)
-                                     .Then (() => Assert.Equal ("_New file", Application.Navigation!.GetFocused ()!.Title))
-                                     .Then (() => Assert.True (Application.Top!.Running))
+                                     .AssertEqual ("_New file", Application.Navigation!.GetFocused ()!.Title)
+                                     .AssertTrue (Application.Top!.Running)
                                      .ScreenShot ($"After {MenuBarv2.DefaultKey}", _out)
                                      .RaiseKeyDownEvent (Application.QuitKey)
-                                     .Then (() => Assert.False (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.True (Application.Top!.Running))
+                                     .AssertFalse (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertTrue (Application.Top!.Running)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -496,14 +497,14 @@ public class MenuBarv2Tests
                                                 Application.Top!.Add (menuBar);
                                             })
                                      .WaitIteration ()
-                                     .Then (() => Assert.IsNotType<MenuItemv2> (Application.Navigation!.GetFocused ()))
+                                     .AssertIsNotType<MenuItemv2> (Application.Navigation!.GetFocused ())
                                      .ScreenShot ("MenuBar initial state", _out)
                                      .RaiseKeyDownEvent (MenuBarv2.DefaultKey)
-                                     .Then (() => Assert.Equal ("_New file", Application.Navigation!.GetFocused ()!.Title))
+                                     .AssertEqual ("_New file", Application.Navigation!.GetFocused ()!.Title)
                                      .ScreenShot ($"After {MenuBarv2.DefaultKey}", _out)
                                      .RaiseKeyDownEvent (Application.QuitKey)
-                                     .Then (() => Assert.False (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.True (Application.Top!.Running))
+                                     .AssertFalse (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertTrue (Application.Top!.Running)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -540,7 +541,7 @@ public class MenuBarv2Tests
                                      .WaitIteration ()
                                      .Focus (testView)
                                      .RaiseKeyDownEvent (Key.Space)
-                                     .Then (() => Assert.Equal (1, spaceKeyDownCount))
+                                     .AssertEqual (1, spaceKeyDownCount)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -577,7 +578,7 @@ public class MenuBarv2Tests
                                      .WaitIteration ()
                                      .Focus (testView)
                                      .RaiseKeyDownEvent (Key.Enter)
-                                     .Then (() => Assert.Equal (1, enterKeyDownCount))
+                                     .AssertEqual (1, enterKeyDownCount)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }

+ 31 - 26
Tests/IntegrationTests/FluentTests/PopverMenuTests.cs

@@ -1,5 +1,6 @@
 using System.Globalization;
 using TerminalGuiFluentTesting;
+using TerminalGuiFluentTestingXunit;
 using Xunit.Abstractions;
 
 namespace IntegrationTests.FluentTests;
@@ -47,12 +48,15 @@ public class PopoverMenuTests
                                      .Stop ();
     }
 
+    private static object o = new  ();
 
     [Theory]
     [ClassData (typeof (V2TestDrivers))]
     public void Activate_Sets_Application_Navigation_Correctly (V2TestDriver d)
     {
-        using GuiTestContext c = With.A<Window> (50, 20, d)
+        lock (o)
+        {
+            using GuiTestContext c = With.A<Window> (50, 20, d)
                                      .Then (
                                             () =>
                                             {
@@ -80,16 +84,18 @@ public class PopoverMenuTests
                                                 view.SetFocus ();
                                             })
                                      .WaitIteration ()
-                                     .Then (() => Assert.False (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.IsNotType<MenuItemv2> (Application.Navigation!.GetFocused ()))
+                                     .AssertFalse (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertIsNotType<MenuItemv2> (Application.Navigation!.GetFocused ())
                                      .ScreenShot ("PopoverMenu initial state", _out)
                                      .Then (() => Application.Popover!.Show (Application.Popover.Popovers.First ()))
                                      .WaitIteration ()
                                      .ScreenShot ($"After Show", _out)
-                                     .Then (() => Assert.True (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.Equal ("Cu_t", Application.Navigation!.GetFocused ()!.Title))
+                                     .AssertTrue (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertEqual ("Cu_t", Application.Navigation!.GetFocused ()!.Title)
                                      .WriteOutLogs (_out)
                                      .Stop ();
+        }
+        
     }
 
     [Theory]
@@ -125,19 +131,18 @@ public class PopoverMenuTests
                                             })
                                      .WaitIteration ()
                                      .ScreenShot ("PopoverMenu initial state", _out)
-                                     .Then (() => Assert.False (Application.Popover?.GetActivePopover () is PopoverMenu))
+                                     .AssertFalse (Application.Popover?.GetActivePopover () is PopoverMenu)
                                      .Then (() => Application.Popover!.Show (Application.Popover.Popovers.First ()))
                                      .WaitIteration ()
                                      .ScreenShot ($"After Show", _out)
-                                     .Then (() => Assert.True (Application.Popover?.GetActivePopover () is PopoverMenu))
+                                     .AssertTrue (Application.Popover?.GetActivePopover () is PopoverMenu)
                                      .RaiseKeyDownEvent (Application.QuitKey)
-                                     .Then (() => Application.LayoutAndDraw (true))
                                      .WaitIteration ()
                                      .WriteOutLogs (_out)
                                      .ScreenShot ($"After {Application.QuitKey}", _out)
-                                     .Then (() => Assert.False (Application.Popover!.Popovers.Cast<PopoverMenu> ().FirstOrDefault()!.Visible))
-                                     .Then (() => Assert.Null (Application.Popover!.GetActivePopover()))
-                                     .Then (() => Assert.True (Application.Top!.Running))
+                                     .AssertFalse (Application.Popover!.Popovers.Cast<PopoverMenu> ().FirstOrDefault()!.Visible)
+                                     .AssertNull (Application.Popover!.GetActivePopover())
+                                     .AssertTrue (Application.Top!.Running)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -175,17 +180,17 @@ public class PopoverMenuTests
                                             })
                                      .WaitIteration ()
                                      .ScreenShot ("PopoverMenu initial state", _out)
-                                     .Then (() => Assert.False (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.IsNotType<MenuItemv2>(Application.Navigation!.GetFocused()))
+                                     .AssertFalse (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertIsNotType<MenuItemv2>(Application.Navigation!.GetFocused())
                                      .Then (() => Application.Popover!.Show (Application.Popover.Popovers.First ()))
                                      .WaitIteration ()
                                      .ScreenShot ($"After Show", _out)
-                                     .Then (() => Assert.True (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.IsType<MenuItemv2>(Application.Navigation!.GetFocused()))
+                                     .AssertTrue (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertIsType<MenuItemv2>(Application.Navigation!.GetFocused())
                                      .RaiseKeyDownEvent (Application.QuitKey)
                                      .ScreenShot ($"After {Application.QuitKey}", _out)
-                                     .Then (() => Assert.False (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.IsNotType<MenuItemv2>(Application.Navigation!.GetFocused()))
+                                     .AssertFalse (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertIsNotType<MenuItemv2>(Application.Navigation!.GetFocused())
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -222,18 +227,18 @@ public class PopoverMenuTests
                                                 view.SetFocus ();
                                             })
                                      .WaitIteration ()
-                                     .Then (() => Assert.IsNotType<MenuItemv2>(Application.Navigation!.GetFocused()))
+                                     .AssertIsNotType<MenuItemv2>(Application.Navigation!.GetFocused())
                                      .ScreenShot ("PopoverMenu initial state", _out)
                                      .Then (() => Application.Popover!.Show (Application.Popover.Popovers.First ()))
                                      .WaitIteration ()
                                      .ScreenShot ("PopoverMenu after Show", _out)
-                                     .Then (() => Assert.Equal ("Cu_t", Application.Navigation!.GetFocused ()!.Title))
-                                     .Then (() => Assert.True (Application.Top!.Running))
+                                     .AssertEqual ("Cu_t", Application.Navigation!.GetFocused ()!.Title)
+                                     .AssertTrue (Application.Top!.Running)
                                      .RaiseKeyDownEvent (Application.QuitKey)
-                                     .Then (() => Application.LayoutAndDraw ())
+                                     .WaitIteration ()
                                      .ScreenShot ($"After {Application.QuitKey}", _out)
-                                     .Then (() => Assert.False (Application.Popover?.GetActivePopover () is PopoverMenu))
-                                     .Then (() => Assert.True (Application.Top!.Running))
+                                     .AssertFalse (Application.Popover?.GetActivePopover () is PopoverMenu)
+                                     .AssertTrue (Application.Top!.Running)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -271,7 +276,7 @@ public class PopoverMenuTests
                                      .WaitIteration ()
                                      .Focus (testView)
                                      .RaiseKeyDownEvent (Key.Space)
-                                     .Then (() => Assert.Equal (1, spaceKeyDownCount))
+                                     .AssertEqual (1, spaceKeyDownCount)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -308,7 +313,7 @@ public class PopoverMenuTests
                                      .WaitIteration ()
                                      .Focus (testView)
                                      .RaiseKeyDownEvent (Key.Enter)
-                                     .Then (() => Assert.Equal (1, enterKeyDownCount))
+                                     .AssertEqual (1, enterKeyDownCount)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }
@@ -345,7 +350,7 @@ public class PopoverMenuTests
                                      .WaitIteration ()
                                      .Focus (testView)
                                      .RaiseKeyDownEvent (Application.QuitKey)
-                                     .Then (() => Assert.Equal (1, quitKeyDownCount))
+                                     .AssertEqual (1, quitKeyDownCount)
                                      .WriteOutLogs (_out)
                                      .Stop ();
     }

+ 1 - 1
Tests/IntegrationTests/FluentTests/TreeViewFluentTests.cs

@@ -42,7 +42,7 @@ public class TreeViewFluentTests
                 .WaitIteration ()
                 .ScreenShot ("Before expanding", _out)
                 .AssertEqual (root, tv.GetObjectOnRow (0))
-                .Then (() => Assert.Null (tv.GetObjectOnRow (1)))
+                .AssertNull (tv.GetObjectOnRow (1))
                 .Right ()
                 .ScreenShot ("After expanding", _out)
                 .AssertMultiple (

+ 158 - 0
Tests/TerminalGuiFluentTesting/FakeDriverV2.cs

@@ -0,0 +1,158 @@
+using System.Collections.Concurrent;
+using System.Drawing;
+using TerminalGuiFluentTesting;
+
+namespace Terminal.Gui.Drivers;
+
+public class FakeApplicationFactory
+{
+    /// <summary>
+    /// Creates an initialized fake application which will be cleaned up when result object
+    /// is disposed.
+    /// </summary>
+    /// <returns></returns>
+    public IDisposable SetupFakeApplication ()
+    {
+        var cts = new CancellationTokenSource ();
+        var fakeInput = new FakeNetInput (cts.Token);
+        FakeOutput _output = new ();
+        _output.Size = new (25, 25);
+
+
+        IApplication origApp = ApplicationImpl.Instance;
+
+        var sizeMonitor = new FakeSizeMonitor ();
+
+        var v2 = new ApplicationV2 (new FakeNetComponentFactory (fakeInput, _output, sizeMonitor));
+
+        ApplicationImpl.ChangeInstance (v2);
+        v2.Init (null,"v2net");
+
+        var d = (ConsoleDriverFacade<ConsoleKeyInfo>)Application.Driver;
+        sizeMonitor.SizeChanging += (_, e) =>
+                                           {
+                                               if (e.Size != null)
+                                               {
+                                                   var s = e.Size.Value;
+                                                   _output.Size = s;
+                                                   d.OutputBuffer.SetWindowSize (s.Width, s.Height);
+                                               }
+                                           };
+
+        return new FakeApplicationLifecycle (origApp,cts);
+    }
+}
+
+class FakeApplicationLifecycle : IDisposable
+{
+    private readonly IApplication _origApp;
+    private readonly CancellationTokenSource _hardStop;
+
+    public FakeApplicationLifecycle (IApplication origApp, CancellationTokenSource hardStop)
+    {
+        _origApp = origApp;
+        _hardStop = hardStop;
+    }
+    /// <inheritdoc />
+    public void Dispose ()
+    {
+        _hardStop.Cancel();
+
+        Application.Top?.Dispose ();
+        Application.Shutdown ();
+        ApplicationImpl.ChangeInstance (_origApp);
+    }
+}
+
+public class FakeDriverFactory
+{
+    /// <summary>
+    /// Creates a new instance of <see cref="FakeDriverV2"/> using default options
+    /// </summary>
+    /// <returns></returns>
+    public IFakeDriverV2 Create ()
+    {
+        return new FakeDriverV2 (
+                                 new ConcurrentQueue<ConsoleKeyInfo> (),
+                                 new OutputBuffer (),
+                                 new FakeOutput (),
+                                 () => DateTime.Now,
+                                 new FakeSizeMonitor ());
+    }
+}
+
+public interface IFakeDriverV2 : IConsoleDriver, IConsoleDriverFacade
+{
+    void SetBufferSize (int width, int height);
+}
+
+/// <summary>
+/// Implementation of <see cref="IConsoleDriver"/> that uses fake input/output.
+/// This is a lightweight alternative to <see cref="GuiTestContext"/> (if you don't
+/// need the entire application main loop running).
+/// </summary>
+class FakeDriverV2 : ConsoleDriverFacade<ConsoleKeyInfo>, IFakeDriverV2
+{
+    public ConcurrentQueue<ConsoleKeyInfo> InputBuffer { get; }
+    public FakeSizeMonitor SizeMonitor { get; }
+    public OutputBuffer OutputBuffer { get; }
+
+    public IConsoleOutput ConsoleOutput { get; }
+
+    private FakeOutput _fakeOutput;
+
+    internal FakeDriverV2 (
+        ConcurrentQueue<ConsoleKeyInfo> inputBuffer,
+        OutputBuffer outputBuffer,
+        FakeOutput fakeOutput,
+        Func<DateTime> datetimeFunc,
+        FakeSizeMonitor sizeMonitor) :
+        base (new NetInputProcessor (inputBuffer),
+             outputBuffer,
+             fakeOutput,
+             new (new AnsiResponseParser (), datetimeFunc),
+             sizeMonitor)
+    {
+        InputBuffer = inputBuffer;
+        SizeMonitor = sizeMonitor;
+        OutputBuffer = outputBuffer;
+        ConsoleOutput = _fakeOutput = fakeOutput;
+        SizeChanged += (_, e) =>
+                       {
+                           if (e.Size != null)
+                           {
+                               var s = e.Size.Value;
+                               _fakeOutput.Size = s;
+                               OutputBuffer.SetWindowSize (s.Width,s.Height);
+                           }
+                       };
+
+    }
+
+    public void SetBufferSize (int width, int height)
+    {
+        SizeMonitor.RaiseSizeChanging (new Size (width,height));
+        OutputBuffer.SetWindowSize (width,height);
+    }
+}
+
+public class FakeSizeMonitor : IWindowSizeMonitor
+{
+    /// <inheritdoc />
+    public event EventHandler<SizeChangedEventArgs>? SizeChanging;
+
+    /// <inheritdoc />
+    public bool Poll ()
+    {
+        return false;
+    }
+
+    /// <summary>
+    /// Raises the <see cref="SizeChanging"/> event.
+    /// </summary>
+    /// <param name="newSize"></param>
+    public void RaiseSizeChanging (Size newSize)
+    {
+        SizeChanging?.Invoke (this,new (newSize));
+    }
+}

+ 259 - 129
Tests/TerminalGuiFluentTesting/GuiTestContext.cs

@@ -1,4 +1,5 @@
-using System.Drawing;
+using System.Diagnostics;
+using System.Drawing;
 using System.Text;
 using Microsoft.Extensions.Logging;
 
@@ -13,106 +14,105 @@ public class GuiTestContext : IDisposable
     private readonly CancellationTokenSource _cts = new ();
     private readonly CancellationTokenSource _hardStop = new (With.Timeout);
     private readonly Task _runTask;
-    private Exception _ex;
+    private Exception? _ex;
     private readonly FakeOutput _output = new ();
     private readonly FakeWindowsInput _winInput;
     private readonly FakeNetInput _netInput;
     private View? _lastView;
+    private readonly object _logsLock = new ();
     private readonly StringBuilder _logsSb;
     private readonly V2TestDriver _driver;
     private bool _finished;
-    private readonly object _threadLock = new ();
+    private readonly FakeSizeMonitor _fakeSizeMonitor;
 
-    internal GuiTestContext (Func<Toplevel> topLevelBuilder, int width, int height, V2TestDriver driver)
+    internal GuiTestContext (Func<Toplevel> topLevelBuilder, int width, int height, V2TestDriver driver, TextWriter? logWriter = null)
     {
-        lock (_threadLock)
-        {
-            IApplication origApp = ApplicationImpl.Instance;
-            ILogger? origLogger = Logging.Logger;
-            _logsSb = new ();
-            _driver = driver;
+        // Remove frame limit
+        Application.MaximumIterationsPerSecond = ushort.MaxValue;
+
+        IApplication origApp = ApplicationImpl.Instance;
+        ILogger? origLogger = Logging.Logger;
+        _logsSb = new ();
+        _driver = driver;
+
+        _netInput = new (_cts.Token);
+        _winInput = new (_cts.Token);
 
-            _netInput = new (_cts.Token);
-            _winInput = new (_cts.Token);
+        _output.Size = new (width, height);
+        _fakeSizeMonitor = new ();
 
-            _output.Size = new (width, height);
+        IComponentFactory cf = driver == V2TestDriver.V2Net
+                                   ? new FakeNetComponentFactory (_netInput, _output, _fakeSizeMonitor)
+                                   : (IComponentFactory)new FakeWindowsComponentFactory (_winInput, _output, _fakeSizeMonitor);
 
-            var v2 = new ApplicationV2 (
-                                        () => _netInput,
-                                        () => _output,
-                                        () => _winInput,
-                                        () => _output);
+        var v2 = new ApplicationV2 (cf);
 
-            var booting = new SemaphoreSlim (0, 1);
+        var booting = new SemaphoreSlim (0, 1);
 
-            // Start the application in a background thread
-            _runTask = Task.Run (() =>
+        // Start the application in a background thread
+        _runTask = Task.Run (
+                             () =>
+                             {
+                                 try
+                                 {
+                                     ApplicationImpl.ChangeInstance (v2);
+
+                                     ILogger logger = LoggerFactory.Create (
+                                                                            builder =>
+                                                                                builder.SetMinimumLevel (LogLevel.Trace)
+                                                                                       .AddProvider (
+                                                                                                     new TextWriterLoggerProvider (
+                                                                                                      new ThreadSafeStringWriter (_logsSb, _logsLock))))
+                                                                   .CreateLogger ("Test Logging");
+                                     Logging.Logger = logger;
+
+                                     v2.Init (null, GetDriverName ());
+
+                                     booting.Release ();
+
+                                     Toplevel t = topLevelBuilder ();
+                                     t.Closed += (s, e) => { _finished = true; };
+                                     Application.Run (t); // This will block, but it's on a background thread now
+
+                                     t.Dispose ();
+                                     Application.Shutdown ();
+                                     _cts.Cancel ();
+                                 }
+                                 catch (OperationCanceledException)
+                                 { }
+                                 catch (Exception ex)
                                  {
-                                     while (Application.Top is { })
+                                     _ex = ex;
+
+                                     if (logWriter != null)
                                      {
-                                         Task.Delay (300).Wait ();
+                                         WriteOutLogs (logWriter);
                                      }
-                                 })
-                           .ContinueWith (
-                                          (task, _) =>
-                                          {
-                                              try
-                                              {
-                                                  if (task.IsFaulted)
-                                                  {
-                                                      _ex = task.Exception ?? new Exception ("Unknown error in background task");
-                                                  }
-
-                                                  // Ensure we are not running on the main thread
-                                                  if (ApplicationImpl.Instance != origApp)
-                                                  {
-                                                      throw new InvalidOperationException (
-                                                                                           "Application instance is not the original one, this should not happen.");
-                                                  }
-
-                                                  ApplicationImpl.ChangeInstance (v2);
-
-                                                  ILogger logger = LoggerFactory.Create (builder =>
-                                                                                             builder.SetMinimumLevel (LogLevel.Trace)
-                                                                                                    .AddProvider (
-                                                                                                         new TextWriterLoggerProvider (
-                                                                                                              new StringWriter (_logsSb))))
-                                                                                .CreateLogger ("Test Logging");
-                                                  Logging.Logger = logger;
-
-                                                  v2.Init (null, GetDriverName ());
-
-                                                  booting.Release ();
-
-                                                  Toplevel t = topLevelBuilder ();
-                                                  t.Closed += (s, e) => { _finished = true; };
-                                                  Application.Run (t); // This will block, but it's on a background thread now
-
-                                                  t.Dispose ();
-                                                  Application.Shutdown ();
-                                              }
-                                              catch (OperationCanceledException)
-                                              { }
-                                              catch (Exception ex)
-                                              {
-                                                  _ex = ex;
-                                              }
-                                              finally
-                                              {
-                                                  ApplicationImpl.ChangeInstance (origApp);
-                                                  Logging.Logger = origLogger;
-                                                  _finished = true;
-                                              }
-                                          },
-                                          _cts.Token);
-
-            // Wait for booting to complete with a timeout to avoid hangs
-            if (!booting.WaitAsync (TimeSpan.FromSeconds (10)).Result)
-            {
-                throw new TimeoutException ("Application failed to start within the allotted time.");
-            }
 
-            WaitIteration ();
+                                     _hardStop.Cancel ();
+                                 }
+                                 finally
+                                 {
+                                     ApplicationImpl.ChangeInstance (origApp);
+                                     Logging.Logger = origLogger;
+                                     _finished = true;
+
+                                     Application.MaximumIterationsPerSecond = Application.DefaultMaximumIterationsPerSecond;
+                                 }
+                             },
+                             _cts.Token);
+
+        // Wait for booting to complete with a timeout to avoid hangs
+        if (!booting.WaitAsync (TimeSpan.FromSeconds (10)).Result)
+        {
+            throw new TimeoutException ("Application failed to start within the allotted time.");
+        }
+
+        ResizeConsole (width, height);
+
+        if (_ex != null)
+        {
+            throw new ("Application crashed", _ex);
         }
     }
 
@@ -137,7 +137,7 @@ public class GuiTestContext : IDisposable
             return this;
         }
 
-        Application.Invoke (() => { Application.RequestStop (); });
+        WaitIteration (() => { Application.RequestStop (); });
 
         // Wait for the application to stop, but give it a 1-second timeout
         if (!_runTask.Wait (TimeSpan.FromMilliseconds (1000)))
@@ -147,7 +147,19 @@ public class GuiTestContext : IDisposable
             // Timeout occurred, force the task to stop
             _hardStop.Cancel ();
 
-            throw new TimeoutException ("Application failed to stop within the allotted time.");
+            // App is having trouble shutting down, try sending some more shutdown stuff from this thread.
+            // If this doesn't work there will be test cascade failures as the main loop continues to run during next test.
+            try
+            {
+                Application.RequestStop ();
+                Application.Shutdown ();
+            }
+            catch (Exception)
+            {
+                throw new TimeoutException ("Application failed to stop within the allotted time.", _ex);
+            }
+
+            throw new TimeoutException ("Application failed to stop within the allotted time.", _ex);
         }
 
         _cts.Cancel ();
@@ -163,8 +175,13 @@ public class GuiTestContext : IDisposable
     /// <summary>
     ///     Hard stops the application and waits for the background thread to exit.
     /// </summary>
-    public void HardStop ()
+    public void HardStop (Exception? ex = null)
     {
+        if (ex != null)
+        {
+            _ex = ex;
+        }
+
         _hardStop.Cancel ();
         Stop ();
     }
@@ -179,7 +196,8 @@ public class GuiTestContext : IDisposable
         if (_hardStop.IsCancellationRequested)
         {
             throw new (
-                       "Application was hard stopped, typically this means it timed out or did not shutdown gracefully. Ensure you call Stop in your test");
+                       "Application was hard stopped, typically this means it timed out or did not shutdown gracefully. Ensure you call Stop in your test",
+                       _ex);
         }
 
         _hardStop.Cancel ();
@@ -213,19 +231,27 @@ public class GuiTestContext : IDisposable
     /// <returns></returns>
     public GuiTestContext ResizeConsole (int width, int height)
     {
-        _output.Size = new (width, height);
-
-        return WaitIteration ();
+        return WaitIteration (
+                              () =>
+                              {
+                                  _output.Size = new (width, height);
+                                  _fakeSizeMonitor.RaiseSizeChanging (_output.Size);
+
+                                  var d = (IConsoleDriverFacade)Application.Driver!;
+                                  d.OutputBuffer.SetWindowSize (width, height);
+                              });
     }
 
     public GuiTestContext ScreenShot (string title, TextWriter writer)
     {
-        writer.WriteLine (title + ":");
-        var text = Application.ToString ();
-
-        writer.WriteLine (text);
-
-        return this; //WaitIteration();
+        return WaitIteration (
+                              () =>
+                              {
+                                  writer.WriteLine (title + ":");
+                                  var text = Application.ToString ();
+
+                                  writer.WriteLine (text);
+                              });
     }
 
     /// <summary>
@@ -235,7 +261,10 @@ public class GuiTestContext : IDisposable
     /// <returns></returns>
     public GuiTestContext WriteOutLogs (TextWriter writer)
     {
-        writer.WriteLine (_logsSb.ToString ());
+        lock (_logsLock)
+        {
+            writer.WriteLine (_logsSb.ToString ());
+        }
 
         return this; //WaitIteration();
     }
@@ -254,14 +283,27 @@ public class GuiTestContext : IDisposable
             return this;
         }
 
+        if (Thread.CurrentThread.ManagedThreadId == Application.MainThreadId)
+        {
+            throw new NotSupportedException ("Cannot WaitIteration during Invoke");
+        }
+
         a ??= () => { };
         var ctsLocal = new CancellationTokenSource ();
 
         Application.Invoke (
                             () =>
                             {
-                                a ();
-                                ctsLocal.Cancel ();
+                                try
+                                {
+                                    a ();
+                                    ctsLocal.Cancel ();
+                                }
+                                catch (Exception e)
+                                {
+                                    _ex = e;
+                                    _hardStop.Cancel ();
+                                }
                             });
 
         // Blocks until either the token or the hardStopToken is cancelled.
@@ -286,10 +328,11 @@ public class GuiTestContext : IDisposable
     {
         try
         {
-            doAction ();
+            WaitIteration (doAction);
         }
-        catch (Exception)
+        catch (Exception ex)
         {
+            _ex = ex;
             HardStop ();
 
             throw;
@@ -322,10 +365,19 @@ public class GuiTestContext : IDisposable
 
     private GuiTestContext Click<T> (WindowsConsole.ButtonState btn, Func<T, bool> evaluator) where T : View
     {
-        T v = Find (evaluator);
-        Point screen = v.ViewportToScreen (new Point (0, 0));
+        T v;
+        var screen = Point.Empty;
+
+        GuiTestContext ctx = WaitIteration (
+                                            () =>
+                                            {
+                                                v = Find (evaluator);
+                                                screen = v.ViewportToScreen (new Point (0, 0));
+                                            });
+
+        Click (btn, screen.X, screen.Y);
 
-        return Click (btn, screen.X, screen.Y);
+        return ctx;
     }
 
     private GuiTestContext Click (WindowsConsole.ButtonState btn, int screenX, int screenY)
@@ -356,6 +408,8 @@ public class GuiTestContext : IDisposable
                                                    }
                                                });
 
+                return WaitUntil (() => _winInput.InputBuffer.IsEmpty);
+
                 break;
             case V2TestDriver.V2Net:
 
@@ -370,17 +424,31 @@ public class GuiTestContext : IDisposable
 
                 foreach (ConsoleKeyInfo k in NetSequences.Click (netButton, screenX, screenY))
                 {
-                    SendNetKey (k);
+                    SendNetKey (k, false);
                 }
 
-                break;
+                return WaitIteration ();
             default:
                 throw new ArgumentOutOfRangeException ();
         }
+    }
 
-        return WaitIteration ();
+    private GuiTestContext WaitUntil (Func<bool> condition)
+    {
+        GuiTestContext? c = null;
+        var sw = Stopwatch.StartNew ();
 
-        ;
+        while (!condition ())
+        {
+            if (sw.Elapsed > With.Timeout)
+            {
+                throw new TimeoutException ("Failed to reach condition within the time limit");
+            }
+
+            c = WaitIteration ();
+        }
+
+        return c ?? this;
     }
 
     public GuiTestContext Down ()
@@ -648,7 +716,15 @@ public class GuiTestContext : IDisposable
         WaitIteration ();
     }
 
-    private void SendNetKey (ConsoleKeyInfo consoleKeyInfo) { _netInput.InputBuffer.Enqueue (consoleKeyInfo); }
+    private void SendNetKey (ConsoleKeyInfo consoleKeyInfo, bool wait = true)
+    {
+        _netInput.InputBuffer.Enqueue (consoleKeyInfo);
+
+        if (wait)
+        {
+            WaitUntil (() => _netInput.InputBuffer.IsEmpty);
+        }
+    }
 
     /// <summary>
     ///     Sends a special key e.g. cursor key that does not map to a specific character
@@ -697,7 +773,7 @@ public class GuiTestContext : IDisposable
     /// <returns></returns>
     public GuiTestContext RaiseKeyDownEvent (Key key)
     {
-        Application.RaiseKeyDownEvent (key);
+        WaitIteration (() => Application.RaiseKeyDownEvent (key));
 
         return this; //WaitIteration();
     }
@@ -728,9 +804,11 @@ public class GuiTestContext : IDisposable
     ///     is found (of Type T) or all views are looped through (back to the beginning)
     ///     in which case triggers hard stop and Exception
     /// </summary>
-    /// <param name="evaluator">Delegate that returns true if the passed View is the one
-    /// you are trying to focus. Leave <see langword="null"/> to focus the first view of type
-    /// <typeparamref name="T"/></param>
+    /// <param name="evaluator">
+    ///     Delegate that returns true if the passed View is the one
+    ///     you are trying to focus. Leave <see langword="null"/> to focus the first view of type
+    ///     <typeparamref name="T"/>
+    /// </param>
     /// <returns></returns>
     /// <exception cref="ArgumentException"></exception>
     public GuiTestContext Focus<T> (Func<T, bool>? evaluator = null) where T : View
@@ -760,11 +838,14 @@ public class GuiTestContext : IDisposable
             // No, try tab to the next (or first)
             Tab ();
             WaitIteration ();
+
             next = t.MostFocused;
 
             if (next is null)
             {
-                Fail ("Failed to tab to a view which matched the Type and evaluator constraints of the test because MostFocused became or was always null");
+                Fail (
+                      "Failed to tab to a view which matched the Type and evaluator constraints of the test because MostFocused became or was always null"
+                      + DescribeSeenViews (seen));
 
                 return this;
             }
@@ -773,7 +854,9 @@ public class GuiTestContext : IDisposable
             // We have looped around to the start again if it was already there
             if (!seen.Add (next))
             {
-                Fail ("Failed to tab to a view which matched the Type and evaluator constraints of the test before looping back to the original View");
+                Fail (
+                      "Failed to tab to a view which matched the Type and evaluator constraints of the test before looping back to the original View"
+                      + DescribeSeenViews (seen));
 
                 return this;
             }
@@ -781,6 +864,8 @@ public class GuiTestContext : IDisposable
         while (true);
     }
 
+    private string DescribeSeenViews (HashSet<View> seen) { return Environment.NewLine + string.Join (Environment.NewLine, seen); }
+
     private T Find<T> (Func<T, bool> evaluator) where T : View
     {
         Toplevel? t = Application.Top;
@@ -830,25 +915,70 @@ public class GuiTestContext : IDisposable
 
     public GuiTestContext Send (Key key)
     {
-        if (Application.Driver is IConsoleDriverFacade facade)
-        {
-            facade.InputProcessor.OnKeyDown (key);
-            facade.InputProcessor.OnKeyUp (key);
-        }
-        else
-        {
-            Fail ("Expected Application.Driver to be IConsoleDriverFacade");
-        }
-
-        return this;
+        return WaitIteration (
+                              () =>
+                              {
+                                  if (Application.Driver is IConsoleDriverFacade facade)
+                                  {
+                                      facade.InputProcessor.OnKeyDown (key);
+                                      facade.InputProcessor.OnKeyUp (key);
+                                  }
+                                  else
+                                  {
+                                      Fail ("Expected Application.Driver to be IConsoleDriverFacade");
+                                  }
+                              });
     }
 
     /// <summary>
-    /// Returns the last set position of the cursor.
+    ///     Returns the last set position of the cursor.
     /// </summary>
     /// <returns></returns>
-    public Point GetCursorPosition ()
+    public Point GetCursorPosition () { return _output.CursorPosition; }
+}
+
+internal class FakeWindowsComponentFactory : WindowsComponentFactory
+{
+    private readonly FakeWindowsInput _winInput;
+    private readonly FakeOutput _output;
+    private readonly FakeSizeMonitor _fakeSizeMonitor;
+
+    public FakeWindowsComponentFactory (FakeWindowsInput winInput, FakeOutput output, FakeSizeMonitor fakeSizeMonitor)
     {
-        return _output.CursorPosition;
+        _winInput = winInput;
+        _output = output;
+        _fakeSizeMonitor = fakeSizeMonitor;
     }
+
+    /// <inheritdoc/>
+    public override IConsoleInput<WindowsConsole.InputRecord> CreateInput () { return _winInput; }
+
+    /// <inheritdoc/>
+    public override IConsoleOutput CreateOutput () { return _output; }
+
+    /// <inheritdoc/>
+    public override IWindowSizeMonitor CreateWindowSizeMonitor (IConsoleOutput consoleOutput, IOutputBuffer outputBuffer) { return _fakeSizeMonitor; }
+}
+
+internal class FakeNetComponentFactory : NetComponentFactory
+{
+    private readonly FakeNetInput _netInput;
+    private readonly FakeOutput _output;
+    private readonly FakeSizeMonitor _fakeSizeMonitor;
+
+    public FakeNetComponentFactory (FakeNetInput netInput, FakeOutput output, FakeSizeMonitor fakeSizeMonitor)
+    {
+        _netInput = netInput;
+        _output = output;
+        _fakeSizeMonitor = fakeSizeMonitor;
+    }
+
+    /// <inheritdoc/>
+    public override IConsoleInput<ConsoleKeyInfo> CreateInput () { return _netInput; }
+
+    /// <inheritdoc/>
+    public override IConsoleOutput CreateOutput () { return _output; }
+
+    /// <inheritdoc/>
+    public override IWindowSizeMonitor CreateWindowSizeMonitor (IConsoleOutput consoleOutput, IOutputBuffer outputBuffer) { return _fakeSizeMonitor; }
 }

+ 31 - 0
Tests/TerminalGuiFluentTesting/ThreadSafeStringWriter.cs

@@ -0,0 +1,31 @@
+using System.Text;
+
+namespace TerminalGuiFluentTesting;
+
+class ThreadSafeStringWriter : StringWriter
+{
+    private readonly object _lock;
+
+    public ThreadSafeStringWriter (StringBuilder sb, object syncLock) : base (sb)
+    {
+        _lock = syncLock;
+    }
+
+    public override void Write (char value)
+    {
+        lock (_lock)
+        {
+            base.Write (value);
+        }
+    }
+
+    public override void Write (string? value)
+    {
+        lock (_lock)
+        {
+            base.Write (value);
+        }
+    }
+
+    // (override other Write* methods as needed)
+}

+ 7 - 7
Tests/TerminalGuiFluentTesting/With.cs

@@ -12,24 +12,24 @@ public static class With
     /// <param name="width"></param>
     /// <param name="height"></param>
     /// <param name="v2TestDriver">Which v2 v2TestDriver to use for the test</param>
+    /// <param name="logWriter"></param>
     /// <returns></returns>
-    public static GuiTestContext A<T> (int width, int height, V2TestDriver v2TestDriver) where T : Toplevel, new ()
+    public static GuiTestContext A<T> (int width, int height, V2TestDriver v2TestDriver, TextWriter? logWriter = null) where T : Toplevel, new ()
     {
-        return new (() => new T (), width, height,v2TestDriver);
+        return new (() => new T (), width, height,v2TestDriver,logWriter);
     }
 
     /// <summary>
-    /// Overload that takes an existing instance <paramref name="toplevel"/>
-    /// instead of creating one.
+    /// Overload that takes a function to create instance <paramref name="toplevelFactory"/> after application is initialized.
     /// </summary>
-    /// <param name="toplevel"></param>
+    /// <param name="toplevelFactory"></param>
     /// <param name="width"></param>
     /// <param name="height"></param>
     /// <param name="v2TestDriver"></param>
     /// <returns></returns>
-    public static GuiTestContext A (Toplevel toplevel, int width, int height, V2TestDriver v2TestDriver)
+    public static GuiTestContext A (Func<Toplevel> toplevelFactory, int width, int height, V2TestDriver v2TestDriver)
     {
-        return new (()=>toplevel, width, height, v2TestDriver);
+        return new (toplevelFactory, width, height, v2TestDriver);
     }
     /// <summary>
     ///     The global timeout to allow for any given application to run for before shutting down.

+ 2 - 2
Tests/TerminalGuiFluentTestingXunit.Generator/TheGenerator.cs

@@ -123,9 +123,9 @@ public class TheGenerator : IIncrementalGenerator
                                {
                                    Assert.{{methodName}}{{typeParams}} ({{string.Join (",", paramNames)}});
                                }
-                               catch(Exception)
+                               catch(Exception ex)
                                {
-                                   context.HardStop ();
+                                   context.HardStop (ex);
                                    
                                
                                    throw;

+ 53 - 82
Tests/UnitTests/Application/ApplicationTests.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
+using System.Reflection;
 using UnitTests;
 using Xunit.Abstractions;
 using static Terminal.Gui.Configuration.ConfigurationManager;
@@ -40,7 +41,9 @@ public class ApplicationTests
 
         Application.InitializedChanged += OnApplicationOnInitializedChanged;
 
-        Application.Init (new FakeDriver ());
+        var a = new AutoInitShutdownAttribute ();
+        a.Before (null);
+
         Assert.True (initialized);
         Assert.False (shutdown);
 
@@ -76,6 +79,8 @@ public class ApplicationTests
             _timeoutLock = null;
         }
 
+
+        a.After (null);
         return;
 
         void OnApplicationOnInitializedChanged (object s, EventArgs<bool> a)
@@ -143,15 +148,13 @@ public class ApplicationTests
     }
 
     [Fact]
+    [AutoInitShutdown]
     public void Begin_Null_Toplevel_Throws ()
     {
-        // Setup Mock driver
-        Init ();
-
         // Test null Toplevel
         Assert.Throws<ArgumentNullException> (() => Application.Begin (null));
 
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -163,21 +166,21 @@ public class ApplicationTests
     public void Begin_Sets_Application_Top_To_Console_Size ()
     {
         Assert.Null (Application.Top);
+        AutoInitShutdownAttribute.FakeResize (new Size (80,25));
         Toplevel top = new ();
         Application.Begin (top);
         Assert.Equal (new (0, 0, 80, 25), Application.Top!.Frame);
-        ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(5, 5));
         Assert.Equal (new (0, 0, 5, 5), Application.Top!.Frame);
         top.Dispose ();
     }
 
     [Fact]
+    [AutoInitShutdown]
     public void End_And_Shutdown_Should_Not_Dispose_ApplicationTop ()
     {
         Assert.Null (Application.Top);
 
-        Init ();
-
         RunState rs = Application.Begin (new ());
         Application.Top!.Title = "End_And_Shutdown_Should_Not_Dispose_ApplicationTop";
         Assert.Equal (rs.Toplevel, Application.Top);
@@ -193,25 +196,24 @@ public class ApplicationTests
         Toplevel top = Application.Top;
 
 #if DEBUG_IDISPOSABLE
-        Exception exception = Record.Exception (() => Shutdown ());
+        Exception exception = Record.Exception (Application.Shutdown);
         Assert.NotNull (exception);
         Assert.False (top.WasDisposed);
         top.Dispose ();
         Assert.True (top.WasDisposed);
 #endif
-        Shutdown ();
+        Application.Shutdown ();
         Assert.Null (Application.Top);
     }
 
     [Fact]
+    [AutoInitShutdown]
     public void Init_Begin_End_Cleans_Up ()
     {
         // Start stopwatch
         Stopwatch stopwatch = new Stopwatch ();
         stopwatch.Start ();
 
-        Init ();
-
         // Begin will cause Run() to be called, which will call Begin(). Thus will block the tests
         // if we don't stop
         Application.Iteration += (s, a) => { Application.RequestStop (); };
@@ -237,14 +239,12 @@ public class ApplicationTests
         Application.End (runstate);
 
         Assert.NotNull (Application.Top);
-        Assert.NotNull (Application.MainLoop);
         Assert.NotNull (Application.Driver);
 
         topLevel.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
-        Assert.Null (Application.MainLoop);
         Assert.Null (Application.Driver);
 
         // Stop stopwatch
@@ -255,7 +255,6 @@ public class ApplicationTests
     }
 
     [Theory]
-    [InlineData (typeof (FakeDriver))]
     [InlineData (typeof (NetDriver))]
 
     //[InlineData (typeof (ANSIDriver))]
@@ -268,7 +267,7 @@ public class ApplicationTests
         Assert.NotNull (Application.Driver);
         Assert.NotEqual (driver, Application.Driver);
         Assert.Equal (driverType, Application.Driver?.GetType ());
-        Shutdown ();
+        Application.Shutdown ();
     }
 
     [Fact]
@@ -278,7 +277,7 @@ public class ApplicationTests
 
         Assert.NotNull (Application.Driver);
 
-        Shutdown ();
+        Application.Shutdown ();
     }
 
     [Theory]
@@ -468,7 +467,7 @@ public class ApplicationTests
                                                                                 new FakeDriver ()
                                                                                )
                                                  );
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -478,7 +477,7 @@ public class ApplicationTests
         Application.InternalInit (new FakeDriver ());
 
         Assert.Throws<InvalidOperationException> (() => Application.Init (new FakeDriver ()));
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -521,7 +520,7 @@ public class ApplicationTests
         Assert.NotNull (Application.Driver);
 
         topLevel.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -645,34 +644,13 @@ public class ApplicationTests
         Assert.Throws<ArgumentNullException> (static () => Application.SubscribeDriverEvents ());
     }
 
-    private void Init ()
-    {
-        Application.Init (new FakeDriver ());
-        Assert.NotNull (Application.Driver);
-        Assert.NotNull (Application.MainLoop);
-        Assert.NotNull (SynchronizationContext.Current);
-    }
-
-    private void Shutdown ()
-    {
-        if (ApplicationImpl.Instance is ApplicationV2)
-        {
-            ApplicationImpl.Instance.Shutdown ();
-        }
-        else
-        {
-            Application.Shutdown ();
-        }
-    }
 
     #region RunTests
 
     [Fact]
+    [AutoInitShutdown]
     public void Run_T_After_InitWithDriver_with_TopLevel_Does_Not_Throws ()
     {
-        // Setup Mock driver
-        Init ();
-
         Application.Iteration += (s, e) => Application.RequestStop ();
 
         // Run<Toplevel> when already initialized or not with a Driver will not throw (because Window is derived from Toplevel)
@@ -681,7 +659,7 @@ public class ApplicationTests
         Assert.True (Application.Top is Window);
 
         Application.Top!.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -691,9 +669,6 @@ public class ApplicationTests
     [Fact]
     public void Run_T_After_InitWithDriver_with_TopLevel_and_Driver_Does_Not_Throws ()
     {
-        // Setup Mock driver
-        Init ();
-
         Application.Iteration += (s, e) => Application.RequestStop ();
 
         // Run<Toplevel> when already initialized or not with a Driver will not throw (because Window is derived from Toplevel)
@@ -708,7 +683,7 @@ public class ApplicationTests
         Assert.True (Application.Top is Dialog);
 
         Application.Top!.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -716,10 +691,10 @@ public class ApplicationTests
     }
 
     [Fact]
+    [AutoInitShutdown]
     [TestRespondersDisposed]
     public void Run_T_After_Init_Does_Not_Disposes_Application_Top ()
     {
-        Init ();
 
         // Init doesn't create a Toplevel and assigned it to Application.Top
         // but Begin does
@@ -742,7 +717,7 @@ public class ApplicationTests
         Assert.True (initTop.WasDisposed);
 #endif
         Application.Top!.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -751,18 +726,16 @@ public class ApplicationTests
 
     [Fact]
     [TestRespondersDisposed]
+    [AutoInitShutdown]
     public void Run_T_After_InitWithDriver_with_TestTopLevel_DoesNotThrow ()
     {
-        // Setup Mock driver
-        Init ();
-
         Application.Iteration += (s, a) => { Application.RequestStop (); };
 
         // Init has been called and we're passing no driver to Run<TestTopLevel>. This is ok.
         Application.Run<Toplevel> ();
 
         Application.Top!.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -775,8 +748,8 @@ public class ApplicationTests
     {
         Application.ForceDriver = "FakeDriver";
 
-        Application.Init ();
-        Assert.Equal (typeof (FakeDriver), Application.Driver?.GetType ());
+        var a = new AutoInitShutdownAttribute ();
+        a.Before (null);
 
         Application.Iteration += (s, a) => { Application.RequestStop (); };
 
@@ -784,25 +757,26 @@ public class ApplicationTests
         Application.Run<Toplevel> ();
 
         Application.Top!.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
         Assert.Null (Application.Driver);
+
+        a.After (null);
     }
 
     [Fact]
     [TestRespondersDisposed]
+    [AutoInitShutdown]
     public void Run_T_Init_Driver_Cleared_with_TestTopLevel_Throws ()
     {
-        Init ();
-
         Application.Driver = null;
 
         // Init has been called, but Driver has been set to null. Bad.
         Assert.Throws<InvalidOperationException> (() => Application.Run<Toplevel> ());
 
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -821,7 +795,7 @@ public class ApplicationTests
         Assert.Equal (typeof (FakeDriver), Application.Driver?.GetType ());
 
         Application.Top!.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -838,7 +812,7 @@ public class ApplicationTests
         Application.Run<Toplevel> (null, new FakeDriver ());
 
         Application.Top!.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
 
         Assert.Null (Application.Top);
         Assert.Null (Application.MainLoop);
@@ -847,10 +821,11 @@ public class ApplicationTests
 
     [Fact]
     [TestRespondersDisposed]
+    [AutoInitShutdown]
     public void Run_RequestStop_Stops ()
     {
         // Setup Mock driver
-        Init ();
+        Application.Init ();
 
         var top = new Toplevel ();
         RunState rs = Application.Begin (top);
@@ -868,11 +843,9 @@ public class ApplicationTests
     }
 
     [Fact]
+    [AutoInitShutdown]
     public void Run_Sets_Running_True ()
     {
-        // Setup Mock driver
-        Init ();
-
         var top = new Toplevel ();
         RunState rs = Application.Begin (top);
         Assert.NotNull (rs);
@@ -894,11 +867,9 @@ public class ApplicationTests
 
     [Fact]
     [TestRespondersDisposed]
+    [AutoInitShutdown]
     public void Run_RunningFalse_Stops ()
     {
-        // Setup Mock driver
-        Init ();
-
         var top = new Toplevel ();
         RunState rs = Application.Begin (top);
         Assert.NotNull (rs);
@@ -915,10 +886,10 @@ public class ApplicationTests
     }
 
     [Fact]
+    [AutoInitShutdown]
     [TestRespondersDisposed]
     public void Run_Loaded_Ready_Unloaded_Events ()
     {
-        Init ();
         Toplevel top = new ();
         var count = 0;
         top.Loaded += (s, e) => count++;
@@ -933,17 +904,16 @@ public class ApplicationTests
 
     // TODO: All Toplevel layout tests should be moved to ToplevelTests.cs
     [Fact]
+    [AutoInitShutdown]
     public void Run_A_Modal_Toplevel_Refresh_Background_On_Moving ()
     {
-        Init ();
-
         // Don't use Dialog here as it has more layout logic. Use Window instead.
         var w = new Window
         {
             Width = 5, Height = 5,
             Arrangement = ViewArrangement.Movable
         };
-        ((FakeDriver)Application.Driver!).SetBufferSize (10, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(10, 10));
         RunState rs = Application.Begin (w);
 
         // Don't use visuals to test as style of border can change over time.
@@ -963,10 +933,9 @@ public class ApplicationTests
     }
 
     [Fact]
+    [AutoInitShutdown]
     public void End_Does_Not_Dispose ()
     {
-        Init ();
-
         var top = new Toplevel ();
 
         Window w = new ();
@@ -1117,8 +1086,12 @@ public class ApplicationTests
     private readonly object _forceDriverLock = new ();
 
     [Theory]
-    [InlineData ("v2win", typeof (ConsoleDriverFacade<WindowsConsole.InputRecord>))]
-    [InlineData ("v2net", typeof (ConsoleDriverFacade<ConsoleKeyInfo>))]
+
+    // This test wants to Run which results in console handle errors, it wants to rely non drivers checking ConsoleDriver.RunningUnitTests
+    // And suppressing things that might fail, this is anti pattern, instead we should test this kind of thing with  Mocking
+    //    [InlineData ("v2win", typeof (ConsoleDriverFacade<WindowsConsole.InputRecord>))]
+    //    [InlineData ("v2net", typeof (ConsoleDriverFacade<ConsoleKeyInfo>))]
+
     [InlineData ("FakeDriver", typeof (FakeDriver))]
     [InlineData ("NetDriver", typeof (NetDriver))]
     [InlineData ("WindowsDriver", typeof (WindowsDriver))]
@@ -1160,7 +1133,7 @@ public class ApplicationTests
         Assert.NotNull (Application.Top);
         Assert.False (Application.Top!.Running);
         Application.Top!.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
         Assert.True (result);
     }
 
@@ -1176,7 +1149,7 @@ public class ApplicationTests
         Assert.NotNull (Application.Top);
         Assert.False (Application.Top!.Running);
         Application.Top!.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
     }
 
     [Fact]
@@ -1203,7 +1176,7 @@ public class ApplicationTests
         Assert.NotNull (Application.Top);
         Assert.False (Application.Top!.Running);
         Application.Top!.Dispose ();
-        Shutdown ();
+        Application.Shutdown ();
     }
 
     // TODO: Add tests for Run that test errorHandler
@@ -1225,7 +1198,6 @@ public class ApplicationTests
             isCompletedSuccessfully = true;
         }
 
-        Init ();
         Application.Shutdown ();
 
         Assert.False (isCompletedSuccessfully);
@@ -1237,7 +1209,6 @@ public class ApplicationTests
     [Fact]
     public void Shutdown_Resets_SyncContext ()
     {
-        Init ();
         Application.Shutdown ();
         Assert.Null (SynchronizationContext.Current);
     }

+ 41 - 4
Tests/UnitTests/AutoInitShutdownAttribute.cs

@@ -49,7 +49,7 @@ public class AutoInitShutdownAttribute : BeforeAfterTestAttribute
     {
         AutoInit = autoInit;
         CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
-        _driverType = consoleDriverType ?? typeof (FakeDriver);
+        _driverType = consoleDriverType;
         FakeDriver.FakeBehaviors.UseFakeClipboard = useFakeClipboard;
         FakeDriver.FakeBehaviors.FakeClipboardAlwaysThrowsNotSupportedException =
             fakeClipboardAlwaysThrowsNotSupportedException;
@@ -59,14 +59,17 @@ public class AutoInitShutdownAttribute : BeforeAfterTestAttribute
 
     private readonly bool _verifyShutdown;
     private readonly Type _driverType;
+    private IDisposable _v2Cleanup;
 
     public override void After (MethodInfo methodUnderTest)
     {
-        Debug.WriteLine ($"After: {methodUnderTest.Name}");
+        Debug.WriteLine ($"After: {methodUnderTest?.Name ?? "Unknown Test"}");
 
         // Turn off diagnostic flags in case some test left them on
         View.Diagnostics = ViewDiagnosticFlags.Off;
 
+        _v2Cleanup?.Dispose ();
+
         if (AutoInit)
         {
             // try
@@ -109,7 +112,7 @@ public class AutoInitShutdownAttribute : BeforeAfterTestAttribute
 
     public override void Before (MethodInfo methodUnderTest)
     {
-        Debug.WriteLine ($"Before: {methodUnderTest.Name}");
+        Debug.WriteLine ($"Before: {methodUnderTest?.Name ?? "Unknown Test"}");
 
         // Disable & force the ConfigurationManager to reset to its hardcoded defaults
         CM.Disable (true);
@@ -131,9 +134,43 @@ public class AutoInitShutdownAttribute : BeforeAfterTestAttribute
                 View.Instances.Clear ();
             }
 #endif
-            Application.Init ((IConsoleDriver)Activator.CreateInstance (_driverType));
+            if (_driverType == null)
+            {
+                Application.Top = null;
+                Application.TopLevels.Clear ();
+
+                var fa = new FakeApplicationFactory ();
+                _v2Cleanup = fa.SetupFakeApplication ();
+                AutoInitShutdownAttribute.FakeResize (new Size (80,25));
+            }
+            else
+            {
+                Application.Init ((IConsoleDriver)Activator.CreateInstance (_driverType));
+            }
         }
     }
 
     private bool AutoInit { get; }
+
+    /// <summary>
+    /// 'Resizes' the application and forces layout. Only works if your test uses <see cref="AutoInitShutdownAttribute"/>
+    /// </summary>
+    /// <param name="size"></param>
+    public static void FakeResize (Size size)
+    {
+        var d = (IConsoleDriverFacade)Application.Driver!;
+        d.OutputBuffer.SetWindowSize (size.Width, size.Height);
+        ((FakeSizeMonitor)d.WindowSizeMonitor).RaiseSizeChanging (size);
+
+        Application.LayoutAndDrawImpl ();
+    }
+
+    /// <summary>
+    /// Runs a single iteration of the main loop (layout, draw, run timed events etc.)
+    /// </summary>
+    public static void RunIteration ()
+    {
+        var a = (ApplicationV2)ApplicationImpl.Instance;
+        a.Coordinator?.RunIteration ();
+    }
 }

+ 1 - 1
Tests/UnitTests/ConsoleDrivers/ConsoleDriverTests.cs

@@ -235,7 +235,7 @@ public class ConsoleDriverTests
     //		{
     //			var win = new Window ();
     //			Application.Begin (win);
-    //			((FakeDriver)Application.Driver!).SetBufferSize (20, 8);
+    //			AutoInitShutdownAttribute.FakeResize(new Size ( (20, 8);
 
     //			System.Threading.Tasks.Task.Run (() => {
     //				System.Threading.Tasks.Task.Delay (500).Wait ();

+ 32 - 14
Tests/UnitTests/ConsoleDrivers/V2/ApplicationV2Tests.cs

@@ -3,6 +3,7 @@ using System.Collections.Concurrent;
 using System.Runtime.CompilerServices;
 using Microsoft.Extensions.Logging;
 using Moq;
+using TerminalGuiFluentTesting;
 
 namespace UnitTests.ConsoleDrivers.V2;
 public class ApplicationV2Tests
@@ -12,18 +13,34 @@ public class ApplicationV2Tests
         ConsoleDriver.RunningUnitTests = true;
     }
 
-    private ApplicationV2 NewApplicationV2 ()
+    private ApplicationV2 NewApplicationV2 (V2TestDriver driver = V2TestDriver.V2Net)
     {
-        var netInput = new Mock<INetInput> ();
-        SetupRunInputMockMethodToBlock (netInput);
-        var winInput = new Mock<IWindowsInput> ();
-        SetupRunInputMockMethodToBlock (winInput);
 
-        return new (
-                    () => netInput.Object,
-                    Mock.Of<IConsoleOutput>,
-                    () => winInput.Object,
-                    Mock.Of<IConsoleOutput>);
+        if (driver == V2TestDriver.V2Net)
+        {
+            var netInput = new Mock<INetInput> ();
+            SetupRunInputMockMethodToBlock (netInput);
+
+            var m = new Mock<IComponentFactory<ConsoleKeyInfo>> ();
+            m.Setup (f => f.CreateInput ()).Returns (netInput.Object);
+            m.Setup (f => f.CreateInputProcessor (It.IsAny<ConcurrentQueue<ConsoleKeyInfo>> ())).Returns (Mock.Of <IInputProcessor> ());
+            m.Setup (f => f.CreateOutput ()).Returns (Mock.Of<IConsoleOutput> ());
+            m.Setup (f => f.CreateWindowSizeMonitor (It.IsAny<IConsoleOutput> (),It.IsAny<IOutputBuffer> ())).Returns (Mock.Of<IWindowSizeMonitor> ());
+
+            return new (m.Object);
+        }
+        else
+        {
+
+            var winInput = new Mock<IConsoleInput<WindowsConsole.InputRecord>> ();
+            SetupRunInputMockMethodToBlock (winInput);
+            var m = new Mock<IComponentFactory<WindowsConsole.InputRecord>> ();
+            m.Setup (f => f.CreateInput ()).Returns (winInput.Object);
+            m.Setup (f => f.CreateInputProcessor (It.IsAny<ConcurrentQueue<WindowsConsole.InputRecord>> ())).Returns (Mock.Of<IInputProcessor> ());
+            m.Setup (f => f.CreateOutput ()).Returns (Mock.Of<IConsoleOutput> ());
+            m.Setup (f => f.CreateWindowSizeMonitor (It.IsAny<IConsoleOutput> (), It.IsAny<IOutputBuffer> ())).Returns (Mock.Of<IWindowSizeMonitor> ());
+            return new (m.Object);
+        }
     }
 
     [Fact]
@@ -68,7 +85,7 @@ public class ApplicationV2Tests
 
         ApplicationImpl.ChangeInstance (orig);
     }
-
+    /*
     [Fact]
     public void Init_ExplicitlyRequestWin ()
     {
@@ -150,8 +167,8 @@ public class ApplicationV2Tests
 
         ApplicationImpl.ChangeInstance (orig);
     }
-
-    private void SetupRunInputMockMethodToBlock (Mock<IWindowsInput> winInput)
+*/
+    private void SetupRunInputMockMethodToBlock (Mock<IConsoleInput<WindowsConsole.InputRecord>> winInput)
     {
         winInput.Setup (r => r.Run (It.IsAny<CancellationToken> ()))
                 .Callback<CancellationToken> (token =>
@@ -473,7 +490,7 @@ public class ApplicationV2Tests
 
         return true;
     }
-
+    /*
     [Fact]
     public void Shutdown_Called_Repeatedly_DoNotDuplicateDisposeOutput ()
     {
@@ -500,6 +517,7 @@ public class ApplicationV2Tests
 
         ApplicationImpl.ChangeInstance (orig);
     }
+    */
 
     [Fact]
     public void Init_Called_Repeatedly_WarnsAndIgnores ()

+ 6 - 6
Tests/UnitTests/ConsoleDrivers/V2/MainLoopCoordinatorTests.cs

@@ -14,15 +14,15 @@ public class MainLoopCoordinatorTests
         var beforeLogger = Logging.Logger;
         Logging.Logger = mockLogger.Object;
 
-        var c = new MainLoopCoordinator<char> (new TimedEvents (),
-                                               // Runs on a separate thread (input thread)
-                                               () => throw new Exception ("Crash on boot"),
+        var m = new Mock<IComponentFactory<char>> ();
+        // Runs on a separate thread (input thread)
+        m.Setup (f => f.CreateInput ()).Throws (new Exception ("Crash on boot"));
 
+        var c = new MainLoopCoordinator<char> (new TimedEvents (),
                                                // Rest runs on main thread
                                                new ConcurrentQueue<char> (),
-                                               Mock.Of <IInputProcessor>(),
-                                               ()=>Mock.Of<IConsoleOutput>(),
-                                               Mock.Of<IMainLoop<char>>());
+                                               Mock.Of<IMainLoop<char>>(),
+                                               m.Object);
 
         // StartAsync boots the main loop and the input thread. But if the input class bombs
         // on startup it is important that the exception surface at the call site and not lost

+ 11 - 1
Tests/UnitTests/ConsoleDrivers/V2/MainLoopTTests.cs

@@ -18,10 +18,20 @@ public class MainLoopTTests
         Assert.Throws<NotInitializedException> (() => m.AnsiRequestScheduler);
         Assert.Throws<NotInitializedException> (() => m.WindowSizeMonitor);
 
+        var componentFactory = new Mock<IComponentFactory<int>> ();
+
+        componentFactory.Setup (
+                                c => c.CreateWindowSizeMonitor (
+                                                                It.IsAny<IConsoleOutput> (),
+                                                                It.IsAny<IOutputBuffer> ()))
+                        .Returns (Mock.Of <IWindowSizeMonitor>());
+
         m.Initialize (new TimedEvents (),
                       new ConcurrentQueue<int> (),
                       Mock.Of <IInputProcessor>(),
-                      Mock.Of<IConsoleOutput>());
+                      Mock.Of<IConsoleOutput>(),
+                      componentFactory.Object
+                     );
 
         Assert.NotNull (m.TimedEvents);
         Assert.NotNull (m.InputBuffer);

+ 62 - 67
Tests/UnitTests/Dialogs/DialogTests.cs

@@ -13,8 +13,6 @@ public class DialogTests (ITestOutputHelper output)
     {
         RunState? runState = null;
 
-        var d = (FakeDriver)Driver!;
-
         var title = "1234";
         var btn1Text = "yes";
         var btn1 = $"{Glyphs.LeftBracket} {btn1Text} {Glyphs.RightBracket}";
@@ -23,7 +21,7 @@ public class DialogTests (ITestOutputHelper output)
 
         // We test with one button first, but do this to get the width right for 2
         int width = $@"{Glyphs.VLine} {btn1} {btn2} {Glyphs.VLine}".Length;
-        d.SetBufferSize (width, 1);
+        AutoInitShutdownAttribute.FakeResize(new(width, 1));
 
         // Override CM
         Dialog.DefaultButtonAlignment = Alignment.Center;
@@ -46,7 +44,7 @@ public class DialogTests (ITestOutputHelper output)
         runState = Begin (dlg);
         var buttonRow = $"{Glyphs.VLine}    {btn1}     {Glyphs.VLine}";
 
-        RunIteration (ref runState);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
 
@@ -54,7 +52,7 @@ public class DialogTests (ITestOutputHelper output)
         buttonRow = $"{Glyphs.VLine} {btn1} {btn2} {Glyphs.VLine}";
         dlg.AddButton (new () { Text = btn2Text });
 
-        RunIteration (ref runState);
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
         End (runState);
         dlg.Dispose ();
@@ -73,7 +71,7 @@ public class DialogTests (ITestOutputHelper output)
         dlg.Border!.Thickness = new (1, 0, 1, 0);
         runState = Begin (dlg);
 
-        RunIteration (ref runState);
+        AutoInitShutdownAttribute.RunIteration ();
 
         buttonRow = $"{Glyphs.VLine}{btn1}         {Glyphs.VLine}";
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
@@ -81,7 +79,7 @@ public class DialogTests (ITestOutputHelper output)
         // Now add a second button
         buttonRow = $"{Glyphs.VLine}{btn1}   {btn2}{Glyphs.VLine}";
         dlg.AddButton (new () { Text = btn2Text });
-        RunIteration (ref runState);
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
         End (runState);
         dlg.Dispose ();
@@ -100,7 +98,7 @@ public class DialogTests (ITestOutputHelper output)
         dlg.Border!.Thickness = new (1, 0, 1, 0);
         runState = Begin (dlg);
 
-        RunIteration (ref runState);
+        AutoInitShutdownAttribute.RunIteration ();
 
         buttonRow = $"{Glyphs.VLine}{new (' ', width - btn1.Length - 2)}{btn1}{Glyphs.VLine}";
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
@@ -109,7 +107,7 @@ public class DialogTests (ITestOutputHelper output)
         buttonRow = $"{Glyphs.VLine}  {btn1} {btn2}{Glyphs.VLine}";
         dlg.AddButton (new () { Text = btn2Text });
 
-        RunIteration (ref runState);
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
         End (runState);
         dlg.Dispose ();
@@ -127,7 +125,7 @@ public class DialogTests (ITestOutputHelper output)
         // Create with no top or bottom border to simplify testing button layout (no need to account for title etc..)
         dlg.Border!.Thickness = new (1, 0, 1, 0);
         runState = Begin (dlg);
-        RunIteration (ref runState);
+        AutoInitShutdownAttribute.RunIteration ();
 
         buttonRow = $"{Glyphs.VLine}{btn1}{new (' ', width - btn1.Length - 2)}{Glyphs.VLine}";
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
@@ -136,7 +134,7 @@ public class DialogTests (ITestOutputHelper output)
         buttonRow = $"{Glyphs.VLine}{btn1} {btn2}  {Glyphs.VLine}";
         dlg.AddButton (new () { Text = btn2Text });
 
-        RunIteration (ref runState);
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
         End (runState);
         dlg.Dispose ();
@@ -148,7 +146,6 @@ public class DialogTests (ITestOutputHelper output)
     {
         RunState? runState = null;
 
-        var d = (FakeDriver)Driver!;
         Dialog.DefaultShadow = ShadowStyle.None;
         Button.DefaultShadow = ShadowStyle.None;
 
@@ -166,7 +163,8 @@ public class DialogTests (ITestOutputHelper output)
 
         var buttonRow = $"{Glyphs.VLine} {btn1} {btn2} {btn3} {btn4} {Glyphs.VLine}";
         int width = buttonRow.Length;
-        d.SetBufferSize (buttonRow.Length, 3);
+
+        AutoInitShutdownAttribute.FakeResize(new (buttonRow.Length, 3));
 
         // Default - Center
         (runState, Dialog dlg) = BeginButtonTestDialog (
@@ -195,6 +193,7 @@ public class DialogTests (ITestOutputHelper output)
                                                  new Button { Text = btn3Text },
                                                  new Button { Text = btn4Text }
                                                 );
+
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
         End (runState);
         dlg.Dispose ();
@@ -240,7 +239,6 @@ public class DialogTests (ITestOutputHelper output)
     {
         RunState? runState = null;
 
-        var d = (FakeDriver)Driver!;
         Dialog.DefaultShadow = ShadowStyle.None;
         Button.DefaultShadow = ShadowStyle.None;
 
@@ -258,7 +256,7 @@ public class DialogTests (ITestOutputHelper output)
         var buttonRow = string.Empty;
 
         var width = 30;
-        d.SetBufferSize (width, 1);
+        AutoInitShutdownAttribute.FakeResize(new(width, 1));
 
         // Default - Center
         buttonRow =
@@ -335,7 +333,6 @@ public class DialogTests (ITestOutputHelper output)
     {
         RunState? runState = null;
 
-        var d = (FakeDriver)Driver!;
         Dialog.DefaultShadow = ShadowStyle.None;
         Button.DefaultShadow = ShadowStyle.None;
 
@@ -355,7 +352,7 @@ public class DialogTests (ITestOutputHelper output)
         //                         123456                          1234567
         var buttonRow = $"{Glyphs.VLine}      {btn1} {btn2} {btn3} {btn4}      {Glyphs.VLine}";
         int width = buttonRow.Length;
-        d.SetBufferSize (buttonRow.Length, 1);
+        AutoInitShutdownAttribute.FakeResize (new (buttonRow.Length, 1));
 
         // Default - Center
         (runState, Dialog dlg) = BeginButtonTestDialog (
@@ -429,7 +426,6 @@ public class DialogTests (ITestOutputHelper output)
     {
         RunState? runState = null;
 
-        var d = (FakeDriver)Driver!;
         Dialog.DefaultShadow = ShadowStyle.None;
         Button.DefaultShadow = ShadowStyle.None;
 
@@ -451,7 +447,7 @@ public class DialogTests (ITestOutputHelper output)
         //                         123456                           123456
         var buttonRow = $"{Glyphs.VLine}      {btn1} {btn2} {btn3} {btn4}      {Glyphs.VLine}";
         int width = buttonRow.GetColumns ();
-        d.SetBufferSize (width, 3);
+        AutoInitShutdownAttribute.FakeResize(new(width, 3));
 
         // Default - Center
         (runState, Dialog dlg) = BeginButtonTestDialog (
@@ -523,7 +519,6 @@ public class DialogTests (ITestOutputHelper output)
     [AutoInitShutdown]
     public void ButtonAlignment_One ()
     {
-        var d = (FakeDriver)Driver!;
         RunState? runState = null;
         Dialog.DefaultShadow = ShadowStyle.None;
         Button.DefaultShadow = ShadowStyle.None;
@@ -537,7 +532,7 @@ public class DialogTests (ITestOutputHelper output)
             $"{Glyphs.VLine}  {Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket}  {Glyphs.VLine}";
         int width = buttonRow.Length;
 
-        d.SetBufferSize (width, 1);
+        AutoInitShutdownAttribute.FakeResize(new(width, 1));
 
         (runState, Dialog dlg) = BeginButtonTestDialog (
                                                         title,
@@ -601,7 +596,7 @@ public class DialogTests (ITestOutputHelper output)
             $"{Glyphs.VLine}   {Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket}   {Glyphs.VLine}";
         width = buttonRow.Length;
 
-        d.SetBufferSize (width, 1);
+        AutoInitShutdownAttribute.FakeResize(new(width, 1));
 
         (runState, dlg) = BeginButtonTestDialog (
                                                  title,
@@ -665,7 +660,6 @@ public class DialogTests (ITestOutputHelper output)
     {
         RunState? runState = null;
 
-        var d = (FakeDriver)Driver!;
         Dialog.DefaultShadow = ShadowStyle.None;
         Button.DefaultShadow = ShadowStyle.None;
 
@@ -682,7 +676,7 @@ public class DialogTests (ITestOutputHelper output)
         var buttonRow = $@"{Glyphs.VLine} {btn1} {btn2} {btn3} {Glyphs.VLine}";
         int width = buttonRow.Length;
 
-        d.SetBufferSize (buttonRow.Length, 3);
+        AutoInitShutdownAttribute.FakeResize(new(buttonRow.Length, 3));
 
         (runState, Dialog dlg) = BeginButtonTestDialog (
                                                         title,
@@ -751,7 +745,6 @@ public class DialogTests (ITestOutputHelper output)
     {
         RunState? runState = null;
 
-        var d = (FakeDriver)Driver!;
         Dialog.DefaultShadow = ShadowStyle.None;
         Button.DefaultShadow = ShadowStyle.None;
 
@@ -766,7 +759,7 @@ public class DialogTests (ITestOutputHelper output)
         var buttonRow = $@"{Glyphs.VLine} {btn1} {btn2} {Glyphs.VLine}";
         int width = buttonRow.Length;
 
-        d.SetBufferSize (buttonRow.Length, 3);
+        AutoInitShutdownAttribute.FakeResize(new(buttonRow.Length, 3));
 
         (runState, Dialog dlg) = BeginButtonTestDialog (
                                                         title,
@@ -832,7 +825,6 @@ public class DialogTests (ITestOutputHelper output)
         RunState? runState = null;
         var firstIteration = false;
 
-        var d = (FakeDriver)Driver!;
         Dialog.DefaultShadow = ShadowStyle.None;
         Button.DefaultShadow = ShadowStyle.None;
 
@@ -847,7 +839,7 @@ public class DialogTests (ITestOutputHelper output)
         var buttonRow = $@"{Glyphs.VLine} {btn1} {btn2} {Glyphs.VLine}";
         int width = buttonRow.Length;
 
-        d.SetBufferSize (buttonRow.Length, 3);
+        AutoInitShutdownAttribute.FakeResize(new(buttonRow.Length, 3));
 
         Dialog dlg = null;
         Button button1, button2;
@@ -857,8 +849,10 @@ public class DialogTests (ITestOutputHelper output)
         button2 = new () { Text = btn2Text };
         (runState, dlg) = BeginButtonTestDialog (title, width, Alignment.Center, button1, button2);
         button1.Visible = false;
-        RunIteration (ref runState, firstIteration);
+        AutoInitShutdownAttribute.RunIteration ();
+
         buttonRow = $@"{Glyphs.VLine}         {btn2} {Glyphs.VLine}";
+
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
         End (runState);
         dlg.Dispose ();
@@ -869,7 +863,8 @@ public class DialogTests (ITestOutputHelper output)
         button2 = new () { Text = btn2Text };
         (runState, dlg) = BeginButtonTestDialog (title, width, Alignment.Fill, button1, button2);
         button1.Visible = false;
-        RunIteration (ref runState, firstIteration);
+        AutoInitShutdownAttribute.RunIteration ();
+
         buttonRow = $@"{Glyphs.VLine}          {btn2}{Glyphs.VLine}";
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
         End (runState);
@@ -881,7 +876,8 @@ public class DialogTests (ITestOutputHelper output)
         button2 = new () { Text = btn2Text };
         (runState, dlg) = BeginButtonTestDialog (title, width, Alignment.End, button1, button2);
         button1.Visible = false;
-        RunIteration (ref runState, firstIteration);
+        AutoInitShutdownAttribute.RunIteration ();
+
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
         End (runState);
         dlg.Dispose ();
@@ -892,7 +888,8 @@ public class DialogTests (ITestOutputHelper output)
         button2 = new () { Text = btn2Text };
         (runState, dlg) = BeginButtonTestDialog (title, width, Alignment.Start, button1, button2);
         button1.Visible = false;
-        RunIteration (ref runState, firstIteration);
+        AutoInitShutdownAttribute.RunIteration ();
+
         buttonRow = $@"{Glyphs.VLine}        {btn2}  {Glyphs.VLine}";
         DriverAssert.AssertDriverContentsWithFrameAre ($"{buttonRow}", output);
         End (runState);
@@ -903,7 +900,7 @@ public class DialogTests (ITestOutputHelper output)
     [AutoInitShutdown]
     public void Dialog_In_Window_With_Size_One_Button_Aligns ()
     {
-        ((FakeDriver)Driver!).SetBufferSize (20, 5);
+        AutoInitShutdownAttribute.FakeResize(new(20, 5));
 
         // Override CM
         Window.DefaultBorderStyle = LineStyle.Single;
@@ -931,7 +928,7 @@ public class DialogTests (ITestOutputHelper output)
 
                           dlg.Loaded += (s, a) =>
                                         {
-                                            LayoutAndDraw ();
+                                            AutoInitShutdownAttribute.RunIteration ();
 
                                             var expected = @$"
 ┌──────────────────┐
@@ -1008,7 +1005,7 @@ public class DialogTests (ITestOutputHelper output)
                 )]
     public void Dialog_In_Window_Without_Size_One_Button_Aligns (int height, string expected)
     {
-        ((FakeDriver)Driver!).SetBufferSize (20, height);
+        AutoInitShutdownAttribute.FakeResize(new (20, height));
         var win = new Window ();
 
         int iterations = -1;
@@ -1036,7 +1033,7 @@ public class DialogTests (ITestOutputHelper output)
                          }
                          else if (iterations == 1)
                          {
-                             LayoutAndDraw ();
+                             AutoInitShutdownAttribute.RunIteration ();
 
                              // BUGBUG: This seems wrong; is it a bug in Dim.Percent(85)?? No
                              _ = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
@@ -1055,7 +1052,7 @@ public class DialogTests (ITestOutputHelper output)
     [AutoInitShutdown]
     public void Dialog_Opened_From_Another_Dialog ()
     {
-        ((FakeDriver)Driver!).SetBufferSize (30, 10);
+        AutoInitShutdownAttribute.FakeResize(new (30, 10));
 
         // Override CM
         Dialog.DefaultButtonAlignment = Alignment.Center;
@@ -1108,7 +1105,6 @@ public class DialogTests (ITestOutputHelper output)
                              case 0:
                                  Top!.SetNeedsLayout ();
                                  Top.SetNeedsDraw ();
-                                 LayoutAndDraw ();
 
                                  break;
 
@@ -1116,8 +1112,10 @@ public class DialogTests (ITestOutputHelper output)
                                  Assert.False (btn1.NewKeyDownEvent (Key.Space));
 
                                  break;
-                             case 2:
-                                 LayoutAndDraw ();
+
+                             // Now this happens on iteration 3 because Space triggers Run on the new dialog which itself causes another iteration
+                             // as it starts. Meaning we haven't exited case 1 when we enter case 2 from next Run stack frame.
+                             case 3:
 
                                  expected = @$"
   ┌───────────────────────┐
@@ -1133,8 +1131,7 @@ public class DialogTests (ITestOutputHelper output)
                                  Assert.False (btn2!.NewKeyDownEvent (Key.Space));
 
                                  break;
-                             case 3:
-                                 LayoutAndDraw ();
+                             case 5:
 
                                  DriverAssert.AssertDriverContentsWithFrameAre (
                                                                                 @$"
@@ -1152,15 +1149,14 @@ public class DialogTests (ITestOutputHelper output)
                                  Assert.False (Top!.NewKeyDownEvent (Key.Enter));
 
                                  break;
-                             case 4:
-                                 LayoutAndDraw ();
+                             case 7:
 
                                  DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
 
                                  Assert.False (btn3!.NewKeyDownEvent (Key.Space));
 
                                  break;
-                             case 5:
+                             case 9:
                                  DriverAssert.AssertDriverContentsWithFrameAre ("", output);
 
                                  RequestStop ();
@@ -1172,7 +1168,7 @@ public class DialogTests (ITestOutputHelper output)
         Run ().Dispose ();
         Shutdown ();
 
-        Assert.Equal (5, iterations);
+        Assert.Equal (9, iterations);
     }
 
     [Fact]
@@ -1198,7 +1194,7 @@ public class DialogTests (ITestOutputHelper output)
             Height = Dim.Percent (85)
         };
         Begin (d);
-        ((FakeDriver)Driver!).SetBufferSize (100, 100);
+        AutoInitShutdownAttribute.FakeResize(new(100, 100));
 
         // Default location is centered, so 100 / 2 - 85 / 2 = 7
         var expected = 7;
@@ -1212,7 +1208,7 @@ public class DialogTests (ITestOutputHelper output)
     {
         var d = new Dialog { X = 1, Y = 1 };
         Begin (d);
-        ((FakeDriver)Driver!).SetBufferSize (100, 100);
+        AutoInitShutdownAttribute.FakeResize(new(100, 100));
 
         // Default location is centered, so 100 / 2 - 85 / 2 = 7
         var expected = 1;
@@ -1234,7 +1230,7 @@ public class DialogTests (ITestOutputHelper output)
         var expected = 5;
         var d = new Dialog { X = expected, Y = expected, Height = 5, Width = 5 };
         Begin (d);
-        ((FakeDriver)Driver!).SetBufferSize (20, 10);
+        AutoInitShutdownAttribute.FakeResize(new(20, 10));
 
         // Default location is centered, so 100 / 2 - 85 / 2 = 7
         Assert.Equal (new (expected, expected), d.Frame.Location);
@@ -1256,9 +1252,7 @@ public class DialogTests (ITestOutputHelper output)
     public void One_Button_Works ()
     {
         RunState? runState = null;
-
-        var d = (FakeDriver)Driver!;
-
+        
         Button.DefaultShadow = ShadowStyle.None;
 
         var title = "";
@@ -1268,7 +1262,7 @@ public class DialogTests (ITestOutputHelper output)
             $"{Glyphs.VLine}   {Glyphs.LeftBracket} {btnText} {Glyphs.RightBracket}   {Glyphs.VLine}";
 
         int width = buttonRow.Length;
-        d.SetBufferSize (buttonRow.Length, 10);
+        AutoInitShutdownAttribute.FakeResize(new(buttonRow.Length, 10));
 
         (runState, Dialog dlg) = BeginButtonTestDialog (
                                                         title,
@@ -1292,7 +1286,7 @@ public class DialogTests (ITestOutputHelper output)
         };
 
         Begin (d);
-        ((FakeDriver)Driver!).SetBufferSize (100, 100);
+        AutoInitShutdownAttribute.FakeResize(new(100, 100));
 
         // Default size is Percent(85) 
         Assert.Equal (new ((int)(100 * .85), (int)(100 * .85)), d.Frame.Size);
@@ -1308,7 +1302,7 @@ public class DialogTests (ITestOutputHelper output)
         var d = new Dialog { Width = 50, Height = 50 };
 
         Begin (d);
-        ((FakeDriver)Driver!).SetBufferSize (100, 100);
+        AutoInitShutdownAttribute.FakeResize(new(100, 100));
 
         // Default size is Percent(85) 
         Assert.Equal (new (50, 50), d.Frame.Size);
@@ -1316,18 +1310,16 @@ public class DialogTests (ITestOutputHelper output)
     }
 
     [Fact]
-    [SetupFakeDriver]
+    [AutoInitShutdown]
     public void Zero_Buttons_Works ()
     {
         RunState? runState = null;
 
-        var d = (FakeDriver)Driver!;
-
         var title = "1234";
 
         var buttonRow = $"{Glyphs.VLine}        {Glyphs.VLine}";
         int width = buttonRow.Length;
-        d.SetBufferSize (buttonRow.Length, 3);
+        AutoInitShutdownAttribute.FakeResize(new(buttonRow.Length, 3));
 
         (runState, Dialog dlg) = BeginButtonTestDialog (title, width, Alignment.Center, null);
 
@@ -1368,8 +1360,8 @@ public class DialogTests (ITestOutputHelper output)
 
         dlg.SetNeedsDraw ();
         dlg.SetNeedsLayout ();
-        dlg.Layout ();
-        dlg.Draw ();
+
+        AutoInitShutdownAttribute.RunIteration ();
 
         return (runState, dlg);
     }
@@ -1439,9 +1431,9 @@ public class DialogTests (ITestOutputHelper output)
         // Run another view without dispose the prior will throw an assertion
 #if DEBUG_IDISPOSABLE
         Dialog dlg2 = new ();
-        dlg2.Ready += Dlg_Ready;
-        Exception exception = Record.Exception (() => Run (dlg2));
-        Assert.NotNull (exception);
+        dlg2.Ready += Dlg_Ready; 
+        //   Exception exception = Record.Exception (() => Run (dlg2));
+   //     Assert.NotNull (exception);
 
         dlg.Dispose ();
 
@@ -1455,9 +1447,12 @@ public class DialogTests (ITestOutputHelper output)
 
         dlg2.Dispose ();
 
+        // tznind REMOVED: Why wouldn't you be able to read cancelled after dispose - that makes no sense
         // Now an assertion will throw accessing the Canceled property
-        exception = Record.Exception (() => Assert.True (dlg.Canceled))!;
-        Assert.NotNull (exception);
+        //var exception = Record.Exception (() => Assert.True (dlg.Canceled))!;
+        //Assert.NotNull (exception);
+        //Assert.StartsWith ("Cannot access a disposed object.", exception.Message);
+
         Assert.True (Top.WasDisposed);
         Shutdown ();
         Assert.True (dlg2.WasDisposed);
@@ -1491,7 +1486,7 @@ public class DialogTests (ITestOutputHelper output)
             Y = 1
         };
 
-        ((FakeDriver)Driver!).SetBufferSize (20, 20);
+        AutoInitShutdownAttribute.FakeResize(new(20, 20));
 
         int iterations = 0;
         Iteration += (s, a) =>

+ 16 - 25
Tests/UnitTests/Dialogs/MessageBoxTests.cs

@@ -155,7 +155,7 @@ public class MessageBoxTests
     {
         int iterations = -1;
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (15, 15); // 15 x 15 gives us enough room for a button with one char (9x1)
+        AutoInitShutdownAttribute.FakeResize(new Size(15, 15)); // 15 x 15 gives us enough room for a button with one char (9x1)
         Dialog.DefaultShadow = ShadowStyle.None;
         Button.DefaultShadow = ShadowStyle.None;
 
@@ -189,7 +189,7 @@ public class MessageBoxTests
         int iterations = -1;
         var top = new Toplevel ();
         top.BorderStyle = LineStyle.None;
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 10));
 
         var btn =
             $"{Glyphs.LeftBracket}{Glyphs.LeftDefaultIndicator} btn {Glyphs.RightDefaultIndicator}{Glyphs.RightBracket}";
@@ -217,9 +217,8 @@ public class MessageBoxTests
 
                                          Application.RequestStop ();
                                      }
-                                     else if (iterations == 1)
+                                     else if (iterations == 2)
                                      {
-                                         Application.LayoutAndDraw ();
 
                                          DriverAssert.AssertDriverContentsWithFrameAre (
                                                                                         @"
@@ -234,9 +233,8 @@ public class MessageBoxTests
                                          // Really long text
                                          MessageBox.Query (string.Empty, new ('f', 500), 0, false, "btn");
                                      }
-                                     else if (iterations == 2)
+                                     else if (iterations == 4)
                                      {
-                                         Application.LayoutAndDraw ();
 
                                          DriverAssert.AssertDriverContentsWithFrameAre (
                                                                                         @"
@@ -261,7 +259,7 @@ public class MessageBoxTests
         int iterations = -1;
         var top = new Toplevel ();
         top.BorderStyle = LineStyle.None;
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 10));
 
         var btn =
             $"{Glyphs.LeftBracket}{Glyphs.LeftDefaultIndicator} btn {Glyphs.RightDefaultIndicator}{Glyphs.RightBracket}";
@@ -289,9 +287,8 @@ public class MessageBoxTests
 
                                          Application.RequestStop ();
                                      }
-                                     else if (iterations == 1)
+                                     else if (iterations == 2)
                                      {
-                                         Application.LayoutAndDraw ();
 
                                          DriverAssert.AssertDriverContentsWithFrameAre (
                                                                                         @"
@@ -309,9 +306,8 @@ public class MessageBoxTests
                                          // Really long text
                                          MessageBox.Query (string.Empty, new ('f', 500), 0, true, "btn");
                                      }
-                                     else if (iterations == 2)
+                                     else if (iterations == 4)
                                      {
-                                         Application.LayoutAndDraw ();
 
                                          DriverAssert.AssertDriverContentsWithFrameAre (
                                                                                         @"
@@ -347,7 +343,7 @@ public class MessageBoxTests
     public void Size_Not_Default_Message (int height, int width, string message)
     {
         int iterations = -1;
-        ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
+        AutoInitShutdownAttribute.FakeResize(new Size(100, 100));
 
         Application.Iteration += (s, a) =>
                                  {
@@ -361,7 +357,7 @@ public class MessageBoxTests
                                      }
                                      else if (iterations == 1)
                                      {
-                                         Application.LayoutAndDraw ();
+                                         AutoInitShutdownAttribute.RunIteration ();
 
                                          Assert.IsType<Dialog> (Application.Top);
                                          Assert.Equal (new (height, width), Application.Top.Frame.Size);
@@ -384,7 +380,7 @@ public class MessageBoxTests
     public void Size_Not_Default_Message_Button (int height, int width, string message)
     {
         int iterations = -1;
-        ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
+        AutoInitShutdownAttribute.FakeResize(new Size(100, 100));
 
         Application.Iteration += (s, a) =>
                                  {
@@ -398,7 +394,7 @@ public class MessageBoxTests
                                      }
                                      else if (iterations == 1)
                                      {
-                                         Application.LayoutAndDraw ();
+                                         AutoInitShutdownAttribute.RunIteration ();
 
                                          Assert.IsType<Dialog> (Application.Top);
                                          Assert.Equal (new (height, width), Application.Top.Frame.Size);
@@ -417,7 +413,7 @@ public class MessageBoxTests
     public void Size_Not_Default_No_Message (int height, int width)
     {
         int iterations = -1;
-        ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
+        AutoInitShutdownAttribute.FakeResize(new Size(100, 100));
 
         Application.Iteration += (s, a) =>
                                  {
@@ -431,7 +427,7 @@ public class MessageBoxTests
                                      }
                                      else if (iterations == 1)
                                      {
-                                         Application.LayoutAndDraw ();
+                                         AutoInitShutdownAttribute.RunIteration ();
 
                                          Assert.IsType<Dialog> (Application.Top);
                                          Assert.Equal (new (height, width), Application.Top.Frame.Size);
@@ -446,7 +442,7 @@ public class MessageBoxTests
     public void UICatalog_AboutBox ()
     {
         int iterations = -1;
-        ((FakeDriver)Application.Driver).SetBufferSize (70, 15);
+        AutoInitShutdownAttribute.FakeResize (new Size (70, 15));
 
         // Override CM
         MessageBox.DefaultButtonAlignment = Alignment.End;
@@ -469,10 +465,8 @@ public class MessageBoxTests
 
                                          Application.RequestStop ();
                                      }
-                                     else if (iterations == 1)
+                                     else if (iterations == 2)
                                      {
-                                         Application.LayoutAndDraw ();
-
                                          var expectedText = """
                                                             ┌────────────────────────────────────────────────────────────────────┐
                                                             │   ╔═══════════════════════════════════════════════════════════╗    │
@@ -505,16 +499,13 @@ public class MessageBoxTests
 
     [Theory]
     [MemberData (nameof (AcceptingKeys))]
+    [AutoInitShutdown]
     public void Button_IsDefault_True_Return_His_Index_On_Accepting (Key key)
     {
-        Application.Init (new FakeDriver ());
-
         Application.Iteration += (_, _) => Assert.True (Application.RaiseKeyDownEvent (key));
         int res = MessageBox.Query ("hey", "IsDefault", "Yes", "No");
 
         Assert.Equal (0, res);
-
-        Application.Shutdown ();
     }
 
     public static IEnumerable<object []> AcceptingKeys ()

+ 5 - 8
Tests/UnitTests/Dialogs/WizardTests.cs

@@ -392,14 +392,13 @@ public class WizardTests ()
     // and that the title is correct
     public void OneStepWizard_Shows ()
     {
-        var d = (FakeDriver)Application.Driver;
 
         var title = "1234";
         var stepTitle = "ABCD";
 
         var width = 30;
         var height = 7;
-        d.SetBufferSize (width, height);
+        AutoInitShutdownAttribute.FakeResize (new Size (width, height));
 
         //	var btnBackText = "Back";
         var btnBack = string.Empty; // $"{Glyphs.LeftBracket} {btnBackText} {Glyphs.RightBracket}";
@@ -482,14 +481,14 @@ public class WizardTests ()
     // this test is needed because Wizard overrides Dialog's title behavior ("Title - StepTitle")
     public void Setting_Title_Works ()
     {
-        var d = (FakeDriver)Application.Driver;
-
+        var d = (IConsoleDriverFacade)Application.Driver;
+        
         var title = "1234";
         var stepTitle = " - ABCD";
 
         var width = 40;
         var height = 4;
-        d.SetBufferSize (width, height);
+        d.OutputBuffer.SetWindowSize (width,height);
 
         var btnNextText = "Finish";
 
@@ -646,14 +645,12 @@ public class WizardTests ()
     // and that the title is correct
     public void ZeroStepWizard_Shows ()
     {
-        var d = (FakeDriver)Application.Driver;
-
         var title = "1234";
         var stepTitle = "";
 
         var width = 30;
         var height = 6;
-        d.SetBufferSize (width, height);
+        AutoInitShutdownAttribute.FakeResize (new Size (width, height));
 
         var btnBackText = "Back";
         var btnBack = $"{Glyphs.LeftBracket} {btnBackText} {Glyphs.RightBracket}";

+ 1 - 1
Tests/UnitTests/Drawing/RulerTests.cs

@@ -30,7 +30,7 @@ public class RulerTests
     [AutoInitShutdown]
     public void Draw_Default ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (25, 25);
+        AutoInitShutdownAttribute.FakeResize(new Size(25, 25));
 
         var r = new Ruler ();
         r.Draw (Point.Empty);

+ 7 - 6
Tests/UnitTests/Drawing/ThicknessTests.cs

@@ -10,7 +10,7 @@ public class ThicknessTests (ITestOutputHelper output)
     [AutoInitShutdown]
     public void DrawTests ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (60, 60);
+        AutoInitShutdownAttribute.FakeResize(new Size(60, 60));
         var t = new Thickness (0, 0, 0, 0);
         var r = new Rectangle (5, 5, 40, 15);
 
@@ -125,10 +125,11 @@ public class ThicknessTests (ITestOutputHelper output)
         top.Add (f);
         RunState rs = Application.Begin (top);
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (45, 20);
+        AutoInitShutdownAttribute.FakeResize(new Size(45, 20));
         var t = new Thickness (0, 0, 0, 0);
         var r = new Rectangle (2, 2, 40, 15);
-        Application.RunIteration (ref rs);
+
+        AutoInitShutdownAttribute.RunIteration ();
 
         t.Draw (r, ViewDiagnosticFlags.Ruler, "Test");
 
@@ -160,7 +161,7 @@ public class ThicknessTests (ITestOutputHelper output)
         t = new (1, 1, 1, 1);
         r = new (1, 1, 40, 15);
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         t.Draw (r, ViewDiagnosticFlags.Ruler, "Test");
 
         DriverAssert.AssertDriverContentsAre (
@@ -191,7 +192,7 @@ public class ThicknessTests (ITestOutputHelper output)
         t = new (1, 2, 3, 4);
         r = new (2, 2, 40, 15);
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         t.Draw (r, ViewDiagnosticFlags.Ruler, "Test");
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -222,7 +223,7 @@ public class ThicknessTests (ITestOutputHelper output)
         t = new (-1, 1, 1, 1);
         r = new (5, 5, 40, 15);
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         t.Draw (r, ViewDiagnosticFlags.Ruler, "Test");
 
         DriverAssert.AssertDriverContentsWithFrameAre (

+ 17 - 8
Tests/UnitTests/FileServices/FileDialogTests.cs

@@ -28,9 +28,11 @@ public class FileDialogTests ()
         dlg.Dispose ();
     }
 
-    [Fact]
+    [Theory]
+    [InlineData ("Bob", "csv")]
+    [InlineData ("𝔹ob", "CSV")]
     [AutoInitShutdown]
-    public void DirectTyping_Allowed ()
+    public void DirectTyping_Allowed (string path, string extension)
     {
         FileDialog dlg = GetInitializedFileDialog ();
         TextField tf = dlg.SubViews.OfType<TextField> ().First (t => t.HasFocus);
@@ -46,15 +48,15 @@ public class FileDialogTests ()
                      );
 
         // continue typing the rest of the path
-        Send ("BOB");
+        Send (path);
         Send ('.', ConsoleKey.OemPeriod);
-        Send ("CSV");
+        Send (extension);
 
         Assert.True (dlg.Canceled);
 
         Send ('\n', ConsoleKey.Enter);
         Assert.False (dlg.Canceled);
-        Assert.Equal ("bob.csv", Path.GetFileName (dlg.Path));
+        Assert.Equal ($"{path}.{extension}", Path.GetFileName (dlg.Path));
         dlg.Dispose ();
     }
 
@@ -72,7 +74,7 @@ public class FileDialogTests ()
 
         dlg.Path = openIn + Path.DirectorySeparatorChar;
 
-        Send ("X");
+        Send ("x");
 
         // nothing selected yet
         Assert.True (dlg.Canceled);
@@ -375,7 +377,7 @@ public class FileDialogTests ()
         Send ('>', ConsoleKey.LeftArrow);
         Send ('>', ConsoleKey.RightArrow);
 
-        Send ("SUBFOLDER");
+        Send ("subfolder");
 
         // Dialog has not yet been confirmed with a choice
         Assert.True (dlg.Canceled);
@@ -772,7 +774,14 @@ public class FileDialogTests ()
     {
         foreach (char ch in chars)
         {
-            Application.Driver?.SendKeys (ch, ConsoleKey.NoName, false, false, false);
+            ConsoleKeyInfo consoleKeyInfo = EscSeqUtils.MapConsoleKeyInfo (new (ch, ConsoleKey.None, false, false, false));
+
+            Application.Driver?.SendKeys (
+                                          ch,
+                                          consoleKeyInfo.Key,
+                                          (consoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0,
+                                          (consoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0,
+                                          (consoleKeyInfo.Modifiers & ConsoleModifiers.Control) != 0);
         }
     }
 

+ 8 - 1
Tests/UnitTests/SetupFakeDriverAttribute.cs

@@ -1,5 +1,6 @@
 using System.Diagnostics;
 using System.Reflection;
+using TerminalGuiFluentTesting;
 using Xunit.Sdk;
 
 namespace UnitTests;
@@ -34,7 +35,13 @@ public class SetupFakeDriverAttribute : BeforeAfterTestAttribute
 
         Application.ResetState (true);
         Assert.Null (Application.Driver);
-        Application.Driver = new FakeDriver { Rows = 25, Cols = 25 };
+
+        var ff = new FakeDriverFactory ();
+        var driver = ff.Create ();
+
+        Application.Driver = driver;
+        driver.SetBufferSize (25, 25);
+
         Assert.Equal (new (0, 0, 25, 25), Application.Screen);
         // Ensures subscribing events, at least for the SizeChanged event
         Application.SubscribeDriverEvents ();

+ 11 - 10
Tests/UnitTests/Text/AutocompleteTests.cs

@@ -10,6 +10,7 @@ public class AutocompleteTests (ITestOutputHelper output)
     [AutoInitShutdown]
     public void CursorLeft_CursorRight_Mouse_Button_Pressed_Does_Not_Show_Popup ()
     {
+        AutoInitShutdownAttribute.FakeResize (new Size (50,5));
         var tv = new TextView { Width = 50, Height = 5, Text = "This a long line and against TextView." };
 
         var g = (SingleWordSuggestionGenerator)tv.Autocomplete.SuggestionGenerator;
@@ -26,7 +27,7 @@ public class AutocompleteTests (ITestOutputHelper output)
         {
             Assert.True (tv.NewKeyDownEvent (Key.CursorRight));
             top.SetNeedsDraw ();
-            Application.RunIteration (ref rs);
+            AutoInitShutdownAttribute.RunIteration ();
 
             if (i < 4 || i > 5)
             {
@@ -54,7 +55,7 @@ This a long line and against TextView.
                                       )
                     );
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -66,7 +67,7 @@ This a long line and against TextView.
 
         Assert.True (tv.NewKeyDownEvent (Key.G));
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -77,7 +78,7 @@ This ag long line and against TextView.
 
         Assert.True (tv.NewKeyDownEvent (Key.CursorLeft));
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -88,7 +89,7 @@ This ag long line and against TextView.
 
         Assert.True (tv.NewKeyDownEvent (Key.CursorLeft));
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -99,7 +100,7 @@ This ag long line and against TextView.
 
         Assert.True (tv.NewKeyDownEvent (Key.CursorLeft));
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -111,7 +112,7 @@ This ag long line and against TextView.",
         {
             Assert.True (tv.NewKeyDownEvent (Key.CursorRight));
             top.SetNeedsDraw ();
-            Application.RunIteration (ref rs);
+            AutoInitShutdownAttribute.RunIteration ();
 
             DriverAssert.AssertDriverContentsWithFrameAre (
                                                            @"
@@ -123,7 +124,7 @@ This ag long line and against TextView.
 
         Assert.True (tv.NewKeyDownEvent (Key.Backspace));
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -135,7 +136,7 @@ This a long line and against TextView.
 
         Assert.True (tv.NewKeyDownEvent (Key.N));
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -146,7 +147,7 @@ This an long line and against TextView.
 
         Assert.True (tv.NewKeyDownEvent (Key.CursorRight));
         top.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"

+ 2 - 2
Tests/UnitTests/Text/TextFormatterTests.cs

@@ -3935,7 +3935,7 @@ ssb
     [SetupFakeDriver]
     public void FillRemaining_True_False ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (22, 5);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (22, 5);
 
         Attribute [] attrs =
         {
@@ -4157,7 +4157,7 @@ Nice       Work")]
         Size tfSize = tf.FormatAndGetSize ();
         Assert.Equal (new (59, 13), tfSize);
 
-        ((FakeDriver)Application.Driver).SetBufferSize (tfSize.Width, tfSize.Height);
+        ((IFakeDriverV2)Application.Driver).SetBufferSize (tfSize.Width, tfSize.Height);
 
         Application.Driver.FillRect (Application.Screen, (Rune)'*');
         tf.Draw (Application.Screen, Attribute.Default, Attribute.Default);

+ 1 - 0
Tests/UnitTests/UnitTests.csproj

@@ -46,6 +46,7 @@
 	<ItemGroup>
 		<ProjectReference Include="..\..\Terminal.Gui\Terminal.Gui.csproj" />
 		<ProjectReference Include="..\..\Examples\UICatalog\UICatalog.csproj" />
+		<ProjectReference Include="..\TerminalGuiFluentTesting\TerminalGuiFluentTesting.csproj" />
 	</ItemGroup>
 	<ItemGroup>
 		<None Update="xunit.runner.json">

+ 15 - 15
Tests/UnitTests/View/Adornment/BorderTests.cs

@@ -97,8 +97,8 @@ public class BorderTests (ITestOutputHelper output)
         RunState rs = Application.Begin (win);
         var firstIteration = false;
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (width, 5);
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.FakeResize(new Size(width, 5));
+        AutoInitShutdownAttribute.RunIteration ();
         var expected = string.Empty;
 
         switch (width)
@@ -230,7 +230,7 @@ public class BorderTests (ITestOutputHelper output)
 
         RunState rs = Application.Begin (win);
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (width, 4);
+        AutoInitShutdownAttribute.FakeResize(new Size(width, 4));
         Application.RunIteration (ref rs, false);
         var expected = string.Empty;
 
@@ -364,8 +364,8 @@ public class BorderTests (ITestOutputHelper output)
         RunState rs = Application.Begin (win);
         var firstIteration = false;
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (width, 4);
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.FakeResize(new Size(width, 4));
+        AutoInitShutdownAttribute.RunIteration ();
         var expected = string.Empty;
 
         switch (width)
@@ -487,8 +487,8 @@ public class BorderTests (ITestOutputHelper output)
         RunState rs = Application.Begin (win);
         var firstIteration = false;
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, height);
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, height));
+        AutoInitShutdownAttribute.RunIteration ();
         var expected = string.Empty;
 
         switch (height)
@@ -549,8 +549,8 @@ public class BorderTests (ITestOutputHelper output)
         RunState rs = Application.Begin (win);
         var firstIteration = false;
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (width, 3);
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.FakeResize(new Size(width, 3));
+        AutoInitShutdownAttribute.RunIteration ();
         var expected = string.Empty;
 
         switch (width)
@@ -733,8 +733,8 @@ public class BorderTests (ITestOutputHelper output)
         RunState rs = Application.Begin (top);
         var firstIteration = false;
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.FakeResize(new Size(5, 5));
+        AutoInitShutdownAttribute.RunIteration ();
 
         var expected = @"
 ╔═══╗
@@ -761,8 +761,8 @@ public class BorderTests (ITestOutputHelper output)
         RunState rs = Application.Begin (top);
         var firstIteration = false;
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.FakeResize(new Size(10, 4));
+        AutoInitShutdownAttribute.RunIteration ();
 
         var expected = @"
 ╔════════╗
@@ -784,8 +784,8 @@ public class BorderTests (ITestOutputHelper output)
         RunState rs = Application.Begin (win);
         var firstIteration = false;
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (3, 3);
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.FakeResize(new Size(3, 3));
+        AutoInitShutdownAttribute.RunIteration ();
 
         var expected = @"
 ┌─┐

+ 2 - 2
Tests/UnitTests/View/Adornment/MarginTests.cs

@@ -9,7 +9,7 @@ public class MarginTests (ITestOutputHelper output)
     [SetupFakeDriver]
     public void Margin_Is_Transparent ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (5, 5);
 
         var view = new View { Height = 3, Width = 3 };
         view.Margin!.Diagnostics = ViewDiagnosticFlags.Thickness;
@@ -44,7 +44,7 @@ public class MarginTests (ITestOutputHelper output)
     [SetupFakeDriver]
     public void Margin_ViewPortSettings_Not_Transparent_Is_NotTransparent ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (5, 5);
 
         var view = new View { Height = 3, Width = 3 };
         view.Margin!.Diagnostics = ViewDiagnosticFlags.Thickness;

+ 1 - 1
Tests/UnitTests/View/Adornment/PaddingTests.cs

@@ -9,7 +9,7 @@ public class PaddingTests (ITestOutputHelper output)
     [SetupFakeDriver]
     public void Padding_Uses_Parent_Scheme ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (5, 5);
         var view = new View { Height = 3, Width = 3 };
         view.Padding!.Thickness = new (1);
         view.Padding.Diagnostics = ViewDiagnosticFlags.Thickness;

+ 2 - 2
Tests/UnitTests/View/Adornment/ShadowStyleTests.cs

@@ -30,7 +30,7 @@ public class ShadowStyleTests (ITestOutputHelper output)
     [SetupFakeDriver]
     public void ShadowView_Colors (ShadowStyle style, string expectedAttrs)
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (5, 5);
         Color fg = Color.Red;
         Color bg = Color.Green;
 
@@ -100,7 +100,7 @@ public class ShadowStyleTests (ITestOutputHelper output)
     [SetupFakeDriver]
     public void Visual_Test (ShadowStyle style, string expected)
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (5, 5);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (5, 5);
 
         var superView = new Toplevel
         {

+ 2 - 2
Tests/UnitTests/View/Draw/ClearViewportTests.cs

@@ -209,7 +209,7 @@ public class ClearViewportTests (ITestOutputHelper output)
         var top = new Toplevel ();
         top.Add (view);
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 10));
 
         var expected = @"
 ┌──────────────────┐
@@ -274,7 +274,7 @@ public class ClearViewportTests (ITestOutputHelper output)
         var top = new Toplevel ();
         top.Add (view);
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 10));
 
         var expected = @"
 ┌──────────────────┐

+ 1 - 1
Tests/UnitTests/View/Draw/ClipTests.cs

@@ -171,7 +171,7 @@ public class ClipTests (ITestOutputHelper _output)
     [Trait ("Category", "Unicode")]
     public void Clipping_Wide_Runes ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 1);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (30, 1);
 
         var top = new View
         {

+ 2 - 2
Tests/UnitTests/View/Draw/DrawEventTests.cs

@@ -20,8 +20,8 @@ public class DrawEventTests
 
         var top = new Toplevel ();
         top.Add (view, tv);
-        RunState runState = Application.Begin (top);
-        Application.RunIteration (ref runState);
+        Application.Begin (top);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.True (viewCalled);
         Assert.True (tvCalled);

+ 27 - 26
Tests/UnitTests/View/Draw/DrawTests.cs

@@ -32,7 +32,7 @@ public class DrawTests (ITestOutputHelper output)
         top.Add (win);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
+        AutoInitShutdownAttribute.FakeResize(new Size(10, 4)) ;
 
         const string expectedOutput = """
 
@@ -75,8 +75,8 @@ public class DrawTests (ITestOutputHelper output)
         top.Add (viewRight, viewBottom);
 
         var rs = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (7, 7);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.FakeResize(new Size(7, 7));
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -302,7 +302,8 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.X = -1;
-        Application.LayoutAndDraw ();
+
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -317,12 +318,12 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.X = -2;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre (@"", output);
 
         content.X = 0;
         content.Y = -1;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -337,7 +338,7 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.Y = -6;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -352,7 +353,7 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.Y = -19;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -363,12 +364,12 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.Y = -20;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ("", output);
 
         content.X = -2;
         content.Y = 0;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ("", output);
         top.Dispose ();
     }
@@ -408,7 +409,7 @@ public class DrawTests (ITestOutputHelper output)
         top.SubViewsLaidOut += Top_LayoutComplete;
         Application.Begin (top);
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
                                                       
@@ -419,7 +420,7 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.X = -1;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -431,7 +432,7 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.Y = -1;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -442,12 +443,12 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.Y = -2;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ("", output);
 
         content.X = -20;
         content.Y = 0;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ("", output);
         top.Dispose ();
 
@@ -495,7 +496,7 @@ public class DrawTests (ITestOutputHelper output)
         top.Add (container);
         Application.Begin (top);
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
                                                       
@@ -509,7 +510,7 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.X = -1;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -524,12 +525,12 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.X = -2;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre (@"", output);
 
         content.X = 0;
         content.Y = -1;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -544,7 +545,7 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.Y = -6;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -559,7 +560,7 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.Y = -19;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       """
@@ -570,12 +571,12 @@ public class DrawTests (ITestOutputHelper output)
                                                      );
 
         content.Y = -20;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ("", output);
 
         content.X = -2;
         content.Y = 0;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ("", output);
         top.Dispose ();
     }
@@ -615,7 +616,7 @@ public class DrawTests (ITestOutputHelper output)
         top.Add (win);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
+        AutoInitShutdownAttribute.FakeResize(new Size(10, 4));
 
         var expected = """
 
@@ -684,7 +685,7 @@ public class DrawTests (ITestOutputHelper output)
         Toplevel top = new ();
         top.Add (label, view);
         RunState runState = Application.Begin (top);
-        Application.RunIteration (ref runState);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -785,7 +786,7 @@ At 0,0
         Toplevel top = new ();
         top.Add (label, view);
         RunState runState = Application.Begin (top);
-        Application.RunIteration (ref runState);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"

+ 2 - 0
Tests/UnitTests/View/Layout/Pos.AnchorEndTests.cs

@@ -26,6 +26,8 @@ public class PosAnchorEndTests ()
         top.Add (win);
         RunState rs = Application.Begin (top);
 
+        AutoInitShutdownAttribute.FakeResize (new Size (80,25));
+
         Assert.Equal (new (0, 0, 80, 25), top.Frame);
         Assert.Equal (new (0, 0, 80, 25), win.Frame);
         Assert.Equal (new (68, 22, 10, 1), tv.Frame);

+ 4 - 4
Tests/UnitTests/View/Layout/Pos.CenterTests.cs

@@ -35,8 +35,8 @@ public class PosCenterTests (ITestOutputHelper output)
         RunState rs = Application.Begin (win);
         var firstIteration = false;
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, height);
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, height));
+        AutoInitShutdownAttribute.RunIteration ();
         var expected = string.Empty;
 
         switch (height)
@@ -182,8 +182,8 @@ public class PosCenterTests (ITestOutputHelper output)
         RunState rs = Application.Begin (win);
         var firstIteration = false;
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (width, 7);
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.FakeResize(new Size(width, 7));
+        AutoInitShutdownAttribute.RunIteration ();
         var expected = string.Empty;
 
         switch (width)

+ 3 - 2
Tests/UnitTests/View/Layout/SetLayoutTests.cs

@@ -25,17 +25,18 @@ public class SetLayoutTests (ITestOutputHelper output)
         Application.Top.Add (view);
 
         var rs = Application.Begin (Application.Top);
+        AutoInitShutdownAttribute.FakeResize (new Size (80,25));
 
         Assert.Equal (new (0, 0, 80, 25), new Rectangle (0, 0, Application.Screen.Width, Application.Screen.Height));
         Assert.Equal (new (0, 0, Application.Screen.Width, Application.Screen.Height), Application.Top.Frame);
         Assert.Equal (new (0, 0, 80, 25), Application.Top.Frame);
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 10))    ;
         Assert.Equal (new (0, 0, Application.Screen.Width, Application.Screen.Height), Application.Top.Frame);
 
         Assert.Equal (new (0, 0, 20, 10), Application.Top.Frame);
 
         Application.End (rs);
-
+        Application.Top.Dispose ();
     }
 }

+ 1 - 1
Tests/UnitTests/View/Mouse/MouseTests.cs

@@ -49,7 +49,7 @@ public class MouseTests : TestsAllViews
         Application.RaiseMouseEvent (new () { ScreenPosition = new (xy, xy), Flags = MouseFlags.Button1Pressed });
 
         Application.RaiseMouseEvent (new () { ScreenPosition = new (xy + 1, xy + 1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition });
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (expectedMoved, new Point (5, 5) == testView.Frame.Location);
         top.Dispose ();

+ 2 - 3
Tests/UnitTests/View/Navigation/CanFocusTests.cs

@@ -6,11 +6,10 @@ public class CanFocusTests
 {
     // TODO: Figure out what this test is supposed to be testing
     [Fact]
+    [AutoInitShutdown]
     public void CanFocus_Faced_With_Container_Before_Run ()
     {
-        Application.Init (new FakeDriver ());
-
-        Toplevel t = new ();
+        using Toplevel t = new ();
 
         var w = new Window ();
         var f = new FrameView ();

+ 2 - 3
Tests/UnitTests/View/Navigation/NavigationTests.cs

@@ -326,14 +326,13 @@ public class NavigationTests (ITestOutputHelper output) : TestsAllViews
 
 
     [Fact]
-    [SetupFakeDriver]
+    [AutoInitShutdown]
     public void Navigation_With_Null_Focused_View ()
     {
         // Non-regression test for #882 (NullReferenceException during keyboard navigation when Focused is null)
 
-        Application.Init (new FakeDriver ());
 
-        var top = new Toplevel ();
+        using var top = new Toplevel ();
         top.Ready += (s, e) => { Assert.Null (top.Focused); };
 
         // Keyboard navigation with tab

+ 23 - 23
Tests/UnitTests/View/TextTests.cs

@@ -68,7 +68,7 @@ Y
         RunState rs = Application.Begin (top);
 
         label.Text = "Hello";
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 1, 5), label.Frame);
 
@@ -85,7 +85,7 @@ Y
 
         label.Width = 2;
         label.Height = 10;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 2, 10), label.Frame);
 
@@ -121,7 +121,7 @@ Y
         top.Add (win);
 
         RunState rs = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (15, 15);
+        AutoInitShutdownAttribute.FakeResize(new Size(15, 15))   ;
 
         Assert.Equal (new (0, 0, 15, 15), win.Frame);
         Assert.Equal (new (0, 0, 15, 15), win.Margin.Frame);
@@ -158,7 +158,7 @@ Y
         view.Text = "Hello World";
         view.Width = 11;
         view.Height = 1;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 0, 11, 1), view.Frame);
         Assert.Equal ("Absolute(0)", view.X.ToString ());
         Assert.Equal ("Absolute(0)", view.Y.ToString ());
@@ -188,7 +188,7 @@ Y
         view.Width = Dim.Auto ();
         view.Height = Dim.Auto ();
         view.Text = "Hello Worlds";
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         int len = "Hello Worlds".Length;
         Assert.Equal (12, len);
         Assert.Equal (new (0, 0, len, 1), view.Frame);
@@ -214,7 +214,7 @@ Y
         pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
 
         view.TextDirection = TextDirection.TopBottom_LeftRight;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 0, 1, 12), view.Frame);
         Assert.Equal (new (0, 0, 1, 12), view.Frame);
 
@@ -241,13 +241,13 @@ Y
         // Setting to false causes Width and Height to be set to the current ContentSize
         view.Width = 1;
         view.Height = 12;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 0, 1, 12), view.Frame);
 
         view.Width = 12;
         view.Height = 1;
         view.TextFormatter.ConstrainToSize = new (12, 1);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (12, 1), view.TextFormatter.ConstrainToSize);
         Assert.Equal (new (0, 0, 12, 1), view.Frame);
 
@@ -257,7 +257,7 @@ Y
         expected = @" HelloWorlds";
         DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         // TextDirection.TopBottom_LeftRight - Height of 1 and Width of 12 means 
         // that the text will be spread "vertically" across 1 line.
@@ -283,7 +283,7 @@ Y
         pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
 
         view.PreserveTrailingSpaces = true;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 12, 1), view.Frame);
 
@@ -312,7 +312,7 @@ Y
         view.Width = f.Height;
         view.Height = f.Width;
         view.TextDirection = TextDirection.TopBottom_LeftRight;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 1, 12), view.Frame);
 
@@ -339,7 +339,7 @@ Y
         view.Width = Dim.Auto ();
         view.Height = Dim.Auto ();
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 1, 12), view.Frame);
 
@@ -386,7 +386,7 @@ Y
         var top = new Toplevel ();
         top.Add (win);
         RunState rs = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (4, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(4, 10));
 
         Assert.Equal (5, text.Length);
 
@@ -416,7 +416,7 @@ Y
         Assert.Equal (10, text.Length);
 
         //view.Height = Dim.Fill () - text.Length;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 1, 5), view.Frame);
         Assert.Equal (new (1, 5), view.TextFormatter.ConstrainToSize);
@@ -511,7 +511,7 @@ w ";
         var top = new Toplevel ();
         top.Add (win);
         RunState rs = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 20);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 20));
 
         Assert.Equal (new (0, 0, 11, 2), horizontalView.Frame);
         Assert.Equal (new (0, 3, 2, 11), verticalView.Frame);
@@ -542,7 +542,7 @@ w ";
         Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
 
         verticalView.Text = $"最初の行{Environment.NewLine}二行目";
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 3, 4, 4), verticalView.Frame);
 
         expected = @"
@@ -599,7 +599,7 @@ w ";
         var top = new Toplevel ();
         top.Add (win);
         RunState rs = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (22, 22);
+        AutoInitShutdownAttribute.FakeResize(new Size(22, 22));
 
         Assert.Equal (new (text.GetColumns (), 1), horizontalView.TextFormatter.ConstrainToSize);
         Assert.Equal (new (2, 8), verticalView.TextFormatter.ConstrainToSize);
@@ -635,7 +635,7 @@ w ";
         Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (expected, output);
 
         verticalView.Text = "最初の行二行目";
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         // height was initialized with 8 and can only grow or keep initial value
         Assert.Equal (new (0, 3, 2, 7), verticalView.Frame);
@@ -678,7 +678,7 @@ w ";
         var top = new Toplevel ();
         top.Add (lbl);
         RunState rs = Application.Begin (top);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 3, 1), lbl.Frame);
 
@@ -691,7 +691,7 @@ w ";
         Assert.Equal (new (0, 0, 2, 1), lbl.NeedsDrawRect);
         Assert.Equal (new (0, 0, 80, 25), lbl.SuperView.NeedsDrawRect);
         Assert.True (lbl.SuperView.NeedsLayout);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal ("12  ", GetContents ());
 
@@ -783,7 +783,7 @@ w ";
         var top = new Toplevel ();
         top.Add (frame);
         Application.Begin (top);
-        ((FakeDriver)Application.Driver).SetBufferSize (width + 2, 6);
+        AutoInitShutdownAttribute.FakeResize (new Size(width + 2, 6));
 
         // frame.Width is width + border wide (20 + 2) and 6 high
 
@@ -913,7 +913,7 @@ w ";
         var top = new Toplevel ();
         top.Add (frame);
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (9, height + 2);
+        AutoInitShutdownAttribute.FakeResize(new Size(9, height + 2));
 
         if (autoSize)
         {
@@ -998,7 +998,7 @@ w ";
     [SetupFakeDriver]
     public void Narrow_Wide_Runes ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (32, 32);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (32, 32);
         var top = new View { Width = 32, Height = 32 };
 
         var text = $"First line{Environment.NewLine}Second line";

+ 3 - 4
Tests/UnitTests/View/ViewTests.cs

@@ -453,10 +453,10 @@ public class ViewTests
 
         view.Width = Dim.Auto ();
         view.Height = Dim.Auto ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal ("Testing visibility.".Length, view.Frame.Width);
         Assert.True (view.Visible);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(30, 5));
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -471,8 +471,7 @@ public class ViewTests
 
         view.Visible = false;
 
-        var firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"

+ 1 - 1
Tests/UnitTests/Views/ButtonTests.cs

@@ -571,7 +571,7 @@ public class ButtonTests (ITestOutputHelper output)
         Assert.False (btn.IsInitialized);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(30, 5));
 
         Assert.True (btn.IsInitialized);
         Assert.Equal ("Say Hello 你", btn.Text);

+ 10 - 10
Tests/UnitTests/Views/CheckBoxTests.cs

@@ -351,7 +351,7 @@ public class CheckBoxTests (ITestOutputHelper output)
         top.Add (win);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
+        AutoInitShutdownAttribute.FakeResize (new Size (30, 5));
 
         Assert.Equal (Alignment.Center, checkBox.TextAlignment);
         Assert.Equal (new (1, 1, 25, 1), checkBox.Frame);
@@ -369,7 +369,7 @@ public class CheckBoxTests (ITestOutputHelper output)
         Assert.Equal (new (0, 0, 30, 5), pos);
 
         checkBox.CheckedState = CheckState.Checked;
-        Application.LayoutAndDraw ();
+        Application.LayoutAndDrawImpl ();
 
         expected = @$"
 ┌┤Test Demo 你├──────────────┐
@@ -411,7 +411,7 @@ public class CheckBoxTests (ITestOutputHelper output)
         top.Add (win);
 
         RunState rs = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 6);
+        AutoInitShutdownAttribute.FakeResize(new Size(30, 6));
 
         Assert.Equal (Alignment.Fill, checkBox1.TextAlignment);
         Assert.Equal (new (1, 1, 25, 1), checkBox1.Frame);
@@ -431,15 +431,15 @@ public class CheckBoxTests (ITestOutputHelper output)
         Assert.Equal (new (0, 0, 30, 6), pos);
 
         checkBox1.CheckedState = CheckState.Checked;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (1, 1, 25, 1), checkBox1.Frame);
         Assert.Equal (_size25x1, checkBox1.TextFormatter.ConstrainToSize);
 
         checkBox2.CheckedState = CheckState.Checked;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (1, 2, 25, 1), checkBox2.Frame);
         Assert.Equal (_size25x1, checkBox2.TextFormatter.ConstrainToSize);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @$"
 ┌┤Test Demo 你├──────────────┐
@@ -472,7 +472,7 @@ public class CheckBoxTests (ITestOutputHelper output)
         top.Add (win);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(30, 5));
 
         Assert.Equal (Alignment.Start, checkBox.TextAlignment);
         Assert.Equal (new (1, 1, 25, 1), checkBox.Frame);
@@ -490,7 +490,7 @@ public class CheckBoxTests (ITestOutputHelper output)
         Assert.Equal (new (0, 0, 30, 5), pos);
 
         checkBox.CheckedState = CheckState.Checked;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @$"
 ┌┤Test Demo 你├──────────────┐
@@ -523,7 +523,7 @@ public class CheckBoxTests (ITestOutputHelper output)
         top.Add (win);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(30, 5));
 
         Assert.Equal (Alignment.End, checkBox.TextAlignment);
         Assert.Equal (new (1, 1, 25, 1), checkBox.Frame);
@@ -541,7 +541,7 @@ public class CheckBoxTests (ITestOutputHelper output)
         Assert.Equal (new (0, 0, 30, 5), pos);
 
         checkBox.CheckedState = CheckState.Checked;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @$"
 ┌┤Test Demo 你├──────────────┐

+ 5 - 5
Tests/UnitTests/Views/FrameViewTests.cs

@@ -38,7 +38,7 @@ public class FrameViewTests (ITestOutputHelper output)
     [AutoInitShutdown]
     public void Draw_Defaults ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (10, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(10, 10));
         var fv = new FrameView () { BorderStyle = LineStyle.Single };
         Assert.Equal (string.Empty, fv.Title);
         Assert.Equal (string.Empty, fv.Text);
@@ -51,7 +51,7 @@ public class FrameViewTests (ITestOutputHelper output)
         fv.Height = 5;
         fv.Width = 5;
         Assert.Equal (new (0, 0, 5, 5), fv.Frame);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -66,7 +66,7 @@ public class FrameViewTests (ITestOutputHelper output)
         fv.X = 1;
         fv.Y = 2;
         Assert.Equal (new (1, 2, 5, 5), fv.Frame);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -81,7 +81,7 @@ public class FrameViewTests (ITestOutputHelper output)
         fv.X = -1;
         fv.Y = -2;
         Assert.Equal (new (-1, -2, 5, 5), fv.Frame);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -94,7 +94,7 @@ public class FrameViewTests (ITestOutputHelper output)
         fv.X = 7;
         fv.Y = 8;
         Assert.Equal (new (7, 8, 5, 5), fv.Frame);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"

+ 22 - 20
Tests/UnitTests/Views/LabelTests.cs

@@ -102,7 +102,7 @@ public class LabelTests (ITestOutputHelper output)
         top.Add (win);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(30, 5));
 
         var expected = @"
 ┌────────────────────────────┐
@@ -116,7 +116,7 @@ public class LabelTests (ITestOutputHelper output)
 
         label.Text = "Say Hello 你 changed";
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @"
 ┌────────────────────────────┐
@@ -142,7 +142,7 @@ public class LabelTests (ITestOutputHelper output)
         top.Add (win);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(30, 5));
 
         var expected = @"
 ┌────────────────────────────┐
@@ -156,7 +156,7 @@ public class LabelTests (ITestOutputHelper output)
 
         label.Text = "Say Hello 你 changed";
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @"
 ┌────────────────────────────┐
@@ -204,6 +204,8 @@ public class LabelTests (ITestOutputHelper output)
         Assert.False (tf1.FillRemaining);
         Assert.True (tf2.FillRemaining);
 
+        AutoInitShutdownAttribute.RunIteration ();
+
         tf1.Draw (new (new (0, 1), tfSize), label.GetAttributeForRole (VisualRole.Normal), label.GetAttributeForRole (VisualRole.HotNormal));
 
         tf2.Draw (new (new (0, 2), tfSize), label.GetAttributeForRole (VisualRole.Normal), label.GetAttributeForRole (VisualRole.HotNormal));
@@ -250,7 +252,7 @@ This TextFormatter (tf2) is rewritten.                                 ",
         var top = new Toplevel ();
         top.Add (label);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 16, 1), label.Frame);
 
@@ -271,7 +273,7 @@ Demo Simple Rune
         var top = new Toplevel ();
         top.Add (label);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.NotNull (label.Width);
         Assert.NotNull (label.Height);
 
@@ -307,7 +309,7 @@ e
         var top = new Toplevel ();
         top.Add (label);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var expected = @"
@@ -392,7 +394,7 @@ e
         Assert.False (label.IsInitialized);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(30, 5));
 
         Assert.True (label.IsInitialized);
         Assert.Equal ("Say Hello 你", label.Text);
@@ -424,7 +426,7 @@ e
         Assert.False (label.IsInitialized);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(30, 5));
 
         Assert.True (label.IsInitialized);
         Assert.Equal ("Say Hello 你", label.Text);
@@ -478,7 +480,7 @@ e
         var top = new Toplevel ();
         top.Add (label);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 6, 3), label.Frame);
         Assert.Equal (new (0, 0, 4, 1), label.Viewport);
@@ -502,7 +504,7 @@ e
         var top = new Toplevel ();
         top.Add (label);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 0, 6, 2), label.Frame);
         Assert.Equal (new (0, 0, 4, 1), label.Viewport);
         Application.Begin (top);
@@ -856,7 +858,7 @@ e
         Toplevel top = new ();
         top.Add (win);
         RunState rs = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (40, 10);
+        AutoInitShutdownAttribute.FakeResize (new Size (40,10));
 
         Assert.Equal (29, label.Text.Length);
         Assert.Equal (new (0, 0, 40, 10), top.Frame);
@@ -903,7 +905,7 @@ e
         Toplevel top = new ();
         top.Add (win);
         RunState rs = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (40, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(40, 10));
 
         Assert.Equal (new (0, 0, 40, 10), top.Frame);
         Assert.Equal (new (0, 0, 40, 10), win.Frame);
@@ -975,7 +977,7 @@ e
                          {
                              if (k.KeyCode == KeyCode.Enter)
                              {
-                                 ((FakeDriver)Application.Driver!).SetBufferSize (22, count + 4);
+                                 AutoInitShutdownAttribute.FakeResize(new Size(22, count + 4));
                                  Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (_expecteds [count], output);
                                  Assert.Equal (new (0, 0, 22, count + 4), pos);
 
@@ -1039,7 +1041,7 @@ e
     [SetupFakeDriver]
     public void Label_Height_Zero_Stays_Zero ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (10, 4);
         var text = "Label";
 
         var label = new Label
@@ -1126,7 +1128,7 @@ e
                          {
                              if (k.KeyCode == KeyCode.Enter)
                              {
-                                 ((FakeDriver)Application.Driver!).SetBufferSize (22, count + 4);
+                                 AutoInitShutdownAttribute.FakeResize(new Size(22, count + 4));
                                  Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (_expecteds [count], output);
                                  Assert.Equal (new (0, 0, 22, count + 4), pos);
 
@@ -1201,7 +1203,7 @@ e
         var top = new Toplevel ();
         top.Add (win);
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
+        AutoInitShutdownAttribute.FakeResize(new Size(10, 4));
 
         Assert.Equal (5, text.Length);
         Assert.Equal (new (0, 0, 5, 1), label.Frame);
@@ -1224,7 +1226,7 @@ e
         Assert.Equal (10, text.Length);
 
         //label.Width = Dim.Fill () - text.Length;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 5, 1), label.Frame);
         Assert.Equal (new (5, 1), label.TextFormatter.ConstrainToSize);
@@ -1260,7 +1262,7 @@ e
         var top = new Toplevel ();
         top.Add (win);
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (10, 4);
+        AutoInitShutdownAttribute.FakeResize(new Size(10, 4));
 
         Assert.Equal (5, text.Length);
         Assert.Equal (new (0, 0, 5, 1), label.Frame);
@@ -1283,7 +1285,7 @@ e
         Assert.Equal (10, text.Length);
 
         //label.Width = Dim.Fill () - text.Length;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (0, 0, 5, 1), label.Frame);
         Assert.Equal (new (5, 1), label.TextFormatter.ConstrainToSize);

+ 18 - 18
Tests/UnitTests/Views/ListViewTests.cs

@@ -56,8 +56,8 @@ public class ListViewTests (ITestOutputHelper output)
         var top = new Toplevel ();
         top.Add (win);
         RunState rs = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (12, 12);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.FakeResize(new Size(12, 12));
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (-1, lv.SelectedItem);
 
@@ -79,7 +79,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.ScrollVertical (10));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (-1, lv.SelectedItem);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -100,7 +100,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveDown ());
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (0, lv.SelectedItem);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -121,7 +121,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveEnd ());
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (19, lv.SelectedItem);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -142,7 +142,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.ScrollVertical (-20));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (19, lv.SelectedItem);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -163,7 +163,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveDown ());
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (19, lv.SelectedItem);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -184,7 +184,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.ScrollVertical (-20));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (19, lv.SelectedItem);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -205,7 +205,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveDown ());
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (19, lv.SelectedItem);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -226,7 +226,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveHome ());
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (0, lv.SelectedItem);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -247,7 +247,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.ScrollVertical (20));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (0, lv.SelectedItem);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -268,7 +268,7 @@ public class ListViewTests (ITestOutputHelper output)
                                                      );
 
         Assert.True (lv.MoveUp ());
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (0, lv.SelectedItem);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -305,7 +305,7 @@ public class ListViewTests (ITestOutputHelper output)
         var top = new Toplevel ();
         top.Add (lv);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -319,7 +319,7 @@ Item 4",
 
         // EnsureSelectedItemVisible is auto enabled on the OnSelectedChanged
         lv.SelectedItem = 6;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -343,7 +343,7 @@ Item 6",
         var top = new Toplevel ();
         top.Add (lv);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal ("Second ", GetContents (0));
         Assert.Equal (new (' ', 7), GetContents (1));
@@ -724,7 +724,7 @@ Item 6",
         var top = new Toplevel ();
         top.Add (lv);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (1), lv.Border.Thickness);
         Assert.Equal (-1, lv.SelectedItem);
@@ -798,7 +798,7 @@ Item 6",
         var top = new Toplevel ();
         top.Add (lv);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -811,7 +811,7 @@ Item 6",
 
         lv.LeftItem = 1;
         lv.TopItem = 1;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"

+ 137 - 131
Tests/UnitTests/Views/Menuv1/MenuBarv1Tests.cs

@@ -30,12 +30,14 @@ public class MenuBarv1Tests (ITestOutputHelper output)
         Application.Begin (top);
 
         top.NewKeyDownEvent (Key.N.WithAlt);
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
+
         Assert.True (menuBar.IsMenuOpen);
         Assert.Equal ("", action);
 
         top.NewKeyDownEvent (Key.I);
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
+
         Assert.False (menuBar.IsMenuOpen);
         Assert.Equal ("I", action);
 
@@ -75,7 +77,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
         Assert.False (mi.Checked);
         Assert.True (menu.NewKeyDownEvent (menu.Key));
         Assert.True (menu._openMenu.NewKeyDownEvent (Key.Enter));
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.True (mi.Checked);
 
         Assert.True (
@@ -89,13 +91,13 @@ public class MenuBarv1Tests (ITestOutputHelper output)
                                                    new () { Position = new (0, 0), Flags = MouseFlags.Button1Clicked, View = menu._openMenu }
                                                   )
                     );
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.False (mi.Checked);
 
         mi.AllowNullChecked = true;
         Assert.True (menu.NewKeyDownEvent (menu.Key));
         Assert.True (menu._openMenu.NewKeyDownEvent (Key.Enter));
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Null (mi.Checked);
 
         Assert.True (
@@ -103,7 +105,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
                                          new () { Position = new (0, 0), Flags = MouseFlags.Button1Pressed, View = menu }
                                         )
                     );
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @$"
@@ -119,11 +121,11 @@ public class MenuBarv1Tests (ITestOutputHelper output)
                                                    new () { Position = new (0, 0), Flags = MouseFlags.Button1Clicked, View = menu._openMenu }
                                                   )
                     );
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.True (mi.Checked);
         Assert.True (menu.NewKeyDownEvent (menu.Key));
         Assert.True (menu._openMenu.NewKeyDownEvent (Key.Enter));
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.False (mi.Checked);
 
         Assert.True (
@@ -137,7 +139,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
                                                    new () { Position = new (0, 0), Flags = MouseFlags.Button1Clicked, View = menu._openMenu }
                                                   )
                     );
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Null (mi.Checked);
 
         mi.AllowNullChecked = false;
@@ -220,7 +222,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
 
         Assert.True (top.NewKeyDownEvent (Key.F.WithAlt));
         Assert.True (top.NewKeyDownEvent (Key.N.WithAlt));
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.NotNull (win);
         Assert.False (CanExecuteNew ());
         Assert.True (CanExecuteClose ());
@@ -468,7 +470,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
         var win = new Window ();
         top.Add (win);
         RunState rsTop = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (40, 15);
+        AutoInitShutdownAttribute.FakeResize(new Size(40, 15))    ;
 
         Assert.Equal (new (0, 0, 40, 15), win.Frame);
 
@@ -656,7 +658,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
             Assert.Equal (items [i], menu.Menus [0].Title);
         }
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 15));
         menu.OpenMenu ();
         Application.RunIteration (ref rsDialog);
 
@@ -779,7 +781,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
         }
 
         RunState rs = Application.Begin (dialog);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (new (2, 2, 15, 4), dialog.Frame);
 
@@ -794,7 +796,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
 
         Assert.Equal ("File", menu.Menus [0].Title);
         menu.OpenMenu ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -815,7 +817,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
 
         // Need to fool MainLoop into thinking it's running
         Application.MainLoop.Running = true;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (items [0], menu.Menus [0].Title);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -833,13 +835,13 @@ public class MenuBarv1Tests (ITestOutputHelper output)
 
             Application.RaiseMouseEvent (new () { ScreenPosition = new (20, 5 + i), Flags = MouseFlags.Button1Clicked });
 
-            Application.RunIteration (ref rs);
+            AutoInitShutdownAttribute.RunIteration ();
             Assert.Equal (items [i], menu.Menus [0].Title);
         }
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 15));
         menu.OpenMenu ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -880,7 +882,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
         Toplevel top = new ();
         Application.Begin (top);
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var expected = @"
 ──────┐
@@ -895,7 +897,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
         menu.CloseAllMenus ();
         menu.Frame = new (-1, -2, menu.Frame.Width, menu.Frame.Height);
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @"
  One  │
@@ -908,9 +910,9 @@ public class MenuBarv1Tests (ITestOutputHelper output)
 
         menu.CloseAllMenus ();
         menu.Frame = new (0, 0, menu.Frame.Width, menu.Frame.Height);
-        ((FakeDriver)Application.Driver!).SetBufferSize (7, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(7, 5));
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @"
 ┌──────
@@ -924,9 +926,9 @@ public class MenuBarv1Tests (ITestOutputHelper output)
 
         menu.CloseAllMenus ();
         menu.Frame = new (0, 0, menu.Frame.Width, menu.Frame.Height);
-        ((FakeDriver)Application.Driver!).SetBufferSize (7, 3);
+        AutoInitShutdownAttribute.FakeResize(new Size(7, 3));
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @"
 ┌──────
@@ -960,7 +962,7 @@ public class MenuBarv1Tests (ITestOutputHelper output)
         Toplevel top = new ();
         Application.Begin (top);
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var expected = @"
 ne
@@ -972,7 +974,7 @@ wo
         menu.CloseAllMenus ();
         menu.Frame = new (-2, -2, menu.Frame.Width, menu.Frame.Height);
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @"
 wo
@@ -982,9 +984,9 @@ wo
 
         menu.CloseAllMenus ();
         menu.Frame = new (0, 0, menu.Frame.Width, menu.Frame.Height);
-        ((FakeDriver)Application.Driver!).SetBufferSize (3, 2);
+        AutoInitShutdownAttribute.FakeResize(new Size(3, 2));
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @"
  On
@@ -995,9 +997,9 @@ wo
 
         menu.CloseAllMenus ();
         menu.Frame = new (0, 0, menu.Frame.Width, menu.Frame.Height);
-        ((FakeDriver)Application.Driver!).SetBufferSize (3, 1);
+        AutoInitShutdownAttribute.FakeResize(new Size(3, 1));
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = @"
  On
@@ -1024,7 +1026,7 @@ wo
         Toplevel top = new ();
         Application.Begin (top);
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var expected = @"
 ┌──────┐
@@ -1056,7 +1058,7 @@ wo
         Toplevel top = new ();
         Application.Begin (top);
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var expected = @"
  One
@@ -1115,13 +1117,13 @@ wo
         Assert.Equal (new (1, 0, 11, 1), pos);
 
         Assert.True (Application.Top.ProcessKeyDown (new KeyEventArgs (Key.N)));
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.False (newAction); // not yet, hot keys don't work if the item is not visible
 
         Assert.True (Application.Top.ProcessKeyDown (new KeyEventArgs (Key.F)));
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.True (Application.Top.ProcessKeyDown (new KeyEventArgs (Key.N)));
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.True (newAction);
         Application.Top.Draw ();
 
@@ -1144,7 +1146,7 @@ wo
 
         Assert.True (Application.Top.ProcessKeyDown (new KeyEventArgs (Key.CursorRight)));
         Assert.True (Application.Top.ProcessKeyDown (new KeyEventArgs (Key.C)));
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.True (copyAction);
 #endif
         top.Dispose ();
@@ -1216,7 +1218,7 @@ wo
         DriverAssert.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), output);
 
         Assert.True (Application.Top.SubViews.ElementAt (1).NewKeyDownEvent (Key.N));
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.True (newAction);
 
         Assert.True (menu.NewKeyDownEvent (Key.E.WithAlt));
@@ -1225,7 +1227,7 @@ wo
         DriverAssert.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), output);
 
         Assert.True (Application.Top.SubViews.ElementAt (1).NewKeyDownEvent (Key.C));
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.True (copyAction);
         top.Dispose ();
     }
@@ -1385,7 +1387,7 @@ wo
         foreach (Key key in keys)
         {
             top.NewKeyDownEvent (key);
-            Application.MainLoop.RunIteration ();
+            AutoInitShutdownAttribute.RunIteration ();
         }
 
         Assert.Equal (expectedBarTitle, mbiCurrent != null ? mbiCurrent.Title : "Closed");
@@ -1440,7 +1442,7 @@ wo
         foreach (KeyCode key in keys)
         {
             Assert.True (top.NewKeyDownEvent (new (key)));
-            Application.MainLoop!.RunIteration ();
+            AutoInitShutdownAttribute.RunIteration ();
         }
 
         Assert.Equal (expectedAction, miAction);
@@ -1479,7 +1481,7 @@ wo
         Application.Begin (top);
 
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -1527,7 +1529,7 @@ wo
         Application.Begin (top);
 
         menu.OpenMenu ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -1629,7 +1631,7 @@ wo
         Toplevel top = new ();
         top.Add (win);
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (40, 8);
+        AutoInitShutdownAttribute.FakeResize(new Size(40, 8));
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -1661,7 +1663,7 @@ wo
                                                      );
 
         Assert.True (menu.NewKeyDownEvent (Key.CursorRight));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -1739,12 +1741,12 @@ wo
         Toplevel top = new ();
         top.Add (win);
 
-        Application.Iteration += (s, a) =>
-                                 {
-                                     ((FakeDriver)Application.Driver!).SetBufferSize (40, 8);
+        Application.AddTimeout (TimeSpan.Zero, () =>
+                                                       {
+                                                           AutoInitShutdownAttribute.FakeResize(new Size (40, 8));
 
-                                     DriverAssert.AssertDriverContentsWithFrameAre (
-                                                                                   @"
+                                                           DriverAssert.AssertDriverContentsWithFrameAre (
+                                                                @"
 ┌──────────────────────────────────────┐
 │ File  Edit                           │
 │                                      │
@@ -1753,14 +1755,14 @@ wo
 │                                      │
 │                                      │
 └──────────────────────────────────────┘",
-                                                                                   output
-                                                                                  );
+                                                                output
+                                                               );
 
-                                     Assert.True (win.NewKeyDownEvent (menu.Key));
-                                     top.Draw ();
+                                                           Assert.True (win.NewKeyDownEvent (menu.Key));
+                                                           top.Draw ();
 
-                                     DriverAssert.AssertDriverContentsWithFrameAre (
-                                                                                   @"
+                                                           DriverAssert.AssertDriverContentsWithFrameAre (
+                                                                @"
 ┌──────────────────────────────────────┐
 │ File  Edit                           │
 │┌──────┐                              │
@@ -1769,14 +1771,14 @@ wo
 │                                      │
 │                                      │
 └──────────────────────────────────────┘",
-                                                                                   output
-                                                                                  );
+                                                                output
+                                                               );
 
-                                     Assert.True (menu.NewKeyDownEvent (Key.CursorRight));
-                                     Application.LayoutAndDraw ();
+                                                           Assert.True (menu.NewKeyDownEvent (Key.CursorRight));
+                                                           AutoInitShutdownAttribute.RunIteration ();
 
-                                     DriverAssert.AssertDriverContentsWithFrameAre (
-                                                                                   @"
+                                                           DriverAssert.AssertDriverContentsWithFrameAre (
+                                                                @"
 ┌──────────────────────────────────────┐
 │ File  Edit                           │
 │      ┌─────────┐                     │
@@ -1785,14 +1787,14 @@ wo
 │                                      │
 │                                      │
 └──────────────────────────────────────┘",
-                                                                                   output
-                                                                                  );
+                                                                output
+                                                               );
 
-                                     Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorRight));
-                                     top.Draw ();
+                                                           Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorRight));
+                                                           top.Draw ();
 
-                                     DriverAssert.AssertDriverContentsWithFrameAre (
-                                                                                   @"
+                                                           DriverAssert.AssertDriverContentsWithFrameAre (
+                                                                @"
 ┌──────────────────────────────────────┐
 │ File  Edit                           │
 │      ┌─────────┐                     │
@@ -1801,15 +1803,15 @@ wo
 │                 │ Selected  │        │
 │                 └───────────┘        │
 └──────────────────────────────────────┘",
-                                                                                   output
-                                                                                  );
+                                                                output
+                                                               );
 
-                                     Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorRight));
-                                     View.SetClipToScreen ();
-                                     top.Draw ();
+                                                           Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorRight));
+                                                           View.SetClipToScreen ();
+                                                           top.Draw ();
 
-                                     DriverAssert.AssertDriverContentsWithFrameAre (
-                                                                                   @"
+                                                           DriverAssert.AssertDriverContentsWithFrameAre (
+                                                                @"
 ┌──────────────────────────────────────┐
 │ File  Edit                           │
 │┌──────┐                              │
@@ -1818,11 +1820,13 @@ wo
 │                                      │
 │                                      │
 └──────────────────────────────────────┘",
-                                                                                   output
-                                                                                  );
+                                                                output
+                                                               );
 
-                                     Application.RequestStop ();
-                                 };
+                                                           Application.RequestStop ();
+
+                                                           return false;
+                                                       });
 
         Application.Run (top);
         top.Dispose ();
@@ -1853,9 +1857,9 @@ wo
             ]
         };
         win.Add (menu);
-        ((FakeDriver)Application.Driver!).SetBufferSize (40, 8);
+        AutoInitShutdownAttribute.FakeResize(new Size(40, 8));
         RunState rs = Application.Begin (win);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -1871,7 +1875,7 @@ wo
                                                      );
 
         Assert.True (win.NewKeyDownEvent (menu.Key));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -1887,7 +1891,7 @@ wo
                                                      );
 
         Assert.True (menu.NewKeyDownEvent (Key.CursorRight));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -1903,7 +1907,7 @@ wo
                                                      );
 
         Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorRight));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -1919,7 +1923,7 @@ wo
                                                      );
 
         Assert.True (menu._openMenu.NewKeyDownEvent (Key.CursorRight));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -1940,15 +1944,16 @@ wo
     [AutoInitShutdown]
     public void MenuBar_In_Window_Without_Other_Views_Without_Top_Init_With_Run_T ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (40, 8);
+        AutoInitShutdownAttribute.FakeResize(new Size(40, 8));
+
+        Application.AddTimeout (TimeSpan.Zero, () =>
+                                                       {
+                                                           Toplevel top = Application.Top;
 
-        Application.Iteration += (s, a) =>
-                                 {
-                                     Toplevel top = Application.Top;
-                                     Application.LayoutAndDraw ();
+                                                           AutoInitShutdownAttribute.RunIteration ();
 
-                                     DriverAssert.AssertDriverContentsWithFrameAre (
-                                                                                   @"
+                                                           DriverAssert.AssertDriverContentsWithFrameAre (
+                                                                @"
 ┌──────────────────────────────────────┐
 │ File  Edit                           │
 │                                      │
@@ -1957,14 +1962,14 @@ wo
 │                                      │
 │                                      │
 └──────────────────────────────────────┘",
-                                                                                   output
-                                                                                  );
+                                                                output
+                                                               );
 
-                                     Assert.True (top.NewKeyDownEvent (Key.F9));
-                                     top.Draw ();
+                                                           Assert.True (top.NewKeyDownEvent (Key.F9));
+                                                           top.Draw ();
 
-                                     DriverAssert.AssertDriverContentsWithFrameAre (
-                                                                                   @"
+                                                           DriverAssert.AssertDriverContentsWithFrameAre (
+                                                                @"
 ┌──────────────────────────────────────┐
 │ File  Edit                           │
 │┌──────┐                              │
@@ -1973,14 +1978,14 @@ wo
 │                                      │
 │                                      │
 └──────────────────────────────────────┘",
-                                                                                   output
-                                                                                  );
+                                                                output
+                                                               );
 
-                                     Assert.True (top.SubViews.ElementAt (0).NewKeyDownEvent (Key.CursorRight));
-                                     Application.LayoutAndDraw ();
+                                                           Assert.True (top.SubViews.ElementAt (0).NewKeyDownEvent (Key.CursorRight));
+                                                           AutoInitShutdownAttribute.RunIteration ();
 
-                                     DriverAssert.AssertDriverContentsWithFrameAre (
-                                                                                   @"
+                                                           DriverAssert.AssertDriverContentsWithFrameAre (
+                                                                @"
 ┌──────────────────────────────────────┐
 │ File  Edit                           │
 │      ┌─────────┐                     │
@@ -1989,16 +1994,16 @@ wo
 │                                      │
 │                                      │
 └──────────────────────────────────────┘",
-                                                                                   output
-                                                                                  );
+                                                                output
+                                                               );
 
-                                     Assert.True (
-                                                  ((MenuBar)top.SubViews.ElementAt (0))._openMenu.NewKeyDownEvent (Key.CursorRight)
-                                                 );
-                                     top.Draw ();
+                                                           Assert.True (
+                                                                        ((MenuBar)top.SubViews.ElementAt (0))._openMenu.NewKeyDownEvent (Key.CursorRight)
+                                                                       );
+                                                           top.Draw ();
 
-                                     DriverAssert.AssertDriverContentsWithFrameAre (
-                                                                                   @"
+                                                           DriverAssert.AssertDriverContentsWithFrameAre (
+                                                                @"
 ┌──────────────────────────────────────┐
 │ File  Edit                           │
 │      ┌─────────┐                     │
@@ -2007,17 +2012,17 @@ wo
 │                 │ Selected  │        │
 │                 └───────────┘        │
 └──────────────────────────────────────┘",
-                                                                                   output
-                                                                                  );
+                                                                output
+                                                               );
 
-                                     Assert.True (
-                                                  ((MenuBar)top.SubViews.ElementAt (0))._openMenu.NewKeyDownEvent (Key.CursorRight)
-                                                 );
-                                     View.SetClipToScreen ();
-                                     top.Draw ();
+                                                           Assert.True (
+                                                                        ((MenuBar)top.SubViews.ElementAt (0))._openMenu.NewKeyDownEvent (Key.CursorRight)
+                                                                       );
+                                                           View.SetClipToScreen ();
+                                                           top.Draw ();
 
-                                     DriverAssert.AssertDriverContentsWithFrameAre (
-                                                                                   @"
+                                                           DriverAssert.AssertDriverContentsWithFrameAre (
+                                                                @"
 ┌──────────────────────────────────────┐
 │ File  Edit                           │
 │┌──────┐                              │
@@ -2026,11 +2031,13 @@ wo
 │                                      │
 │                                      │
 └──────────────────────────────────────┘",
-                                                                                   output
-                                                                                  );
+                                                                output
+                                                               );
 
-                                     Application.RequestStop ();
-                                 };
+                                                           Application.RequestStop ();
+
+                                                           return false;
+                                                       });
 
         Application.Run<CustomWindow> ().Dispose ();
     }
@@ -2881,8 +2888,8 @@ Edit
         RunState rs = Application.Begin (top);
 
         menu.OpenMenu ();
-        var firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
+
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -2893,9 +2900,9 @@ Edit
                                                       output
                                                      );
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 15);
-        firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 15));
+
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -2968,7 +2975,7 @@ Edit
         Application.Begin (top);
 
         Application.RaiseKeyDownEvent (Key.S.WithCtrl);
-        Application.MainLoop.RunIteration ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.True (saveAction);
         top.Dispose ();
@@ -3306,7 +3313,6 @@ Edit
     //  New    Copy
     public class ExpectedMenuBar : MenuBar
     {
-        private FakeDriver _d = (FakeDriver)Application.Driver;
 
         // The expected strings when the menu is closed
         public string ClosedMenuText => MenuBarText + "\n";

+ 3 - 7
Tests/UnitTests/Views/ProgressBarTests.cs

@@ -26,7 +26,7 @@ public class ProgressBarTests
     [AutoInitShutdown]
     public void Fraction_Redraw ()
     {
-        var driver = (FakeDriver)Application.Driver;
+        var driver = Application.Driver;
 
         var pb = new ProgressBar { Width = 5 };
 
@@ -101,8 +101,6 @@ public class ProgressBarTests
     [AutoInitShutdown]
     public void ProgressBarFormat_MarqueeBlocks_MarqueeContinuous_Setter ()
     {
-        var driver = (FakeDriver)Application.Driver;
-
         var pb1 = new ProgressBar { ProgressBarStyle = ProgressBarStyle.MarqueeBlocks };
         var pb2 = new ProgressBar { ProgressBarStyle = ProgressBarStyle.MarqueeContinuous };
 
@@ -144,8 +142,6 @@ public class ProgressBarTests
     [AutoInitShutdown]
     public void ProgressBarStyle_Setter ()
     {
-        var driver = (FakeDriver)Application.Driver;
-
         var pb = new ProgressBar ();
 
         pb.ProgressBarStyle = ProgressBarStyle.Blocks;
@@ -165,7 +161,7 @@ public class ProgressBarTests
     [AutoInitShutdown]
     public void Pulse_Redraw_BidirectionalMarquee_False ()
     {
-        var driver = (FakeDriver)Application.Driver;
+        var driver = Application.Driver;
 
         var pb = new ProgressBar
         {
@@ -873,7 +869,7 @@ public class ProgressBarTests
     [AutoInitShutdown]
     public void Pulse_Redraw_BidirectionalMarquee_True_Default ()
     {
-        var driver = (FakeDriver)Application.Driver;
+        var driver = Application.Driver;
 
         var pb = new ProgressBar { Width = 15, ProgressBarStyle = ProgressBarStyle.MarqueeBlocks };
 

+ 3 - 3
Tests/UnitTests/Views/RadioGroupTests.cs

@@ -533,7 +533,7 @@ public class RadioGroupTests (ITestOutputHelper output)
         top.Add (win);
 
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (30, 5);
+        AutoInitShutdownAttribute.FakeResize(new Size(30, 5));
 
         Assert.Equal (Orientation.Vertical, rg.Orientation);
         Assert.Equal (2, rg.RadioLabels.Length);
@@ -554,7 +554,7 @@ public class RadioGroupTests (ITestOutputHelper output)
         Assert.Equal (new (0, 0, 30, 5), pos);
 
         rg.Orientation = Orientation.Horizontal;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (Orientation.Horizontal, rg.Orientation);
         Assert.Equal (2, rg.HorizontalSpace);
@@ -575,7 +575,7 @@ public class RadioGroupTests (ITestOutputHelper output)
         Assert.Equal (new (0, 0, 30, 5), pos);
 
         rg.HorizontalSpace = 4;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (Orientation.Horizontal, rg.Orientation);
         Assert.Equal (4, rg.HorizontalSpace);

+ 4 - 4
Tests/UnitTests/Views/ScrollBarTests.cs

@@ -554,7 +554,7 @@ public class ScrollBarTests (ITestOutputHelper output)
         // Scroll to end
         scrollBar.Position = 19;
         Assert.Equal (10, scrollBar.Position);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (4, scrollBar.GetSliderPosition ());
         Assert.Equal (10, scrollBar.Position);
@@ -570,7 +570,7 @@ public class ScrollBarTests (ITestOutputHelper output)
             Flags = MouseFlags.Button1Clicked
         });
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (initialPos - increment, scrollBar.Position);
 
@@ -602,7 +602,7 @@ public class ScrollBarTests (ITestOutputHelper output)
 
         // Scroll to top
         scrollBar.Position = 0;
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (0, scrollBar.GetSliderPosition ());
         Assert.Equal (0, scrollBar.Position);
@@ -617,7 +617,7 @@ public class ScrollBarTests (ITestOutputHelper output)
             ScreenPosition = btnPoint,
             Flags = MouseFlags.Button1Clicked
         });
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (initialPos + increment, scrollBar.Position);
 

+ 8 - 8
Tests/UnitTests/Views/SpinnerViewTests.cs

@@ -15,33 +15,33 @@ public class SpinnerViewTests (ITestOutputHelper output)
 
         SpinnerView view = GetSpinnerView ();
 
-        Assert.Empty (Application.MainLoop.TimedEvents.Timeouts);
+        Assert.Empty (Application.TimedEvents.Timeouts);
         view.AutoSpin = true;
-        Assert.NotEmpty (Application.MainLoop.TimedEvents.Timeouts);
+        Assert.NotEmpty (Application.TimedEvents.Timeouts);
         Assert.True (view.AutoSpin);
 
         //More calls to AutoSpin do not add more timeouts
-        Assert.Single (Application.MainLoop.TimedEvents.Timeouts);
+        Assert.Single (Application.TimedEvents.Timeouts);
         view.AutoSpin = true;
         view.AutoSpin = true;
         view.AutoSpin = true;
         Assert.True (view.AutoSpin);
-        Assert.Single (Application.MainLoop.TimedEvents.Timeouts);
+        Assert.Single (Application.TimedEvents.Timeouts);
 
         if (callStop)
         {
             view.AutoSpin = false;
-            Assert.Empty (Application.MainLoop.TimedEvents.Timeouts);
+            Assert.Empty (Application.TimedEvents.Timeouts);
             Assert.False (view.AutoSpin);
         }
         else
         {
-            Assert.NotEmpty (Application.MainLoop.TimedEvents.Timeouts);
+            Assert.NotEmpty (Application.TimedEvents.Timeouts);
         }
 
         // Dispose clears timeout
         view.Dispose ();
-        Assert.Empty (Application.MainLoop.TimedEvents.Timeouts);
+        Assert.Empty (Application.TimedEvents.Timeouts);
         Application.Top.Dispose ();
     }
 
@@ -109,7 +109,7 @@ public class SpinnerViewTests (ITestOutputHelper output)
         Application.Begin (top);
 
         // Required to clear the initial 'Invoke nothing' that Begin does
-        Application.MainLoop.TimedEvents.Timeouts.Clear ();
+        Application.TimedEvents.Timeouts.Clear ();
 
         Assert.Equal (1, view.Frame.Width);
         Assert.Equal (1, view.Frame.Height);

+ 16 - 16
Tests/UnitTests/Views/TabViewTests.cs

@@ -130,21 +130,21 @@ public class TabViewTests (ITestOutputHelper output)
         {
             args = new () { ScreenPosition = new (i, 1), Flags = MouseFlags.ReportMousePosition };
             Application.RaiseMouseEvent (args);
-            Application.LayoutAndDraw ();
+            AutoInitShutdownAttribute.RunIteration ();
             Assert.Null (clicked);
             Assert.Equal (tab1, tv.SelectedTab);
         }
 
         args = new () { ScreenPosition = new (3, 1), Flags = MouseFlags.Button1Clicked };
         Application.RaiseMouseEvent (args);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (tab1, clicked);
         Assert.Equal (tab1, tv.SelectedTab);
 
         // Click to tab2
         args = new () { ScreenPosition = new (6, 1), Flags = MouseFlags.Button1Clicked };
         Application.RaiseMouseEvent (args);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (tab2, clicked);
         Assert.Equal (tab2, tv.SelectedTab);
 
@@ -157,7 +157,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         args = new () { ScreenPosition = new (3, 1), Flags = MouseFlags.Button1Clicked };
         Application.RaiseMouseEvent (args);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         // Tab 1 was clicked but event handler blocked navigation
         Assert.Equal (tab1, clicked);
@@ -165,7 +165,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         args = new () { ScreenPosition = new (12, 1), Flags = MouseFlags.Button1Clicked };
         Application.RaiseMouseEvent (args);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         // Clicking beyond last tab should raise event with null Tab
         Assert.Null (clicked);
@@ -218,7 +218,7 @@ public class TabViewTests (ITestOutputHelper output)
         // Click the right arrow
         var args = new MouseEventArgs { ScreenPosition = new (6, 2), Flags = MouseFlags.Button1Clicked };
         Application.RaiseMouseEvent (args);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Null (clicked);
         Assert.Equal (tab1, oldChanged);
         Assert.Equal (tab2, newChanged);
@@ -238,7 +238,7 @@ public class TabViewTests (ITestOutputHelper output)
         // Click the left arrow
         args = new () { ScreenPosition = new (0, 2), Flags = MouseFlags.Button1Clicked };
         Application.RaiseMouseEvent (args);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Null (clicked);
         Assert.Equal (tab2, oldChanged);
         Assert.Equal (tab1, newChanged);
@@ -308,7 +308,7 @@ public class TabViewTests (ITestOutputHelper output)
         // Click the right arrow
         var args = new MouseEventArgs { ScreenPosition = new (7, 3), Flags = MouseFlags.Button1Clicked };
         Application.RaiseMouseEvent (args);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Null (clicked);
         Assert.Equal (tab1, oldChanged);
         Assert.Equal (tab2, newChanged);
@@ -330,7 +330,7 @@ public class TabViewTests (ITestOutputHelper output)
         // Click the left arrow
         args = new () { ScreenPosition = new (1, 3), Flags = MouseFlags.Button1Clicked };
         Application.RaiseMouseEvent (args);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Null (clicked);
         Assert.Equal (tab2, oldChanged);
         Assert.Equal (tab1, newChanged);
@@ -381,7 +381,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         // Press the cursor up key to focus the selected tab
         Assert.True (Application.RaiseKeyDownEvent (Key.CursorUp));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         // Is the selected tab focused
         Assert.Equal (tab1, tv.SelectedTab);
@@ -399,7 +399,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         // Press the cursor right key to select the next tab
         Assert.True (Application.RaiseKeyDownEvent (Key.CursorRight));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (tab1, oldChanged);
         Assert.Equal (tab2, newChanged);
         Assert.Equal (tab2, tv.SelectedTab);
@@ -472,7 +472,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         // Press the cursor left key to select the previous tab
         Assert.True (Application.RaiseKeyDownEvent (Key.CursorLeft));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (tab2, oldChanged);
         Assert.Equal (tab1, newChanged);
         Assert.Equal (tab1, tv.SelectedTab);
@@ -482,7 +482,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         // Press the end key to select the last tab
         Assert.True (Application.RaiseKeyDownEvent (Key.End));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (tab1, oldChanged);
         Assert.Equal (tab2, newChanged);
         Assert.Equal (tab2, tv.SelectedTab);
@@ -491,7 +491,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         // Press the home key to select the first tab
         Assert.True (Application.RaiseKeyDownEvent (Key.Home));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (tab2, oldChanged);
         Assert.Equal (tab1, newChanged);
         Assert.Equal (tab1, tv.SelectedTab);
@@ -500,7 +500,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         // Press the page down key to select the next set of tabs
         Assert.True (Application.RaiseKeyDownEvent (Key.PageDown));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (tab1, oldChanged);
         Assert.Equal (tab2, newChanged);
         Assert.Equal (tab2, tv.SelectedTab);
@@ -509,7 +509,7 @@ public class TabViewTests (ITestOutputHelper output)
 
         // Press the page up key to select the previous set of tabs
         Assert.True (Application.RaiseKeyDownEvent (Key.PageUp));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (tab2, oldChanged);
         Assert.Equal (tab1, newChanged);
         Assert.Equal (tab1, tv.SelectedTab);

+ 12 - 12
Tests/UnitTests/Views/TableViewTests.cs

@@ -459,7 +459,7 @@ public class TableViewTests (ITestOutputHelper output)
         // is to specify a MinAcceptableWidth for the column
         style.MaxWidth = 10;
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected =
             $@"
@@ -478,7 +478,7 @@ public class TableViewTests (ITestOutputHelper output)
 
         style.RepresentationGetter = s => { return s.ToString ().Length < 15 ? s.ToString () : s.ToString ().Substring (0, 13) + "..."; };
         tableView.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected =
             $@"
@@ -505,7 +505,7 @@ public class TableViewTests (ITestOutputHelper output)
         style.MinAcceptableWidth = 5;
         tableView.SetNeedsDraw ();
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected =
             $@"
@@ -518,11 +518,11 @@ public class TableViewTests (ITestOutputHelper output)
 
         // Now test making the width too small for the MinAcceptableWidth
         // the Column won't fit so should not be rendered
-        var driver = (FakeDriver)Application.Driver;
+        var driver = Application.Driver;
         driver.ClearContents ();
 
         tableView.Viewport = new (0, 0, 9, 5);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected =
             $@"
@@ -538,7 +538,7 @@ public class TableViewTests (ITestOutputHelper output)
         // meet MinAcceptableWidth of 5.  Column width includes terminator line
         // symbol (e.g. ┤ or │)
         tableView.Viewport = new (0, 0, 10, 5);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected =
             $@"
@@ -559,7 +559,7 @@ public class TableViewTests (ITestOutputHelper output)
         tableView.MaxCellWidth = 10;
         tableView.MinCellWidth = 3;
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected =
             $@"
@@ -575,7 +575,7 @@ public class TableViewTests (ITestOutputHelper output)
         tableView.MinCellWidth = 10;
         tableView.SetNeedsDraw ();
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected =
             $@"
@@ -1066,7 +1066,7 @@ public class TableViewTests (ITestOutputHelper output)
         tv.HasFocus = focused;
         Assert.Equal (focused, tv.HasFocus);
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         var expected = $@"
 ┌─┬─┐
@@ -1099,7 +1099,7 @@ public class TableViewTests (ITestOutputHelper output)
         dt.Rows [0] [1] = 5;
 
         tv.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = $@"
 ┌─┬─┐
@@ -1194,7 +1194,7 @@ public class TableViewTests (ITestOutputHelper output)
         dt.Rows [0] [1] = 5;
 
         tv.SetNeedsDraw ();
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         expected = $@"
 ┌─┬─┐
@@ -2206,7 +2206,7 @@ public class TableViewTests (ITestOutputHelper output)
     [SetupFakeDriver]
     public void TestEnumerableDataSource_BasicTypes ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (100, 100);
         var tv = new TableView ();
         tv.SchemeName = "TopLevel";
         tv.Viewport = new (0, 0, 50, 6);

+ 1 - 1
Tests/UnitTests/Views/TextFieldTests.cs

@@ -825,7 +825,7 @@ public class TextFieldTests (ITestOutputHelper output)
         _textField.CursorPosition = 0;
         _textField.NewKeyDownEvent (Key.CursorRight.WithCtrl.WithShift);
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (4, _textField.CursorPosition);
 
         //                                             TAB to jump between text fields.

+ 45 - 45
Tests/UnitTests/Views/TextViewTests.cs

@@ -647,7 +647,7 @@ public class TextViewTests
         var top = new Toplevel ();
         top.Add (tv);
         RunState rs = Application.Begin (top);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.False (tv.WordWrap);
         Assert.Equal (Point.Empty, tv.CursorPosition);
@@ -663,7 +663,7 @@ This is the second line.
         tv.CursorPosition = new (3, 0);
         Assert.Equal (new (3, 0), tv.CursorPosition);
         Assert.True (tv.NewKeyDownEvent (Key.Backspace));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (2, 0), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -677,7 +677,7 @@ This is the second line.
         tv.CursorPosition = new (0, 1);
         Assert.Equal (new (0, 1), tv.CursorPosition);
         Assert.True (tv.NewKeyDownEvent (Key.Backspace));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (22, 0), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -688,7 +688,7 @@ Ths is the first line.This is the second line.
                                                       );
 
         Assert.True (tv.NewKeyDownEvent (Key.Enter));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 1), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -704,7 +704,7 @@ This is the second line.
             Assert.True (tv.NewKeyDownEvent (Key.Z.WithCtrl));
         }
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (envText, tv.Text);
         Assert.Equal (new (3, 0), tv.CursorPosition);
         Assert.False (tv.IsDirty);
@@ -721,7 +721,7 @@ This is the second line.
         var top = new Toplevel ();
         top.Add (tv);
         RunState rs = Application.Begin (top);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.True (tv.WordWrap);
         Assert.Equal (Point.Empty, tv.CursorPosition);
@@ -737,7 +737,7 @@ This is the second line.
         tv.CursorPosition = new (3, 0);
         Assert.Equal (new (3, 0), tv.CursorPosition);
         Assert.True (tv.NewKeyDownEvent (Key.Backspace));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (2, 0), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -751,7 +751,7 @@ This is the second line.
         tv.CursorPosition = new (0, 1);
         Assert.Equal (new (0, 1), tv.CursorPosition);
         Assert.True (tv.NewKeyDownEvent (Key.Backspace));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (22, 0), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -762,7 +762,7 @@ Ths is the first line.This is the second line.
                                                       );
 
         Assert.True (tv.NewKeyDownEvent (Key.Enter));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 1), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -778,7 +778,7 @@ This is the second line.
             Assert.True (tv.NewKeyDownEvent (Key.Z.WithCtrl));
         }
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (envText, tv.Text);
         Assert.Equal (new (3, 0), tv.CursorPosition);
@@ -796,7 +796,7 @@ This is the second line.
         var top = new Toplevel ();
         top.Add (tv);
         RunState rs = Application.Begin (top);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.False (tv.WordWrap);
         Assert.Equal (Point.Empty, tv.CursorPosition);
@@ -812,7 +812,7 @@ This is the second line.
         tv.CursorPosition = new (2, 0);
         Assert.Equal (new (2, 0), tv.CursorPosition);
         Assert.True (tv.NewKeyDownEvent (Key.Delete));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (2, 0), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -826,7 +826,7 @@ This is the second line.
         tv.CursorPosition = new (22, 0);
         Assert.Equal (new (22, 0), tv.CursorPosition);
         Assert.True (tv.NewKeyDownEvent (Key.Delete));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (22, 0), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -837,7 +837,7 @@ Ths is the first line.This is the second line.
                                                       );
 
         Assert.True (tv.NewKeyDownEvent (Key.Enter));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 1), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -869,7 +869,7 @@ This is the second line.
         var top = new Toplevel ();
         top.Add (tv);
         RunState rs = Application.Begin (top);
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.True (tv.WordWrap);
         Assert.Equal (Point.Empty, tv.CursorPosition);
@@ -885,7 +885,7 @@ This is the second line.
         tv.CursorPosition = new (2, 0);
         Assert.Equal (new (2, 0), tv.CursorPosition);
         Assert.True (tv.NewKeyDownEvent (Key.Delete));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (2, 0), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -899,7 +899,7 @@ This is the second line.
         tv.CursorPosition = new (22, 0);
         Assert.Equal (new (22, 0), tv.CursorPosition);
         Assert.True (tv.NewKeyDownEvent (Key.Delete));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (22, 0), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -910,7 +910,7 @@ Ths is the first line.This is the second line.
                                                       );
 
         Assert.True (tv.NewKeyDownEvent (Key.Enter));
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 1), tv.CursorPosition);
 
         DriverAssert.AssertDriverContentsWithFrameAre (
@@ -926,7 +926,7 @@ This is the second line.
             Assert.True (tv.NewKeyDownEvent (Key.Z.WithCtrl));
         }
 
-        Application.RunIteration (ref rs);
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (envText, tv.Text);
         Assert.Equal (new (2, 0), tv.CursorPosition);
@@ -5177,7 +5177,7 @@ This is the second line.
         Assert.True (_textView.Multiline);
         _textView.NewKeyDownEvent (Key.Tab);
         Assert.Equal ("\tTAB to jump between text fields.", _textView.Text);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -5186,7 +5186,7 @@ TAB to jump between text field",
                                                       );
 
         _textView.TabWidth = 4;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -5197,7 +5197,7 @@ TAB to jump between text field",
         _textView.NewKeyDownEvent (Key.Tab.WithShift);
         Assert.Equal ("TAB to jump between text fields.", _textView.Text);
         Assert.True (_textView.NeedsDraw);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -5262,8 +5262,8 @@ TAB to jump between text field",
         var top = new Toplevel ();
         top.Add (win);
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (15, 15);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.FakeResize(new Size(15, 15));
+        AutoInitShutdownAttribute.RunIteration ();
 
         //this passes
         Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (
@@ -5292,7 +5292,7 @@ TAB to jump between text field",
         tv.Used = false;
         tv.CursorPosition = Point.Empty;
         tv.InsertText ("\r\naaa\r\nbbb");
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -5340,8 +5340,8 @@ TAB to jump between text field",
         var top = new Toplevel ();
         top.Add (win);
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (15, 15);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.FakeResize(new Size (15, 15));
+        AutoInitShutdownAttribute.RunIteration ();
 
         //this passes
         Rectangle pos = DriverAssert.AssertDriverContentsWithFrameAre (
@@ -5370,7 +5370,7 @@ TAB to jump between text field",
         tv.Used = false;
         tv.CursorPosition = Point.Empty;
         tv.InsertText ("\naaa\nbbb");
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -5425,7 +5425,7 @@ TAB to jump between text field",
         var top = new Toplevel ();
         top.Add (tv);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.False (tv.WordWrap);
         Assert.Equal (Point.Empty, tv.CursorPosition);
@@ -5453,7 +5453,7 @@ This is the second line.
                                                        _output
                                                       );
 
-        ((FakeDriver)Application.Driver).SetBufferSize (6, 25);
+        AutoInitShutdownAttribute.FakeResize(new Size (6, 25));
         tv.SetRelativeLayout (Application.Screen.Size);
         tv.Draw ();
         Assert.Equal (new (4, 2), tv.CursorPosition);
@@ -6630,7 +6630,7 @@ line.
         var top = new Toplevel ();
         top.Add (tv);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.Equal (Point.Empty, tv.CursorPosition);
         Assert.Equal (0, tv.LeftColumn);
@@ -6644,7 +6644,7 @@ aaaa
 
         tv.CursorPosition = new (5, 0);
         Assert.True (tv.NewKeyDownEvent (Key.Backspace));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (0, tv.LeftColumn);
 
         DriverAssert.AssertDriverContentsAre (
@@ -6655,7 +6655,7 @@ aaa
                                              );
 
         Assert.True (tv.NewKeyDownEvent (Key.Backspace));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (0, tv.LeftColumn);
 
         DriverAssert.AssertDriverContentsAre (
@@ -6666,7 +6666,7 @@ aa
                                              );
 
         Assert.True (tv.NewKeyDownEvent (Key.Backspace));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (0, tv.LeftColumn);
 
         DriverAssert.AssertDriverContentsAre (
@@ -6677,7 +6677,7 @@ a
                                              );
 
         Assert.True (tv.NewKeyDownEvent (Key.Backspace));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (0, tv.LeftColumn);
 
         DriverAssert.AssertDriverContentsAre (
@@ -6688,7 +6688,7 @@ a
                                              );
 
         Assert.True (tv.NewKeyDownEvent (Key.Backspace));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (0, tv.LeftColumn);
 
         DriverAssert.AssertDriverContentsAre (
@@ -6710,7 +6710,7 @@ a
         _textView.Text = "Line 1.\nLine 2.";
         _textView.WordWrap = true;
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.True (_textView.WordWrap);
 
@@ -6725,12 +6725,12 @@ Line 2.",
         Assert.Equal ("Line 1.", _textView.SelectedText);
 
         Assert.True (_textView.NewKeyDownEvent (new (del)));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre ("Line 2.", _output);
 
         Assert.True (_textView.NewKeyDownEvent (Key.H.WithShift));
         Assert.NotEqual (Rectangle.Empty, _textView.NeedsDrawRect);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -7019,7 +7019,7 @@ line.
         var top = new Toplevel ();
         top.Add (tv);
         Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -7031,7 +7031,7 @@ This is the second line.",
         tv.Width = 10;
         tv.Height = 25;
         tv.WordWrap = true;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                        @"
@@ -7075,7 +7075,7 @@ line.  ",
         var top = new Toplevel ();
         top.Add (tv);
         RunState rs = Application.Begin (top);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         Assert.True (tv.InheritsPreviousAttribute);
 
@@ -7117,7 +7117,7 @@ Error   ";
         DriverAssert.AssertDriverAttributesAre (expectedColor, _output, Application.Driver, attributes);
 
         tv.WordWrap = true;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         DriverAssert.AssertDriverContentsWithFrameAre (expectedText, _output);
         DriverAssert.AssertDriverAttributesAre (expectedColor, _output, Application.Driver, attributes);
 
@@ -7129,7 +7129,7 @@ Error   ";
         tv.IsSelecting = false;
         tv.CursorPosition = new (2, 4);
         tv.Paste ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expectedText = @"
 TopLevel  
@@ -7164,7 +7164,7 @@ Dialogror ";
         tv.IsSelecting = false;
         tv.CursorPosition = new (2, 4);
         tv.Paste ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         expectedText = @"
 TopLevel  

+ 90 - 88
Tests/UnitTests/Views/TileViewTests.cs

@@ -52,7 +52,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         tv.Tiles.ElementAt (0).MinSize = int.MaxValue;
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -84,7 +84,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (0, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -104,7 +104,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         tv.Tiles.ElementAt (0).MinSize = int.MaxValue;
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -136,7 +136,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (0, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -158,7 +158,7 @@ public class TileViewTests (ITestOutputHelper output)
         tv.Tiles.ElementAt (1).MinSize = 2;
         tv.Tiles.ElementAt (2).MinSize = 3;
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -179,7 +179,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (1, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -221,7 +221,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         tv.Tiles.ElementAt (1).MinSize = 2;
         tv.Tiles.ElementAt (2).MinSize = 3;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -242,7 +242,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (1, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -265,7 +265,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (1, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"  
@@ -287,7 +287,7 @@ public class TileViewTests (ITestOutputHelper output)
         tv.Tiles.ElementAt (3).MinSize = 2;
         tv.Tiles.ElementAt (4).MinSize = 1;
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -308,7 +308,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (3, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -330,7 +330,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (3, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -351,7 +351,7 @@ public class TileViewTests (ITestOutputHelper output)
         tv.Tiles.ElementAt (3).MinSize = 2;
         tv.Tiles.ElementAt (4).MinSize = 1;
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -372,7 +372,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (3, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"   
@@ -393,7 +393,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (3, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -411,7 +411,7 @@ public class TileViewTests (ITestOutputHelper output)
     {
         TileView tv = Get5x1TilesView ();
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -429,7 +429,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         Assert.False (tv.SetSplitterPos (0, 0));
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -452,7 +452,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (0, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -470,7 +470,7 @@ public class TileViewTests (ITestOutputHelper output)
     {
         TileView tv = Get5x1TilesView (false);
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -486,7 +486,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.True (tv.SetSplitterPos (0, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -509,7 +509,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (0, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -528,7 +528,7 @@ public class TileViewTests (ITestOutputHelper output)
     {
         TileView tv = Get5x1TilesView ();
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -549,7 +549,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (1, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -570,7 +570,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (1, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -588,7 +588,7 @@ public class TileViewTests (ITestOutputHelper output)
     {
         TileView tv = Get5x1TilesView (false);
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -609,7 +609,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (1, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -631,7 +631,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (1, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -649,7 +649,7 @@ public class TileViewTests (ITestOutputHelper output)
     {
         TileView tv = Get5x1TilesView ();
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -670,7 +670,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (3, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -691,7 +691,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (3, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -709,7 +709,7 @@ public class TileViewTests (ITestOutputHelper output)
     {
         TileView tv = Get5x1TilesView (false);
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"   
@@ -730,7 +730,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (3, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"  
@@ -752,7 +752,7 @@ public class TileViewTests (ITestOutputHelper output)
             Assert.False (tv.SetSplitterPos (3, x), $"Assert failed for x={x}");
         }
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -973,7 +973,7 @@ public class TileViewTests (ITestOutputHelper output)
     {
         TileView tileView = GetNestedContainer3Right1Down (true);
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -994,7 +994,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (1).ContentView.Visible = true;
         tileView.Tiles.ElementAt (2).ContentView.Visible = true;
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1013,7 +1013,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         tileView.Tiles.ElementAt (0).ContentView.Visible = true;
         tileView.Tiles.ElementAt (1).ContentView.Visible = false;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1033,7 +1033,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = true;
         tileView.Tiles.ElementAt (1).ContentView.Visible = true;
         tileView.Tiles.ElementAt (2).ContentView.Visible = false;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1053,7 +1053,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = true;
         tileView.Tiles.ElementAt (1).ContentView.Visible = false;
         tileView.Tiles.ElementAt (2).ContentView.Visible = false;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1073,7 +1073,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = false;
         tileView.Tiles.ElementAt (1).ContentView.Visible = true;
         tileView.Tiles.ElementAt (2).ContentView.Visible = false;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1093,7 +1093,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = false;
         tileView.Tiles.ElementAt (1).ContentView.Visible = false;
         tileView.Tiles.ElementAt (2).ContentView.Visible = true;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1115,7 +1115,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = false;
         tileView.Tiles.ElementAt (1).ContentView.Visible = false;
         tileView.Tiles.ElementAt (2).ContentView.Visible = false;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1138,7 +1138,7 @@ public class TileViewTests (ITestOutputHelper output)
     public void TestNestedContainer3RightAnd1Down_TileVisibility_WithoutBorder ()
     {
         TileView tileView = GetNestedContainer3Right1Down (false);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -1158,7 +1158,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = false;
         tileView.Tiles.ElementAt (1).ContentView.Visible = true;
         tileView.Tiles.ElementAt (2).ContentView.Visible = true;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1178,7 +1178,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = true;
         tileView.Tiles.ElementAt (1).ContentView.Visible = false;
         tileView.Tiles.ElementAt (2).ContentView.Visible = true;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1198,7 +1198,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = true;
         tileView.Tiles.ElementAt (1).ContentView.Visible = true;
         tileView.Tiles.ElementAt (2).ContentView.Visible = false;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1218,7 +1218,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = true;
         tileView.Tiles.ElementAt (1).ContentView.Visible = false;
         tileView.Tiles.ElementAt (2).ContentView.Visible = false;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1238,7 +1238,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = false;
         tileView.Tiles.ElementAt (1).ContentView.Visible = true;
         tileView.Tiles.ElementAt (2).ContentView.Visible = false;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1258,7 +1258,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = false;
         tileView.Tiles.ElementAt (1).ContentView.Visible = false;
         tileView.Tiles.ElementAt (2).ContentView.Visible = true;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1280,7 +1280,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.Tiles.ElementAt (0).ContentView.Visible = false;
         tileView.Tiles.ElementAt (1).ContentView.Visible = false;
         tileView.Tiles.ElementAt (2).ContentView.Visible = false;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1294,7 +1294,7 @@ public class TileViewTests (ITestOutputHelper output)
     public void TestNestedContainer3RightAnd1Down_TitleDoesNotOverspill ()
     {
         TileView tileView = GetNestedContainer3Right1Down (true, true, 1);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -1324,7 +1324,7 @@ public class TileViewTests (ITestOutputHelper output)
             .Tiles.ElementAt (1)
             .Title = new ('y', 100);
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -1348,7 +1348,7 @@ public class TileViewTests (ITestOutputHelper output)
     {
         TileView tileView = GetNestedContainer3Right1Down (true);
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -1368,7 +1368,7 @@ public class TileViewTests (ITestOutputHelper output)
         Tile removed = tileView.RemoveTile (1);
         Assert.Same (toRemove, removed);
         Assert.DoesNotContain (removed, tileView.Tiles);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1387,7 +1387,7 @@ public class TileViewTests (ITestOutputHelper output)
         // cannot remove at this index because there is only one horizontal tile left
         Assert.Null (tileView.RemoveTile (2));
         tileView.RemoveTile (0);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1404,7 +1404,7 @@ public class TileViewTests (ITestOutputHelper output)
         DriverAssert.AssertDriverContentsAre (looksLike, output);
 
         Assert.NotNull (tileView.RemoveTile (0));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1429,7 +1429,7 @@ public class TileViewTests (ITestOutputHelper output)
     public void TestNestedContainer3RightAnd1Down_WithBorder_RendersNicely ()
     {
         TileView tileView = GetNestedContainer3Right1Down (true);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -1660,7 +1660,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.NewKeyDownEvent (new (tileView.ToggleResizable));
 
         Assert.True (line.HasFocus);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"    
@@ -1672,7 +1672,7 @@ public class TileViewTests (ITestOutputHelper output)
         // Now move splitter line down
         tileView.NewKeyDownEvent (Key.CursorDown);
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"    
@@ -1683,10 +1683,10 @@ public class TileViewTests (ITestOutputHelper output)
 
         // And 2 up
         line.NewKeyDownEvent (Key.CursorUp);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         line.NewKeyDownEvent (Key.CursorUp);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"    
@@ -1711,7 +1711,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         // position should remain where it was, at 50%
         Assert.Equal (Pos.Percent (50), tileView.SplitterDistances.ElementAt (0));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"    
@@ -1722,7 +1722,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         // Now move splitter line down (allowed
         line.NewKeyDownEvent (Key.CursorDown);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"    
@@ -1736,7 +1736,7 @@ public class TileViewTests (ITestOutputHelper output)
         line.NewKeyDownEvent (Key.CursorUp);
 
         tileView.SetNeedsDraw ();
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"    
@@ -1875,7 +1875,7 @@ public class TileViewTests (ITestOutputHelper output)
         TileView tileView = Get11By3TileView (out LineView line);
         tileView.NewKeyDownEvent (new (tileView.ToggleResizable));
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -1886,7 +1886,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         // Now while focused move the splitter 1 unit right
         line.NewKeyDownEvent (Key.CursorRight);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1899,7 +1899,7 @@ public class TileViewTests (ITestOutputHelper output)
         line.NewKeyDownEvent (Key.CursorLeft);
         tileView.Layout ();
         line.NewKeyDownEvent (Key.CursorLeft);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1917,7 +1917,7 @@ public class TileViewTests (ITestOutputHelper output)
         tileView.SetSplitterPos (0, Pos.Percent (50));
         Assert.IsType<PosPercent> (tileView.SplitterDistances.ElementAt (0));
         tileView.NewKeyDownEvent (new (tileView.ToggleResizable));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -1928,7 +1928,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         // Now while focused move the splitter 1 unit right
         line.NewKeyDownEvent (Key.CursorRight);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1944,7 +1944,7 @@ public class TileViewTests (ITestOutputHelper output)
         line.NewKeyDownEvent (Key.CursorLeft);
         tileView.Layout ();
         line.NewKeyDownEvent (Key.CursorLeft);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1963,7 +1963,7 @@ public class TileViewTests (ITestOutputHelper output)
     {
         TileView tileView = Get11By3TileView (out LineView line, true);
         tileView.NewKeyDownEvent (new (tileView.ToggleResizable));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -1974,7 +1974,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         // Now while focused move the splitter 1 unit right
         line.NewKeyDownEvent (Key.CursorRight);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -1987,7 +1987,7 @@ public class TileViewTests (ITestOutputHelper output)
         line.NewKeyDownEvent (Key.CursorLeft);
         tileView.Layout ();
         line.NewKeyDownEvent (Key.CursorLeft);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -2010,7 +2010,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         // Should stay where it was originally at (50%)
         Assert.Equal (Pos.Percent (50), tileView.SplitterDistances.ElementAt (0));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         // so should ignore the 2 distance and stick to 6
         var looksLike =
@@ -2023,13 +2023,13 @@ public class TileViewTests (ITestOutputHelper output)
         // Keyboard movement on splitter should have no effect because it
         // would take us below the minimum splitter size
         line.NewKeyDownEvent (Key.CursorLeft);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsAre (looksLike, output);
 
         // but we can continue to move the splitter right if we want
         line.NewKeyDownEvent (Key.CursorRight);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -2053,7 +2053,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         // Should stay where it was originally at (50%)
         Assert.Equal (Pos.Percent (50), tileView.SplitterDistances.ElementAt (0));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         // so should ignore the 2 distance and stick to 5
         var looksLike =
@@ -2066,13 +2066,13 @@ public class TileViewTests (ITestOutputHelper output)
         // Keyboard movement on splitter should have no effect because it
         // would take us below the minimum splitter size
         line.NewKeyDownEvent (Key.CursorLeft);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsAre (looksLike, output);
 
         // but we can continue to move the splitter right if we want
         line.NewKeyDownEvent (Key.CursorRight);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -2090,7 +2090,7 @@ public class TileViewTests (ITestOutputHelper output)
         TileView tileView = Get11By3TileView (out LineView line);
         tileView.NewKeyDownEvent (new (tileView.ToggleResizable));
         tileView.Tiles.ElementAt (1).MinSize = 6;
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         // distance leaves too little space for view2 (less than 6 would remain)
         Assert.False (tileView.SetSplitterPos (0, 8));
@@ -2098,7 +2098,7 @@ public class TileViewTests (ITestOutputHelper output)
         //  Should stay where it was originally at (50%)
         Assert.Equal (Pos.Percent (50), tileView.SplitterDistances.ElementAt (0));
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         // so should ignore the 2 distance and stick to 6
         var looksLike =
@@ -2111,13 +2111,13 @@ public class TileViewTests (ITestOutputHelper output)
         // Keyboard movement on splitter should have no effect because it
         // would take us below the minimum splitter size
         line.NewKeyDownEvent (Key.CursorRight);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsAre (looksLike, output);
 
         // but we can continue to move the splitter left if we want
         line.NewKeyDownEvent (Key.CursorLeft);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -2138,12 +2138,12 @@ public class TileViewTests (ITestOutputHelper output)
 
         // distance leaves too little space for view2 (less than 5 would remain)
         Assert.False (tileView.SetSplitterPos (0, 8));
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         //  Should stay where it was originally at (50%)
         Assert.Equal (Pos.Percent (50), tileView.SplitterDistances.ElementAt (0));
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         // so should ignore the 2 distance and stick to 6
         var looksLike =
@@ -2156,13 +2156,13 @@ public class TileViewTests (ITestOutputHelper output)
         // Keyboard movement on splitter should have no effect because it
         // would take us below the minimum splitter size
         line.NewKeyDownEvent (Key.CursorRight);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsAre (looksLike, output);
 
         // but we can continue to move the splitter left if we want
         line.NewKeyDownEvent (Key.CursorLeft);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         looksLike =
             @"
@@ -2179,7 +2179,7 @@ public class TileViewTests (ITestOutputHelper output)
     {
         TileView tileView = Get11By3TileView (out LineView line, true);
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         var looksLike =
             @"
@@ -2190,7 +2190,7 @@ public class TileViewTests (ITestOutputHelper output)
 
         // Keyboard movement on splitter should have no effect if it is not focused
         tileView.NewKeyDownEvent (Key.CursorRight);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
 
         DriverAssert.AssertDriverContentsAre (looksLike, output);
     }
@@ -2262,6 +2262,8 @@ public class TileViewTests (ITestOutputHelper output)
 
         Application.Begin (Application.Top);
 
+        Application.Top.SetNeedsDraw();
+
         return tv;
     }
 

+ 18 - 18
Tests/UnitTests/Views/ToplevelTests.cs

@@ -285,7 +285,7 @@ public class ToplevelTests
 
                                      if (iterations == 0)
                                      {
-                                         ((FakeDriver)Application.Driver!).SetBufferSize (15, 7);
+                                         AutoInitShutdownAttribute.FakeResize(new Size(15, 7));
 
                                          // Don't use MessageBox here; it's too complicated for this unit test; just use Window
                                          testWindow = new ()
@@ -324,7 +324,7 @@ public class ToplevelTests
                                                                           ScreenPosition = new (2, 2), Flags = MouseFlags.Button1Pressed
                                                                               | MouseFlags.ReportMousePosition
                                                                       });
-                                         Application.LayoutAndDraw ();
+                                         AutoInitShutdownAttribute.RunIteration ();
 
                                          Assert.Equal (Application.Top.Border, Application.MouseGrabHandler.MouseGrabView);
                                          Assert.Equal (new (1, 2, 10, 3), Application.Top.Frame);
@@ -347,7 +347,7 @@ public class ToplevelTests
                                                                           ScreenPosition = new (2, 1),
                                                                           Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
                                                                       });
-                                         Application.LayoutAndDraw ();
+                                         AutoInitShutdownAttribute.RunIteration ();
 
                                          Assert.Equal (Application.Top!.Border, Application.MouseGrabHandler.MouseGrabView);
                                          Assert.Equal (new (1, 1, 10, 3), Application.Top.Frame);
@@ -366,7 +366,7 @@ public class ToplevelTests
 
                                          // Ungrab the mouse
                                          Application.RaiseMouseEvent (new () { ScreenPosition = new (2, 1), Flags = MouseFlags.Button1Released });
-                                         Application.LayoutAndDraw ();
+                                         AutoInitShutdownAttribute.RunIteration ();
 
                                          Assert.Null (Application.MouseGrabHandler.MouseGrabView);
                                      }
@@ -405,7 +405,7 @@ public class ToplevelTests
 
                                      if (iterations == 0)
                                      {
-                                         ((FakeDriver)Application.Driver!).SetBufferSize (30, 10);
+                                         AutoInitShutdownAttribute.FakeResize(new Size(30, 10));
                                      }
                                      else if (iterations == 1)
                                      {
@@ -507,10 +507,10 @@ public class ToplevelTests
         top.BeginInit ();
         top.EndInit ();
 
-        Exception exception = Record.Exception (() => ((FakeDriver)Application.Driver!).SetBufferSize (0, 10));
+        Exception exception = Record.Exception (() => ((IFakeDriverV2)Application.Driver!).SetBufferSize (0, 10));
         Assert.Null (exception);
 
-        exception = Record.Exception (() => ((FakeDriver)Application.Driver!).SetBufferSize (10, 0));
+        exception = Record.Exception (() => ((IFakeDriverV2)Application.Driver!).SetBufferSize (10, 0));
         Assert.Null (exception);
     }
 
@@ -596,9 +596,9 @@ public class ToplevelTests
         Toplevel top = new ();
         var window = new Window { Width = 20, Height = 3, Arrangement = ViewArrangement.Movable };
         RunState rsTop = Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (40, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(40, 10));
         RunState rsWindow = Application.Begin (window);
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 0, 40, 10), top.Frame);
         Assert.Equal (new (0, 0, 20, 3), window.Frame);
 
@@ -614,12 +614,12 @@ public class ToplevelTests
                                          ScreenPosition = new (-11, -4), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
                                      });
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 0, 40, 10), top.Frame);
         Assert.Equal (new (-11, -4, 20, 3), window.Frame);
 
         // Changes Top size to same size as Dialog more menu and scroll bar
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 3);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 3));
 
         Application.RaiseMouseEvent (
                                      new ()
@@ -627,12 +627,12 @@ public class ToplevelTests
                                          ScreenPosition = new (-1, -1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
                                      });
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 0, 20, 3), top.Frame);
         Assert.Equal (new (-1, -1, 20, 3), window.Frame);
 
         // Changes Top size smaller than Dialog size
-        ((FakeDriver)Application.Driver!).SetBufferSize (19, 2);
+        AutoInitShutdownAttribute.FakeResize(new Size(19, 2));
 
         Application.RaiseMouseEvent (
                                      new ()
@@ -640,7 +640,7 @@ public class ToplevelTests
                                          ScreenPosition = new (-1, -1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
                                      });
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 0, 19, 2), top.Frame);
         Assert.Equal (new (-1, -1, 20, 3), window.Frame);
 
@@ -650,7 +650,7 @@ public class ToplevelTests
                                          ScreenPosition = new (18, 1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
                                      });
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 0, 19, 2), top.Frame);
         Assert.Equal (new (18, 1, 20, 3), window.Frame);
 
@@ -661,7 +661,7 @@ public class ToplevelTests
                                          ScreenPosition = new (19, 2), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
                                      });
 
-        Application.LayoutAndDraw ();
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (new (0, 0, 19, 2), top.Frame);
         Assert.Equal (new (19, 2, 20, 3), window.Frame);
 
@@ -700,7 +700,7 @@ public class ToplevelTests
         Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
 
         var firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (window.Border, Application.MouseGrabHandler.MouseGrabView);
 
         Assert.Equal (new (0, 0, 10, 3), window.Frame);
@@ -712,7 +712,7 @@ public class ToplevelTests
                                      });
 
         firstIteration = false;
-        Application.RunIteration (ref rs, firstIteration);
+        AutoInitShutdownAttribute.RunIteration ();
         Assert.Equal (window.Border, Application.MouseGrabHandler.MouseGrabView);
         Assert.Equal (new (1, 1, 10, 3), window.Frame);
 

+ 2 - 2
Tests/UnitTests/Views/TreeTableSourceTests.cs

@@ -30,7 +30,7 @@ public class TreeTableSourceTests : IDisposable
     [SetupFakeDriver]
     public void TestTreeTableSource_BasicExpanding_WithKeyboard ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (100, 100);
         TableView tv = GetTreeTable (out _);
 
         tv.Style.GetOrCreateColumnStyle (1).MinAcceptableWidth = 1;
@@ -91,7 +91,7 @@ public class TreeTableSourceTests : IDisposable
     [SetupFakeDriver]
     public void TestTreeTableSource_BasicExpanding_WithMouse ()
     {
-        ((FakeDriver)Application.Driver!).SetBufferSize (100, 100);
+        ((IFakeDriverV2)Application.Driver!).SetBufferSize (100, 100);
 
         TableView tv = GetTreeTable (out _);
 

+ 1 - 1
Tests/UnitTests/Views/ViewDisposalTest.cs

@@ -62,7 +62,7 @@ public class ViewDisposalTest (ITestOutputHelper output)
         // make sure the application is doing to the views whatever its supposed to do to the views
         for (var i = 0; i < 100; i++)
         {
-            Application.LayoutAndDraw ();
+            AutoInitShutdownAttribute.RunIteration ();
         }
 
         top.Remove (container);

+ 3 - 3
Tests/UnitTests/Views/WindowTests.cs

@@ -51,7 +51,7 @@ public class WindowTests (ITestOutputHelper output)
         Toplevel top = new ();
         top.Add (win);
         Application.Begin (top);
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 10));
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -68,7 +68,7 @@ public class WindowTests (ITestOutputHelper output)
                                                       output
                                                      );
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (40, 20);
+        AutoInitShutdownAttribute.FakeResize(new Size(40, 20));
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"
@@ -95,7 +95,7 @@ public class WindowTests (ITestOutputHelper output)
                                                       output
                                                      );
 
-        ((FakeDriver)Application.Driver!).SetBufferSize (20, 10);
+        AutoInitShutdownAttribute.FakeResize(new Size(20, 10));
 
         DriverAssert.AssertDriverContentsWithFrameAre (
                                                       @"