From 832293400de99fac3b8dab180596078edb52a64b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Thu, 9 Apr 2026 21:12:42 +0200 Subject: [PATCH 1/3] feat: add callback for `PeriodicTimer` --- .../MockTimeSystem.cs | 2 +- .../TimeSystem/INotificationHandler.cs | 9 +- .../IPeriodicTimerNotificationHandler.cs | 27 ++++ .../TimeSystem/NotificationHandler.cs | 42 +++++- .../TimeSystem/PeriodicTimerFactoryMock.cs | 7 +- .../TimeSystem/PeriodicTimerMock.cs | 10 +- .../TimeSystem/NotificationHandlerTests.cs | 124 ++++++++++++++++++ .../TimeSystem/PeriodicTimerMockTests.cs | 106 +++++++++++++++ 8 files changed, 320 insertions(+), 7 deletions(-) create mode 100644 Source/Testably.Abstractions.Testing/TimeSystem/IPeriodicTimerNotificationHandler.cs diff --git a/Source/Testably.Abstractions.Testing/MockTimeSystem.cs b/Source/Testably.Abstractions.Testing/MockTimeSystem.cs index d3f0d454..03b95455 100644 --- a/Source/Testably.Abstractions.Testing/MockTimeSystem.cs +++ b/Source/Testably.Abstractions.Testing/MockTimeSystem.cs @@ -96,7 +96,7 @@ public MockTimeSystem(ITimeProviderFactory timeProvider, Func -/// The callback handler for the +/// The callback handler for the . /// public interface INotificationHandler { +#if FEATURE_PERIODIC_TIMER + /// + /// Notifications for the . + /// + IPeriodicTimerNotificationHandler PeriodicTimer { get; } +#endif + /// /// Callback executed when any of the following DateTime read methods is called:
/// -
diff --git a/Source/Testably.Abstractions.Testing/TimeSystem/IPeriodicTimerNotificationHandler.cs b/Source/Testably.Abstractions.Testing/TimeSystem/IPeriodicTimerNotificationHandler.cs new file mode 100644 index 00000000..9d9e8be2 --- /dev/null +++ b/Source/Testably.Abstractions.Testing/TimeSystem/IPeriodicTimerNotificationHandler.cs @@ -0,0 +1,27 @@ +#if FEATURE_PERIODIC_TIMER +using System; +using Testably.Abstractions.TimeSystem; + +namespace Testably.Abstractions.Testing.TimeSystem; + +/// +/// The callback handler for the of the . +/// +public interface IPeriodicTimerNotificationHandler +{ + /// + /// Callback executed when any periodic timer is waiting for the next tick. + /// + /// + /// (optional) The callback to execute when the periodic timer is waiting for the next tick. The parameter is the periodic timer which is waiting for the next tick. + /// + /// + /// (optional) A predicate used to filter which callbacks should be notified.
+ /// If set to (default value) all callbacks are notified. + /// + /// A to un-register the callback on dispose. + IAwaitableCallback WaitingForNextTick( + Action? callback = null, + Func? predicate = null); +} +#endif diff --git a/Source/Testably.Abstractions.Testing/TimeSystem/NotificationHandler.cs b/Source/Testably.Abstractions.Testing/TimeSystem/NotificationHandler.cs index f6dc985e..3731fd34 100644 --- a/Source/Testably.Abstractions.Testing/TimeSystem/NotificationHandler.cs +++ b/Source/Testably.Abstractions.Testing/TimeSystem/NotificationHandler.cs @@ -1,12 +1,25 @@ using System; +#if FEATURE_PERIODIC_TIMER +using Testably.Abstractions.TimeSystem; +#endif namespace Testably.Abstractions.Testing.TimeSystem; -internal sealed class NotificationHandler(MockTimeSystem mockTimeSystem) : INotificationHandler +internal sealed class NotificationHandler(MockTimeSystem mockTimeSystem) +#if FEATURE_PERIODIC_TIMER + : INotificationHandler, IPeriodicTimerNotificationHandler +#else + : INotificationHandler +#endif { private readonly Notification.INotificationFactory _dateTimeReadCallbacks = Notification.CreateFactory(); +#if FEATURE_PERIODIC_TIMER + private readonly Notification.INotificationFactory + _periodicTimerWaitingForNextTickCallbacks = Notification.CreateFactory(); +#endif + private readonly Notification.INotificationFactory _taskDelayCallbacks = Notification.CreateFactory(); @@ -18,6 +31,11 @@ private readonly Notification.INotificationFactory #region INotificationHandler Members +#if FEATURE_PERIODIC_TIMER + /// + public IPeriodicTimerNotificationHandler PeriodicTimer => this; +#endif + /// public IAwaitableCallback DateTimeRead( Action? callback = null, @@ -45,9 +63,31 @@ public IAwaitableCallback TimeChanged( #endregion + #region IPeriodicTimerNotificationHandler Members + +#if FEATURE_PERIODIC_TIMER + + #region IPeriodicTimerNotificationHandler Members + + /// + public IAwaitableCallback WaitingForNextTick( + Action? callback = null, Func? predicate = null) + => _periodicTimerWaitingForNextTickCallbacks.RegisterCallback(callback, predicate); + + #endregion + +#endif + + #endregion + public void InvokeDateTimeReadCallbacks(DateTime now) => _dateTimeReadCallbacks.InvokeCallbacks(now); +#if FEATURE_PERIODIC_TIMER + public void InvokePeriodicTimerWaitingForNextTick(IPeriodicTimer timer) + => _periodicTimerWaitingForNextTickCallbacks.InvokeCallbacks(timer); +#endif + public void InvokeTaskDelayCallbacks(TimeSpan delay) => _taskDelayCallbacks.InvokeCallbacks(delay); diff --git a/Source/Testably.Abstractions.Testing/TimeSystem/PeriodicTimerFactoryMock.cs b/Source/Testably.Abstractions.Testing/TimeSystem/PeriodicTimerFactoryMock.cs index bc7ac412..794bf13f 100644 --- a/Source/Testably.Abstractions.Testing/TimeSystem/PeriodicTimerFactoryMock.cs +++ b/Source/Testably.Abstractions.Testing/TimeSystem/PeriodicTimerFactoryMock.cs @@ -9,11 +9,14 @@ namespace Testably.Abstractions.Testing.TimeSystem; internal sealed class PeriodicTimerFactoryMock : IPeriodicTimerFactory { private readonly MockTimeSystem _mockTimeSystem; + private readonly NotificationHandler _callbackHandler; private readonly bool _autoAdvance; - internal PeriodicTimerFactoryMock(MockTimeSystem timeSystem, bool autoAdvance) + internal PeriodicTimerFactoryMock(MockTimeSystem timeSystem, + NotificationHandler callbackHandler, bool autoAdvance) { _mockTimeSystem = timeSystem; + _callbackHandler = callbackHandler; _autoAdvance = autoAdvance; } @@ -24,7 +27,7 @@ internal PeriodicTimerFactoryMock(MockTimeSystem timeSystem, bool autoAdvance) /// public IPeriodicTimer New(TimeSpan period) - => new PeriodicTimerMock(_mockTimeSystem, period, _autoAdvance); + => new PeriodicTimerMock(_mockTimeSystem, _callbackHandler, period, _autoAdvance); /// public IPeriodicTimer Wrap(PeriodicTimer timer) diff --git a/Source/Testably.Abstractions.Testing/TimeSystem/PeriodicTimerMock.cs b/Source/Testably.Abstractions.Testing/TimeSystem/PeriodicTimerMock.cs index 047077ef..c347056d 100644 --- a/Source/Testably.Abstractions.Testing/TimeSystem/PeriodicTimerMock.cs +++ b/Source/Testably.Abstractions.Testing/TimeSystem/PeriodicTimerMock.cs @@ -13,13 +13,18 @@ internal sealed class PeriodicTimerMock : IPeriodicTimer private bool _isDisposed; private long _lastTime; private readonly MockTimeSystem _timeSystem; + private readonly NotificationHandler _callbackHandler; - internal PeriodicTimerMock(MockTimeSystem timeSystem, - TimeSpan period, bool autoAdvance) + internal PeriodicTimerMock( + MockTimeSystem timeSystem, + NotificationHandler callbackHandler, + TimeSpan period, + bool autoAdvance) { ThrowIfPeriodIsInvalid(period, nameof(period)); _timeSystem = timeSystem; + _callbackHandler = callbackHandler; _autoAdvance = autoAdvance; _lastTime = _timeSystem.TimeProvider.ElapsedTicks; Period = period; @@ -58,6 +63,7 @@ public void Dispose() return false; } + _callbackHandler.InvokePeriodicTimerWaitingForNextTick(this); long now = _timeSystem.TimeProvider.ElapsedTicks; long nextTime = _lastTime + Period.Ticks; if (nextTime > now) diff --git a/Tests/Testably.Abstractions.Testing.Tests/TimeSystem/NotificationHandlerTests.cs b/Tests/Testably.Abstractions.Testing.Tests/TimeSystem/NotificationHandlerTests.cs index 78c7842f..80ab1642 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/TimeSystem/NotificationHandlerTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/TimeSystem/NotificationHandlerTests.cs @@ -1,5 +1,6 @@ using System.Threading; using Testably.Abstractions.Testing.Tests.TestHelpers; +using Testably.Abstractions.TimeSystem; namespace Testably.Abstractions.Testing.Tests.TimeSystem; @@ -87,6 +88,129 @@ public async Task OnDateTimeRead_UtcNow_ShouldExecuteCallbackWithCorrectParamete await That(receivedTime).IsEqualTo(expectedTime); } +#if FEATURE_PERIODIC_TIMER + [Test] + public async Task OnPeriodicTimerWaitingForNextTick_DisposedCallback_ShouldNotBeCalled() + { + MockTimeSystem timeSystem = new(); + IPeriodicTimer? receivedTimer = null; + using IPeriodicTimer periodicTimer = + timeSystem.PeriodicTimer.New(TimeSpan.FromSeconds(1)); + IDisposable disposable = + timeSystem.On.PeriodicTimer.WaitingForNextTick(t => receivedTimer = t); + + disposable.Dispose(); + await periodicTimer.WaitForNextTickAsync(); + + await That(receivedTimer).IsNull(); + } +#endif + +#if FEATURE_PERIODIC_TIMER + [Test] + public async Task + OnPeriodicTimerWaitingForNextTick_MultipleCallbacks_DisposeOne_ShouldCallOtherCallbacks() + { + MockTimeSystem timeSystem = new(); + IPeriodicTimer? receivedTimer1 = null; + IPeriodicTimer? receivedTimer2 = null; + using IPeriodicTimer periodicTimer = + timeSystem.PeriodicTimer.New(TimeSpan.FromSeconds(1)); + + using (timeSystem.On.PeriodicTimer.WaitingForNextTick(t => receivedTimer1 = t)) + { + timeSystem.On.PeriodicTimer.WaitingForNextTick(t => receivedTimer2 = t).Dispose(); + await periodicTimer.WaitForNextTickAsync(); + } + + await That(receivedTimer1).IsEqualTo(periodicTimer); + await That(receivedTimer2).IsNull(); + } +#endif + +#if FEATURE_PERIODIC_TIMER + [Test] + public async Task OnPeriodicTimerWaitingForNextTick_MultipleCallbacks_ShouldAllBeCalled() + { + MockTimeSystem timeSystem = new(); + IPeriodicTimer? receivedTimer1 = null; + IPeriodicTimer? receivedTimer2 = null; + using IPeriodicTimer periodicTimer = + timeSystem.PeriodicTimer.New(TimeSpan.FromSeconds(1)); + + using (timeSystem.On.PeriodicTimer.WaitingForNextTick(t => receivedTimer1 = t)) + { + using (timeSystem.On.PeriodicTimer.WaitingForNextTick(t => receivedTimer2 = t)) + { + await periodicTimer.WaitForNextTickAsync(); + } + } + + await That(receivedTimer1).IsEqualTo(periodicTimer); + await That(receivedTimer2).IsEqualTo(periodicTimer); + } +#endif + +#if FEATURE_PERIODIC_TIMER + [Test] + public async Task + OnPeriodicTimerWaitingForNextTick_ShouldBeCalledOnEachWaitForNextTickAsync() + { + MockTimeSystem timeSystem = new(); + int callbackCount = 0; + using IPeriodicTimer periodicTimer = + timeSystem.PeriodicTimer.New(TimeSpan.FromSeconds(1)); + + using (timeSystem.On.PeriodicTimer.WaitingForNextTick(_ => callbackCount++)) + { + await periodicTimer.WaitForNextTickAsync(); + await periodicTimer.WaitForNextTickAsync(); + await periodicTimer.WaitForNextTickAsync(); + } + + await That(callbackCount).IsEqualTo(3); + } +#endif + +#if FEATURE_PERIODIC_TIMER + [Test] + public async Task OnPeriodicTimerWaitingForNextTick_ShouldExecuteCallbackWithCorrectParameter() + { + MockTimeSystem timeSystem = new(); + IPeriodicTimer? receivedTimer = null; + using IPeriodicTimer periodicTimer = + timeSystem.PeriodicTimer.New(TimeSpan.FromSeconds(1)); + + using (timeSystem.On.PeriodicTimer.WaitingForNextTick(t => receivedTimer = t)) + { + await periodicTimer.WaitForNextTickAsync(); + } + + await That(receivedTimer).IsEqualTo(periodicTimer); + } +#endif + +#if FEATURE_PERIODIC_TIMER + [Test] + public async Task OnPeriodicTimerWaitingForNextTick_WithPredicate_ShouldFilterCallbacks() + { + MockTimeSystem timeSystem = new(); + int callbackCount = 0; + using IPeriodicTimer periodicTimer1 = + timeSystem.PeriodicTimer.New(TimeSpan.FromSeconds(1)); + using IPeriodicTimer periodicTimer2 = + timeSystem.PeriodicTimer.New(TimeSpan.FromSeconds(2)); + + using IAwaitableCallback _ = timeSystem.On.PeriodicTimer.WaitingForNextTick( + callback: _ => callbackCount++, + predicate: p => p == periodicTimer1); + await periodicTimer1.WaitForNextTickAsync(); + await That(callbackCount).IsEqualTo(1); + await periodicTimer2.WaitForNextTickAsync(); + await That(callbackCount).IsEqualTo(1); + } +#endif + [Test] public async Task OnTaskDelay_DisposedCallback_ShouldNotBeCalled() { diff --git a/Tests/Testably.Abstractions.Testing.Tests/TimeSystem/PeriodicTimerMockTests.cs b/Tests/Testably.Abstractions.Testing.Tests/TimeSystem/PeriodicTimerMockTests.cs index 726724c7..551efaba 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/TimeSystem/PeriodicTimerMockTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/TimeSystem/PeriodicTimerMockTests.cs @@ -72,5 +72,111 @@ public async Task ShouldNotBeAffectedByTimeChange() cts.Cancel(); await timerTask; } + + [Test] + public async Task WaitingForNextTick_AutoAdvance_ShouldFireCallback() + { + MockTimeSystem timeSystem = new(); + IPeriodicTimer? receivedTimer = null; + using IPeriodicTimer periodicTimer = timeSystem.PeriodicTimer.New(1.Seconds()); + + using (timeSystem.On.PeriodicTimer.WaitingForNextTick(t => receivedTimer = t)) + { + await periodicTimer.WaitForNextTickAsync(); + } + + await That(receivedTimer).IsEqualTo(periodicTimer); + } + + [Test] + public async Task WaitingForNextTick_DisableAutoAdvance_ShouldFireCallbackBeforeWaiting() + { + MockTimeSystem timeSystem = new(o => o.DisableAutoAdvance()); + using CancellationTokenSource cts = CancellationTokenSource + .CreateLinkedTokenSource(TestContext.Current!.Execution.CancellationToken); + cts.CancelAfter(30.Seconds()); + CancellationToken token = cts.Token; + + int callbackCount = 0; + using IPeriodicTimer periodicTimer = timeSystem.PeriodicTimer.New(1.Seconds()); + using SemaphoreSlim callbackFired = new(0); + + using (timeSystem.On.PeriodicTimer.WaitingForNextTick(_ => + { + callbackCount++; + // ReSharper disable once AccessToDisposedClosure + callbackFired.Release(); + })) + { + Task tickTask = Task.Run(async () => + { + try + { + // ReSharper disable once AccessToDisposedClosure + await periodicTimer.WaitForNextTickAsync(token); + } + catch (OperationCanceledException) + { + // Ignore cancellation + } + }, token); + + await callbackFired.WaitAsync(token); + await That(callbackCount).IsEqualTo(1); + + timeSystem.TimeProvider.AdvanceBy(1.Seconds()); + await tickTask; + } + } + + [Test] + public async Task WaitingForNextTick_ShouldFireCallbackForEachTick() + { + MockTimeSystem timeSystem = new(); + int callbackCount = 0; + using IPeriodicTimer periodicTimer = timeSystem.PeriodicTimer.New(1.Seconds()); + + using (timeSystem.On.PeriodicTimer.WaitingForNextTick(_ => callbackCount++)) + { + await periodicTimer.WaitForNextTickAsync(); + await periodicTimer.WaitForNextTickAsync(); + await periodicTimer.WaitForNextTickAsync(); + } + + await That(callbackCount).IsEqualTo(3); + } + + [Test] + public async Task WaitingForNextTick_ShouldNotFireCallbackAfterDispose() + { + MockTimeSystem timeSystem = new(); + IPeriodicTimer? receivedTimer = null; + using IPeriodicTimer periodicTimer = timeSystem.PeriodicTimer.New(1.Seconds()); + IDisposable disposable = + timeSystem.On.PeriodicTimer.WaitingForNextTick(t => receivedTimer = t); + + disposable.Dispose(); + await periodicTimer.WaitForNextTickAsync(); + + await That(receivedTimer).IsNull(); + } + + [Test] + public async Task WaitingForNextTick_WhenTimerIsDisposed_ShouldNotFireCallback() + { + MockTimeSystem timeSystem = new(); + IPeriodicTimer? receivedTimer = null; + IPeriodicTimer periodicTimer = timeSystem.PeriodicTimer.New(1.Seconds()); + periodicTimer.Dispose(); + + using (timeSystem.On.PeriodicTimer.WaitingForNextTick(t => receivedTimer = t)) + { + #pragma warning disable MA0040 // Use an overload with a CancellationToken + await periodicTimer.WaitForNextTickAsync(); + #pragma warning restore MA0040 + } + + await That(receivedTimer).IsNull(); + } } #endif From 2496ee79d0cfcacb5527e0f4c7db986c3e788186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Thu, 9 Apr 2026 21:28:48 +0200 Subject: [PATCH 2/3] Fix review issues --- .../TimeSystem/IPeriodicTimerNotificationHandler.cs | 2 +- .../TimeSystem/NotificationHandler.cs | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Source/Testably.Abstractions.Testing/TimeSystem/IPeriodicTimerNotificationHandler.cs b/Source/Testably.Abstractions.Testing/TimeSystem/IPeriodicTimerNotificationHandler.cs index 9d9e8be2..7166d183 100644 --- a/Source/Testably.Abstractions.Testing/TimeSystem/IPeriodicTimerNotificationHandler.cs +++ b/Source/Testably.Abstractions.Testing/TimeSystem/IPeriodicTimerNotificationHandler.cs @@ -19,7 +19,7 @@ public interface IPeriodicTimerNotificationHandler /// (optional) A predicate used to filter which callbacks should be notified.
/// If set to (default value) all callbacks are notified. /// - /// A to un-register the callback on dispose. + /// A to un-register the callback on dispose. IAwaitableCallback WaitingForNextTick( Action? callback = null, Func? predicate = null); diff --git a/Source/Testably.Abstractions.Testing/TimeSystem/NotificationHandler.cs b/Source/Testably.Abstractions.Testing/TimeSystem/NotificationHandler.cs index 3731fd34..16e788bf 100644 --- a/Source/Testably.Abstractions.Testing/TimeSystem/NotificationHandler.cs +++ b/Source/Testably.Abstractions.Testing/TimeSystem/NotificationHandler.cs @@ -63,8 +63,6 @@ public IAwaitableCallback TimeChanged( #endregion - #region IPeriodicTimerNotificationHandler Members - #if FEATURE_PERIODIC_TIMER #region IPeriodicTimerNotificationHandler Members @@ -78,8 +76,6 @@ public IAwaitableCallback WaitingForNextTick( #endif - #endregion - public void InvokeDateTimeReadCallbacks(DateTime now) => _dateTimeReadCallbacks.InvokeCallbacks(now); From 7718457029d76f42391906db9edd146ba9cbfaa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Thu, 9 Apr 2026 21:29:37 +0200 Subject: [PATCH 3/3] Accept API changes --- .../Expected/Testably.Abstractions.Testing_net10.0.txt | 5 +++++ .../Expected/Testably.Abstractions.Testing_net8.0.txt | 5 +++++ .../Expected/Testably.Abstractions.Testing_net9.0.txt | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net10.0.txt b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net10.0.txt index 8bb8efd3..ca8846e7 100644 --- a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net10.0.txt +++ b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net10.0.txt @@ -437,11 +437,16 @@ namespace Testably.Abstractions.Testing.TimeSystem { public interface INotificationHandler { + Testably.Abstractions.Testing.TimeSystem.IPeriodicTimerNotificationHandler PeriodicTimer { get; } Testably.Abstractions.Testing.IAwaitableCallback DateTimeRead(System.Action? callback = null, System.Func? predicate = null); Testably.Abstractions.Testing.IAwaitableCallback TaskDelay(System.Action? callback = null, System.Func? predicate = null); Testably.Abstractions.Testing.IAwaitableCallback ThreadSleep(System.Action? callback = null, System.Func? predicate = null); Testably.Abstractions.Testing.IAwaitableCallback TimeChanged(System.Action? callback = null, System.Func? predicate = null); } + public interface IPeriodicTimerNotificationHandler + { + Testably.Abstractions.Testing.IAwaitableCallback WaitingForNextTick(System.Action? callback = null, System.Func? predicate = null); + } public interface ITimeProvider { long ElapsedTicks { get; } diff --git a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net8.0.txt b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net8.0.txt index 072ad37d..5434f86c 100644 --- a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net8.0.txt +++ b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net8.0.txt @@ -437,11 +437,16 @@ namespace Testably.Abstractions.Testing.TimeSystem { public interface INotificationHandler { + Testably.Abstractions.Testing.TimeSystem.IPeriodicTimerNotificationHandler PeriodicTimer { get; } Testably.Abstractions.Testing.IAwaitableCallback DateTimeRead(System.Action? callback = null, System.Func? predicate = null); Testably.Abstractions.Testing.IAwaitableCallback TaskDelay(System.Action? callback = null, System.Func? predicate = null); Testably.Abstractions.Testing.IAwaitableCallback ThreadSleep(System.Action? callback = null, System.Func? predicate = null); Testably.Abstractions.Testing.IAwaitableCallback TimeChanged(System.Action? callback = null, System.Func? predicate = null); } + public interface IPeriodicTimerNotificationHandler + { + Testably.Abstractions.Testing.IAwaitableCallback WaitingForNextTick(System.Action? callback = null, System.Func? predicate = null); + } public interface ITimeProvider { long ElapsedTicks { get; } diff --git a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net9.0.txt b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net9.0.txt index 26650fd1..66d22786 100644 --- a/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net9.0.txt +++ b/Tests/Api/Testably.Abstractions.Api.Tests/Expected/Testably.Abstractions.Testing_net9.0.txt @@ -437,11 +437,16 @@ namespace Testably.Abstractions.Testing.TimeSystem { public interface INotificationHandler { + Testably.Abstractions.Testing.TimeSystem.IPeriodicTimerNotificationHandler PeriodicTimer { get; } Testably.Abstractions.Testing.IAwaitableCallback DateTimeRead(System.Action? callback = null, System.Func? predicate = null); Testably.Abstractions.Testing.IAwaitableCallback TaskDelay(System.Action? callback = null, System.Func? predicate = null); Testably.Abstractions.Testing.IAwaitableCallback ThreadSleep(System.Action? callback = null, System.Func? predicate = null); Testably.Abstractions.Testing.IAwaitableCallback TimeChanged(System.Action? callback = null, System.Func? predicate = null); } + public interface IPeriodicTimerNotificationHandler + { + Testably.Abstractions.Testing.IAwaitableCallback WaitingForNextTick(System.Action? callback = null, System.Func? predicate = null); + } public interface ITimeProvider { long ElapsedTicks { get; }