using Xunit; using Microsoft.Extensions.Time.Testing; using StellaOps.Policy.Engine.Ledger; using StellaOps.Policy.Engine.Orchestration; using StellaOps.Policy.Engine.Snapshots; namespace StellaOps.Policy.Engine.Tests; public sealed class SnapshotServiceTests { [Fact] public async Task CreateAsync_ProducesSnapshotFromLedger() { var clock = new FakeTimeProvider(DateTimeOffset.Parse("2025-11-24T16:00:00Z")); var jobStore = new InMemoryOrchestratorJobStore(); var resultStore = new InMemoryWorkerResultStore(jobStore); var exportStore = new InMemoryLedgerExportStore(); var ledger = new LedgerExportService(clock, jobStore, resultStore, exportStore); var snapshotStore = new InMemorySnapshotStore(); var service = new SnapshotService(clock, ledger, snapshotStore); var job = new OrchestratorJob( JobId: "job-xyz", TenantId: "acme", ContextId: "ctx", PolicyProfileHash: "hash", RequestedAt: clock.GetUtcNow(), Priority: "normal", BatchItems: new[] { new OrchestratorJobItem("pkg:a", "ADV-1") }, Callbacks: null, TraceRef: "trace", Status: "completed", DeterminismHash: "hash", CompletedAt: clock.GetUtcNow(), ResultHash: "res"); await jobStore.SaveAsync(job); await resultStore.SaveAsync(new WorkerRunResult( job.JobId, "worker", clock.GetUtcNow(), clock.GetUtcNow(), new[] { new WorkerResultItem("pkg:a", "ADV-1", "violation", "trace-ref") }, "hash")); await ledger.BuildAsync(new LedgerExportRequest("acme")); var snapshot = await service.CreateAsync(new SnapshotRequest("acme", "overlay-1")); Assert.Equal("acme", snapshot.TenantId); Assert.Equal("overlay-1", snapshot.OverlayHash); Assert.Single(snapshot.Records); Assert.Contains("violation", snapshot.StatusCounts.Keys); var list = await service.ListAsync("acme"); Assert.Single(list.Items); } }