using Microsoft.EntityFrameworkCore; using ScadaLink.Commons.Entities.Notifications; using ScadaLink.Commons.Types.Enums; using ScadaLink.ConfigurationDatabase; using ScadaLink.ConfigurationDatabase.Repositories; namespace ScadaLink.ConfigurationDatabase.Tests; // Coverage for per-site KPI aggregation in the Notification Outbox repository // (Task 2 of the notifications-nav-group feature). public class NotificationOutboxRepositoryPerSiteKpiTests { private static ScadaLinkDbContext NewContext() => SqliteTestHelper.CreateInMemoryContext(); private static Notification NewNotification( string sourceSiteId, NotificationStatus status, DateTimeOffset createdAt, DateTimeOffset? deliveredAt = null) { return new Notification( Guid.NewGuid().ToString(), NotificationType.Email, "Ops List", "Subject", "Body", sourceSiteId) { Status = status, CreatedAt = createdAt, DeliveredAt = deliveredAt, }; } [Fact] public async Task ComputePerSiteKpisAsync_AggregatesMetricsPerSite() { await using var ctx = NewContext(); var now = DateTimeOffset.UtcNow; // plant-a: 1 pending (stuck, created 20m ago), 1 parked ctx.Notifications.Add(NewNotification("plant-a", NotificationStatus.Pending, createdAt: now.AddMinutes(-20))); ctx.Notifications.Add(NewNotification("plant-a", NotificationStatus.Parked, createdAt: now.AddMinutes(-5))); // plant-b: 1 delivered in-window, 1 pending (fresh) ctx.Notifications.Add(NewNotification("plant-b", NotificationStatus.Delivered, createdAt: now.AddHours(-2), deliveredAt: now.AddMinutes(-2))); ctx.Notifications.Add(NewNotification("plant-b", NotificationStatus.Pending, createdAt: now.AddMinutes(-1))); await ctx.SaveChangesAsync(); var repo = new NotificationOutboxRepository(ctx); var result = await repo.ComputePerSiteKpisAsync( stuckCutoff: now.AddMinutes(-10), deliveredSince: now.AddMinutes(-30)); var a = result.Single(s => s.SourceSiteId == "plant-a"); Assert.Equal(1, a.QueueDepth); Assert.Equal(1, a.StuckCount); Assert.Equal(1, a.ParkedCount); Assert.Equal(0, a.DeliveredLastInterval); Assert.NotNull(a.OldestPendingAge); var b = result.Single(s => s.SourceSiteId == "plant-b"); Assert.Equal(1, b.QueueDepth); Assert.Equal(0, b.StuckCount); Assert.Equal(1, b.DeliveredLastInterval); } [Fact] public async Task ComputePerSiteKpisAsync_ReturnsEmpty_WhenNoNotifications() { await using var ctx = NewContext(); var repo = new NotificationOutboxRepository(ctx); var result = await repo.ComputePerSiteKpisAsync( DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddMinutes(-30)); Assert.Empty(result); } }