using Bunit; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using NSubstitute; using System.Security.Claims; using ZB.MOM.WW.ScadaBridge.CentralUI.Auth; using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Monitoring; using ZB.MOM.WW.ScadaBridge.Commons.Entities.Sites; using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories; using ZB.MOM.WW.ScadaBridge.Commons.Messages.RemoteQuery; using ZB.MOM.WW.ScadaBridge.Communication; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Monitoring; /// Review 2026-10-21 07/M-3 (retained-row cap) and the lane D keyword-window hint. public class EventLogsPageTests : BunitContext { private static EventLogEntry Entry(int n) => new($"id-{n}", DateTimeOffset.UnixEpoch.AddSeconds(n), "T", "Info", null, "src", "m", null); private static List Page(int from, int count) => Enumerable.Range(from, count).Select(Entry).ToList(); /// Rows beyond the cap are dropped from the head and their expansion state cleared. [Fact] public void AppendCapped_DropsOldestRowsBeyondCap_AndUnexpandsThem() { var entries = Page(0, 8); var expanded = new HashSet { "id-0", "id-7" }; var dropped = EventLogs.AppendCapped(entries, Page(8, 4), expanded, cap: 10); Assert.Equal(2, dropped); Assert.Equal(10, entries.Count); Assert.Equal("id-2", entries[0].Id); Assert.Equal("id-11", entries[^1].Id); Assert.DoesNotContain("id-0", expanded); Assert.Contains("id-7", expanded); } /// Under the cap nothing is dropped. [Fact] public void AppendCapped_UnderCap_KeepsEverything() { var entries = Page(0, 3); Assert.Equal(0, EventLogs.AppendCapped(entries, Page(3, 3), new HashSet(), cap: 10)); Assert.Equal(6, entries.Count); } /// The page tells operators the keyword search window is bounded. [Fact] public void Page_ShowsKeywordWindowHint() { var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, "u") }, "T"); var auth = Substitute.For(); auth.GetAuthenticationStateAsync().Returns(new AuthenticationState(new ClaimsPrincipal(identity))); Services.AddSingleton(auth); Services.AddScoped(_ => new SiteScopeService(auth)); var siteRepo = Substitute.For(); siteRepo.GetAllSitesAsync().Returns(new List()); Services.AddSingleton(siteRepo); Services.AddSingleton(new CommunicationService( Options.Create(new CommunicationOptions()), NullLogger.Instance)); var cut = Render(); Assert.Contains("at most the last 7 days", cut.Markup); } }