using Xunit.Abstractions; namespace ApplicationTests.RunnableTests; /// /// Tests for IRunnable interface and Runnable base class. /// public class RunnableTests (ITestOutputHelper output) { private readonly ITestOutputHelper _output = output; [Fact] public void Runnable_Implements_IRunnable () { // Arrange & Act Runnable runnable = new (); // Assert Assert.IsAssignableFrom (runnable); Assert.IsAssignableFrom> (runnable); } [Fact] public void Runnable_Result_DefaultsToDefault () { // Arrange & Act Runnable runnable = new (); // Assert Assert.Equal (0, runnable.Result); } [Fact] public void Runnable_Result_CanBeSet () { // Arrange Runnable runnable = new (); // Act runnable.Result = 42; // Assert Assert.Equal (42, runnable.Result); } [Fact] public void Runnable_Result_CanBeSetToNull () { // Arrange Runnable runnable = new (); // Act runnable.Result = null; // Assert Assert.Null (runnable.Result); } [Fact] public void Runnable_IsRunning_ReturnsFalse_WhenNotRunning () { // Arrange IApplication app = Application.Create (); app.Init (); Runnable runnable = new (); // Act & Assert Assert.False (runnable.IsRunning); // Cleanup app.Dispose (); } [Fact] public void Runnable_IsModal_ReturnsFalse_WhenNotRunning () { // Arrange Runnable runnable = new (); // Act & Assert // IsModal should be false when the runnable has no app or is not TopRunnable Assert.False (runnable.IsModal); } [Fact] public void RaiseIsRunningChanging_ClearsResult_WhenStarting () { // Arrange Runnable runnable = new () { Result = 42 }; // Act bool canceled = runnable.RaiseIsRunningChanging (false, true); // Assert Assert.False (canceled); Assert.Equal (0, runnable.Result); // Result should be cleared } [Fact] public void RaiseIsRunningChanging_CanBeCanceled_ByVirtualMethod () { // Arrange CancelableRunnable runnable = new (); // Act bool canceled = runnable.RaiseIsRunningChanging (false, true); // Assert Assert.True (canceled); } [Fact] public void RaiseIsRunningChanging_CanBeCanceled_ByEvent () { // Arrange Runnable runnable = new (); var eventRaised = false; runnable.IsRunningChanging += (s, e) => { eventRaised = true; e.Cancel = true; }; // Act bool canceled = runnable.RaiseIsRunningChanging (false, true); // Assert Assert.True (eventRaised); Assert.True (canceled); } [Fact] public void RaiseIsRunningChanged_RaisesEvent () { // Arrange Runnable runnable = new (); var eventRaised = false; bool? receivedValue = null; runnable.IsRunningChanged += (s, e) => { eventRaised = true; receivedValue = e.Value; }; // Act runnable.RaiseIsRunningChangedEvent (true); // Assert Assert.True (eventRaised); Assert.True (receivedValue); } [Fact] public void RaiseIsModalChanged_RaisesEvent () { // Arrange Runnable runnable = new (); var eventRaised = false; bool? receivedValue = null; runnable.IsModalChanged += (s, e) => { eventRaised = true; receivedValue = e.Value; }; // Act runnable.RaiseIsModalChangedEvent (true); // Assert Assert.True (eventRaised); Assert.True (receivedValue); } /// /// Test runnable that can cancel lifecycle changes. /// private class CancelableRunnable : Runnable { protected override bool OnIsRunningChanging (bool oldIsRunning, bool newIsRunning) => true; // Always cancel } }