feat(centralui): DateTimeRangeFilter reusable from/to input component (T35c)

This commit is contained in:
Joseph Doherty
2026-06-18 19:39:05 -04:00
parent 7b41c2c202
commit 9ee21205d6
2 changed files with 144 additions and 0 deletions
@@ -0,0 +1,87 @@
using Bunit;
using Microsoft.AspNetCore.Components;
using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared;
/// <summary>
/// Component tests for <see cref="DateTimeRangeFilter"/> — the reusable from/to
/// datetime-local input pair. The component is INPUT-ONLY: it emits raw
/// DateTime? (Unspecified kind); UTC conversion is the page's responsibility.
/// </summary>
public class DateTimeRangeFilterTests : BunitContext
{
[Fact]
public void Renders_TwoInputs_WithPrefixedIdsAndTestHooks()
{
var cut = Render<DateTimeRangeFilter>(ps => ps
.Add(p => p.IdPrefix, "sc"));
var fromInput = cut.Find("[data-test='sc-from']");
var toInput = cut.Find("[data-test='sc-to']");
Assert.Equal("datetime-local", fromInput.GetAttribute("type"));
Assert.Equal("datetime-local", toInput.GetAttribute("type"));
Assert.Equal("sc-from", fromInput.GetAttribute("id"));
Assert.Equal("sc-to", toInput.GetAttribute("id"));
}
[Fact]
public void RendersLabels()
{
var cut = Render<DateTimeRangeFilter>(ps => ps
.Add(p => p.FromLabel, "Start")
.Add(p => p.ToLabel, "End"));
cut.Find("label[for='dtr-from']"); // default IdPrefix = "dtr"
cut.Find("label[for='dtr-to']");
Assert.Contains("Start", cut.Markup);
Assert.Contains("End", cut.Markup);
}
[Fact]
public void SettingFromInput_InvokesFromChanged_WithParsedValue()
{
DateTime? captured = default;
var cut = Render<DateTimeRangeFilter>(ps => ps
.Add(p => p.IdPrefix, "sc")
.Add(p => p.FromChanged,
EventCallback.Factory.Create<DateTime?>(this, v => captured = v)));
cut.Find("[data-test='sc-from']").Change("2026-06-01T08:30");
Assert.NotNull(captured);
Assert.Equal(2026, captured!.Value.Year);
Assert.Equal(6, captured.Value.Month);
Assert.Equal(1, captured.Value.Day);
Assert.Equal(8, captured.Value.Hour);
Assert.Equal(30, captured.Value.Minute);
}
[Fact]
public void ClearingFromInput_InvokesFromChanged_WithNull()
{
DateTime? captured = new DateTime(2026, 1, 1);
var cut = Render<DateTimeRangeFilter>(ps => ps
.Add(p => p.IdPrefix, "sc")
.Add(p => p.From, new DateTime(2026, 1, 1))
.Add(p => p.FromChanged,
EventCallback.Factory.Create<DateTime?>(this, v => captured = v)));
cut.Find("[data-test='sc-from']").Change("");
Assert.Null(captured);
}
[Fact]
public void InitialValue_RendersInInput()
{
var initial = new DateTime(2025, 12, 31, 23, 59, 0);
var cut = Render<DateTimeRangeFilter>(ps => ps
.Add(p => p.From, initial));
var value = cut.Find("[data-test='dtr-from']").GetAttribute("value");
Assert.Equal("2025-12-31T23:59", value);
}
}