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("