using Elsa.Common; using Elsa.Common.Multitenancy; using Elsa.Scheduling.StartupTasks; using Elsa.Workflows.Runtime; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using Elsa.Workflows.Runtime.Tasks; using Microsoft.Extensions.DependencyInjection; using NSubstitute; namespace Elsa.Scheduling.UnitTests.StartupTasks; public class CreateSchedulesStartupTaskTests { private readonly StoredTrigger[] _triggers = [new() { WorkflowDefinitionId = "definition", WorkflowDefinitionVersionId = "version", ActivityId = "activity" }]; private readonly StoredBookmark[] _bookmarks = [new() { Hash = "hash", WorkflowInstanceId = "instance" }]; private readonly ITriggerStore _triggerStore = Substitute.For(); private readonly IBookmarkStore _bookmarkStore = Substitute.For(); private readonly ITriggerScheduler _triggerScheduler = Substitute.For(); private readonly IBookmarkScheduler _bookmarkScheduler = Substitute.For(); public CreateSchedulesStartupTaskTests() { _triggerStore.FindManyAsync(Arg.Any(), Arg.Any()).Returns(_triggers); _bookmarkStore.FindManyAsync(Arg.Any(), Arg.Any()).Returns(_bookmarks); } [Fact] public void Task_DependsOnPopulateRegistriesStartupTask() { var dependency = Assert.Single(typeof(CreateSchedulesStartupTask).GetCustomAttributes(typeof(TaskDependencyAttribute), false).Cast()); Assert.Equal(typeof(PopulateRegistriesStartupTask), dependency.DependencyTaskType); } [Fact] public async Task ExecuteAsync_WithoutTenantBackgroundQueue_SchedulesImmediately() { var task = new CreateSchedulesStartupTask(CreateServiceProvider()); await task.ExecuteAsync(CancellationToken.None); await _triggerScheduler.Received(1).ScheduleAsync(Arg.Is>(x => x.SequenceEqual(_triggers)), Arg.Any()); await _bookmarkScheduler.Received(1).ScheduleAsync(Arg.Is>(x => x.SequenceEqual(_bookmarks)), Arg.Any()); } [Fact] public async Task ExecuteAsync_WithTenantBackgroundQueue_EnqueuesScheduleCreation() { TenantBackgroundWorkItem? workItem = null; var workQueue = Substitute.For(); workQueue.EnqueueAsync(Arg.Do(x => workItem = x), Arg.Any()).Returns(ValueTask.CompletedTask); var serviceProvider = CreateServiceProvider(services => services.AddSingleton(workQueue)); var task = new CreateSchedulesStartupTask(serviceProvider); await task.ExecuteAsync(CancellationToken.None); await workQueue.Received(1).EnqueueAsync(Arg.Any(), Arg.Any()); await _triggerScheduler.DidNotReceive().ScheduleAsync(Arg.Any>(), Arg.Any()); Assert.NotNull(workItem); await workItem(serviceProvider, CancellationToken.None); await _triggerScheduler.Received(1).ScheduleAsync(Arg.Is>(x => x.SequenceEqual(_triggers)), Arg.Any()); await _bookmarkScheduler.Received(1).ScheduleAsync(Arg.Is>(x => x.SequenceEqual(_bookmarks)), Arg.Any()); } private ServiceProvider CreateServiceProvider(Action? configureServices = null) { var services = new ServiceCollection(); services.AddSingleton(_triggerStore); services.AddSingleton(_bookmarkStore); services.AddSingleton(_triggerScheduler); services.AddSingleton(_bookmarkScheduler); configureServices?.Invoke(services); return services.BuildServiceProvider(); } }