From bbfc1b327819ac54cf06c1d45aab4733650d6a08 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Fri, 10 Jul 2026 12:12:17 -0400 Subject: [PATCH] feat(kpihistory): add 30d/90d trend windows to Audit/SiteCalls/Notifications/Health (plan #22 T7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds 30d (720h) and 90d (2160h) toggle buttons alongside the existing 24h/7d controls on all four KPI trend surfaces. No fetch-logic changes: the setters already recompute fromUtc and re-fetch, and the query service (T5) transparently routes windows > RollupThresholdHours to hourly rollups — so these windows are what actually exercise the rollup path. bUnit tests extend the Audit and SiteCalls trend harnesses to cover the new buttons. Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj --- .../Components/Pages/Audit/AuditLogPage.razor | 10 +++++ .../Components/Pages/Monitoring/Health.razor | 6 +++ .../Notifications/NotificationKpis.razor | 6 +++ .../Pages/SiteCalls/SiteCallsReport.razor | 6 +++ .../Pages/AuditLogPageTrendTests.cs | 38 +++++++++++++++++++ .../Pages/SiteCallsReportPageTests.cs | 25 ++++++++++++ 6 files changed, 91 insertions(+) diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor index 1e492af4..a09533a5 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Audit/AuditLogPage.razor @@ -39,6 +39,16 @@ @onclick="() => SetWindowAsync(168)" disabled="@_trendsLoading"> 7d + + } diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor index 4a0d273a..a26d8442 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Monitoring/Health.razor @@ -109,6 +109,12 @@ + +
diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor index 6c06347d..93df1e40 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationKpis.razor @@ -172,6 +172,12 @@ + +
diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor index 02abf21f..0a9c640d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor @@ -248,6 +248,12 @@ + +
} diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/AuditLogPageTrendTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/AuditLogPageTrendTests.cs index 76fbbfb1..e0971345 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/AuditLogPageTrendTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/AuditLogPageTrendTests.cs @@ -117,6 +117,44 @@ public class AuditLogPageTrendTests : BunitContext Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()); } + [Fact] + public void TrendsPanel_LongRangeWindows_RenderAndRefetchWithMatchingSpan() + { + // The 30d (720h) / 90d (2160h) buttons added for the hourly-rollup path + // (plan #22 T7) must render alongside 24h/7d and, when clicked, re-fetch + // every series over the corresponding range — the query service then + // transparently routes the long windows to hourly rollups. + var ranges = new List<(DateTime From, DateTime To)>(); + var kpi = Substitute.For(); + kpi.GetSeriesAsync( + Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), + Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + .Returns(ci => + { + ranges.Add((ci.ArgAt(4), ci.ArgAt(5))); + return Task.FromResult(ThreePoints()); + }); + + var cut = RenderAuditLogPage(kpi); + + // Both new window buttons render in the toggle group. + cut.WaitForAssertion(() => + { + Assert.Contains(cut.FindAll("button"), b => b.TextContent.Trim() == "30d"); + Assert.Contains(cut.FindAll("button"), b => b.TextContent.Trim() == "90d"); + }); + + // Click 30d — every series re-fetches over a ~720h span. + cut.FindAll("button").First(b => b.TextContent.Trim() == "30d").Click(); + cut.WaitForAssertion(() => + Assert.Contains(ranges, r => Math.Abs((r.To - r.From).TotalHours - 720) < 0.5)); + + // Click 90d — every series re-fetches over a ~2160h span. + cut.FindAll("button").First(b => b.TextContent.Trim() == "90d").Click(); + cut.WaitForAssertion(() => + Assert.Contains(ranges, r => Math.Abs((r.To - r.From).TotalHours - 2160) < 0.5)); + } + [Fact] public void TrendsPanel_WhenQueryServiceThrows_PageStillRenders() { diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/SiteCallsReportPageTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/SiteCallsReportPageTests.cs index bd35a2fa..d32ebff3 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/SiteCallsReportPageTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/SiteCallsReportPageTests.cs @@ -590,6 +590,31 @@ public class SiteCallsReportPageTests : BunitContext Assert.True(_kpiHistory.ReceivedCalls().Count() > afterExpand)); } + [Fact] + public void TrendsSection_LongRangeWindows_RenderAndReloadSeries() + { + // The 30d/90d buttons (plan #22 T7) render alongside 24h/7d and clicking + // one re-loads the series — the query service then routes the long window + // to hourly rollups transparently. + var cut = Render(); + cut.WaitForState(() => cut.Markup.Contains("ERP.GetOrder")); + + cut.Find("[data-test='site-calls-trends-toggle']").Click(); + cut.WaitForAssertion(() => Assert.NotEmpty(cut.FindAll("[data-test^='kpi-trend-']"))); + + // Both long-range buttons are present in the toggle group. + Assert.Contains(cut.FindAll("button"), b => b.TextContent.Trim() == "30d"); + Assert.Contains(cut.FindAll("button"), b => b.TextContent.Trim() == "90d"); + + var afterExpand = _kpiHistory.ReceivedCalls().Count(); + + // Switch the window to 90d — the series re-load (another batch of calls). + cut.FindAll("button").First(b => b.TextContent.Trim() == "90d").Click(); + + cut.WaitForAssertion(() => + Assert.True(_kpiHistory.ReceivedCalls().Count() > afterExpand)); + } + [Fact] public void TrendsSection_WhenKpiHistoryThrows_PageStillRenders() {