RunnableLifecycleTests.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. using Xunit.Abstractions;
  2. namespace UnitTests_Parallelizable.ApplicationTests.RunnableTests;
  3. /// <summary>
  4. /// Tests for IRunnable lifecycle behavior.
  5. /// </summary>
  6. public class RunnableLifecycleTests (ITestOutputHelper output)
  7. {
  8. private readonly ITestOutputHelper _output = output;
  9. [Fact]
  10. public void Runnable_OnIsRunningChanging_CanExtractResult ()
  11. {
  12. // Arrange
  13. ResultExtractingRunnable runnable = new ();
  14. runnable.TestValue = "extracted";
  15. // Act
  16. bool canceled = runnable.RaiseIsRunningChanging (true, false); // Stopping
  17. // Assert
  18. Assert.False (canceled);
  19. Assert.Equal ("extracted", runnable.Result);
  20. }
  21. [Fact]
  22. public void Runnable_OnIsRunningChanging_ClearsResultWhenStarting ()
  23. {
  24. // Arrange
  25. ResultExtractingRunnable runnable = new () { Result = "previous" };
  26. // Act
  27. bool canceled = runnable.RaiseIsRunningChanging (false, true); // Starting
  28. // Assert
  29. Assert.False (canceled);
  30. Assert.Null (runnable.Result); // Result should be cleared
  31. }
  32. [Fact]
  33. public void Runnable_CanCancelStoppingWithUnsavedChanges ()
  34. {
  35. // Arrange
  36. UnsavedChangesRunnable runnable = new () { HasUnsavedChanges = true };
  37. // Act
  38. bool canceled = runnable.RaiseIsRunningChanging (true, false); // Stopping
  39. // Assert
  40. Assert.True (canceled); // Should be canceled
  41. }
  42. [Fact]
  43. public void Runnable_AllowsStoppingWithoutUnsavedChanges ()
  44. {
  45. // Arrange
  46. UnsavedChangesRunnable runnable = new () { HasUnsavedChanges = false };
  47. // Act
  48. bool canceled = runnable.RaiseIsRunningChanging (true, false); // Stopping
  49. // Assert
  50. Assert.False (canceled); // Should not be canceled
  51. }
  52. [Fact]
  53. public void Runnable_OnIsRunningChanged_CalledAfterStateChange ()
  54. {
  55. // Arrange
  56. TrackedRunnable runnable = new ();
  57. // Act
  58. runnable.RaiseIsRunningChangedEvent (true);
  59. // Assert
  60. Assert.True (runnable.OnIsRunningChangedCalled);
  61. Assert.True (runnable.LastIsRunningValue);
  62. }
  63. [Fact]
  64. public void Runnable_OnIsModalChanged_CalledAfterStateChange ()
  65. {
  66. // Arrange
  67. TrackedRunnable runnable = new ();
  68. // Act
  69. runnable.RaiseIsModalChangedEvent (true);
  70. // Assert
  71. Assert.True (runnable.OnIsModalChangedCalled);
  72. Assert.True (runnable.LastIsModalValue);
  73. }
  74. /// <summary>
  75. /// Test runnable that extracts result in OnIsRunningChanging.
  76. /// </summary>
  77. private class ResultExtractingRunnable : Runnable<string>
  78. {
  79. public string? TestValue { get; set; }
  80. protected override bool OnIsRunningChanging (bool oldIsRunning, bool newIsRunning)
  81. {
  82. if (!newIsRunning) // Stopping
  83. {
  84. // Extract result before removal from stack
  85. Result = TestValue;
  86. }
  87. return base.OnIsRunningChanging (oldIsRunning, newIsRunning);
  88. }
  89. }
  90. /// <summary>
  91. /// Test runnable that can prevent stopping with unsaved changes.
  92. /// </summary>
  93. private class UnsavedChangesRunnable : Runnable<int>
  94. {
  95. public bool HasUnsavedChanges { get; set; }
  96. protected override bool OnIsRunningChanging (bool oldIsRunning, bool newIsRunning)
  97. {
  98. if (!newIsRunning && HasUnsavedChanges) // Stopping with unsaved changes
  99. {
  100. return true; // Cancel stopping
  101. }
  102. return base.OnIsRunningChanging (oldIsRunning, newIsRunning);
  103. }
  104. }
  105. /// <summary>
  106. /// Test runnable that tracks lifecycle method calls.
  107. /// </summary>
  108. private class TrackedRunnable : Runnable<int>
  109. {
  110. public bool OnIsRunningChangedCalled { get; private set; }
  111. public bool LastIsRunningValue { get; private set; }
  112. public bool OnIsModalChangedCalled { get; private set; }
  113. public bool LastIsModalValue { get; private set; }
  114. protected override void OnIsRunningChanged (bool newIsRunning)
  115. {
  116. OnIsRunningChangedCalled = true;
  117. LastIsRunningValue = newIsRunning;
  118. base.OnIsRunningChanged (newIsRunning);
  119. }
  120. protected override void OnIsModalChanged (bool newIsModal)
  121. {
  122. OnIsModalChangedCalled = true;
  123. LastIsModalValue = newIsModal;
  124. base.OnIsModalChanged (newIsModal);
  125. }
  126. }
  127. }