using Elsa.Common;
using Elsa.Mediator.Contracts;
using Elsa.Scheduling.Options;
using Elsa.Scheduling.ScheduledTasks;
using Elsa.Scheduling.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NSubstitute;
using OptionsFactory = Microsoft.Extensions.Options.Options;
namespace Elsa.Scheduling.UnitTests.ScheduledTasks;
///
/// Tests for ScheduledSpecificInstantTask to ensure specific instant tasks handle edge cases correctly.
///
public class ScheduledSpecificInstantTaskTests : IDisposable
{
private static readonly DateTimeOffset DefaultNow = new(2025, 11, 06, 22, 50, 00, 0, TimeSpan.Zero);
private readonly ServiceProvider _serviceProvider;
private readonly ISystemClock _systemClock;
private readonly ILogger _logger;
private readonly PastDueScheduleStaggerer _pastDueScheduleStaggerer = new(OptionsFactory.Create(new SchedulingOptions
{
MinimumPastDueScheduleDelay = TimeSpan.FromMilliseconds(10),
PastDueScheduleStaggerInterval = TimeSpan.FromMilliseconds(25),
PastDueScheduleStaggerWindow = TimeSpan.FromMilliseconds(100)
}));
private readonly List _tasksToDispose = new();
public ScheduledSpecificInstantTaskTests()
{
var services = new ServiceCollection();
_systemClock = Substitute.For();
_logger = Substitute.For>();
services.AddSingleton(Substitute.For());
_serviceProvider = services.BuildServiceProvider();
}
private ScheduledSpecificInstantTask CreateScheduledTask(
DateTimeOffset? startAt = null,
ISystemClock? systemClock = null)
{
var task = Substitute.For();
var scheduledTask = new ScheduledSpecificInstantTask(
task,
startAt ?? DefaultNow.AddMinutes(5),
systemClock ?? _systemClock,
_serviceProvider.CreateScope().ServiceProvider.GetRequiredService(),
_logger,
_pastDueScheduleStaggerer
);
_tasksToDispose.Add(scheduledTask);
return scheduledTask;
}
private void SetupSystemClock(params DateTimeOffset[] times)
{
_systemClock.UtcNow.Returns(times[0], times.Skip(1).ToArray());
}
private void AssertNoErrorLogged()
{
_logger.DidNotReceive().Log(
LogLevel.Error,
Arg.Any(),
Arg.Any