using KArtSell.BuildingBlocks.Time; using KArtSell.BuildingBlocks.Versioning; using KArtSell.Modules.ModelOperations.Application; namespace KArtSell.ModelOperations.UnitTests; public sealed class ModelOperationRequestServiceTests { [Fact] public async Task Persists_the_scheduled_occurrence_and_catch_up_provenance() { var scheduledFor = new DateTimeOffset(2026, 8, 9, 1, 0, 0, TimeSpan.Zero); var context = new ApprovedModelContext( "GLOBAL", new VersionSet("dataset", "data-hash", "model", "config", "code-sha", "contract"), "APPROVED", scheduledFor.AddDays(-1)); var repository = new CapturingRequestRepository(); var service = new ModelOperationRequestService( new FixedContextReader(context), repository, new FixedClock(scheduledFor.AddHours(2))); var request = await service.RequestAsync( Guid.NewGuid(), "J31", "GLOBAL", "EVALUATION_ONLY", "J31:GLOBAL:1:20260809010000Z", scheduledFor, "ALL_WITH_LIMIT", 2, "correlation", CancellationToken.None); Assert.NotNull(request); Assert.Same(request, repository.Request); Assert.Equal(scheduledFor, request.ScheduledFor); Assert.Equal("ALL_WITH_LIMIT", request.CatchUpPolicy); Assert.Equal(2, request.MaxCatchUp); } private sealed class FixedContextReader(ApprovedModelContext context) : IApprovedModelContextReader { public Task ReadAsync(string scopeKey, DateTimeOffset asOf, CancellationToken cancellationToken) => Task.FromResult(context); } private sealed class CapturingRequestRepository : IModelOperationRequestRepository { public ModelOperationRequest? Request { get; private set; } public Task AddAsync(ModelOperationRequest request, CancellationToken cancellationToken) { Request = request; return Task.FromResult(true); } } private sealed class FixedClock(DateTimeOffset utcNow) : IClock { public DateTimeOffset UtcNow => utcNow; } }