using Bunit; using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared; using ZB.MOM.WW.ScadaBridge.Commons.Types.Kpi; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components.Shared; /// /// bUnit tests for (M6 K12) — the reusable /// dependency-free SVG trend chart. Coverage pins the three render states /// (multi-point chart, unavailable placeholder, single-sample note), the stable /// data-test slug, and the coordinate-math edge guards (all-equal /// timestamps, all-zero values) that must not divide by zero or throw. /// public class KpiTrendChartTests : BunitContext { private static readonly DateTime Base = new(2026, 6, 15, 10, 0, 0, DateTimeKind.Utc); private static IReadOnlyList ThreePoints() => new[] { new KpiSeriesPoint(Base, 1.0), new KpiSeriesPoint(Base.AddMinutes(5), 4.0), new KpiSeriesPoint(Base.AddMinutes(10), 2.0), }; [Fact] public void Available_WithThreePoints_RendersPolylineTitleAndDataTest() { var cut = Render(p => p .Add(c => c.Points, ThreePoints()) .Add(c => c.Title, "Queue Depth") .Add(c => c.IsAvailable, true)); var markup = cut.Markup; Assert.Contains("", markup); } [Fact] public void Available_WithUnit_AppendsUnitToValueLabels() { var cut = Render(p => p .Add(c => c.Points, ThreePoints()) .Add(c => c.Title, "Oldest Pending") .Add(c => c.Unit, "s") .Add(c => c.IsAvailable, true)); // Max value label is "4 s" with the unit suffix applied. Assert.Contains("max 4 s", cut.Markup); } [Fact] public void Unavailable_RendersEmDashPlaceholderAndError_NoPolyline() { var cut = Render(p => p .Add(c => c.Points, ThreePoints()) .Add(c => c.Title, "Queue Depth") .Add(c => c.IsAvailable, false) .Add(c => c.ErrorMessage, "KPI query failed")); var markup = cut.Markup; Assert.Contains("—", markup); // em dash Assert.Contains("KPI query failed", markup); Assert.DoesNotContain("(p => p .Add(c => c.Points, (IReadOnlyList?)null) .Add(c => c.Title, "Stuck Count") .Add(c => c.IsAvailable, true)); var markup = cut.Markup; Assert.Contains("—", markup); Assert.DoesNotContain("(p => p .Add(c => c.Points, new[] { new KpiSeriesPoint(Base, 7.0) }) .Add(c => c.Title, "Backlog") .Add(c => c.IsAvailable, true)); var markup = cut.Markup; Assert.Contains("Only one sample in range.", markup); Assert.DoesNotContain("(p => p .Add(c => c.Points, new[] { new KpiSeriesPoint(Base, 1.0), new KpiSeriesPoint(Base, 2.0), new KpiSeriesPoint(Base, 3.0), }) .Add(c => c.Title, "Flat Time") .Add(c => c.IsAvailable, true)); Assert.Contains("(p => p .Add(c => c.Points, new[] { new KpiSeriesPoint(Base, 0.0), new KpiSeriesPoint(Base.AddMinutes(5), 0.0), new KpiSeriesPoint(Base.AddMinutes(10), 0.0), }) .Add(c => c.Title, "Quiet") .Add(c => c.IsAvailable, true)); Assert.Contains("