Merge branch 'worktree-agent-a6cee26f4fe0abdd1' into feat/instance-picker
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
using Bunit;
|
||||
using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// bUnit tests for the <see cref="InstancePicker"/> combobox: the closed field, the
|
||||
/// panel that opens with every area collapsed, area expansion, instance selection
|
||||
/// (callback + close + field text), the disabled guard, the outside-click backdrop,
|
||||
/// parent-driven selection changes and the <c>ItemLabel</c> hook.
|
||||
/// </summary>
|
||||
public class InstancePickerTests : BunitContext
|
||||
{
|
||||
public InstancePickerTests()
|
||||
{
|
||||
JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
}
|
||||
|
||||
private static List<Area> Areas() =>
|
||||
[
|
||||
new("Line1") { Id = 1, SiteId = 1 },
|
||||
new("Cell A") { Id = 2, SiteId = 1, ParentAreaId = 1 },
|
||||
];
|
||||
|
||||
private static List<Instance> Instances() =>
|
||||
[
|
||||
new("P1") { Id = 7, SiteId = 1, AreaId = 2 },
|
||||
new("Zulu") { Id = 8, SiteId = 1 },
|
||||
];
|
||||
|
||||
private IRenderedComponent<InstancePicker> RenderPicker(
|
||||
Action<int>? onChanged = null,
|
||||
bool disabled = false,
|
||||
Func<Instance, string>? itemLabel = null,
|
||||
int selectedInstanceId = 0) =>
|
||||
Render<InstancePicker>(ps =>
|
||||
{
|
||||
ps.Add(p => p.Areas, Areas());
|
||||
ps.Add(p => p.Instances, Instances());
|
||||
ps.Add(p => p.DataTestPrefix, "t");
|
||||
ps.Add(p => p.Disabled, disabled);
|
||||
ps.Add(p => p.SelectedInstanceId, selectedInstanceId);
|
||||
if (itemLabel is not null) ps.Add(p => p.ItemLabel, itemLabel);
|
||||
if (onChanged is not null) ps.Add(p => p.SelectedInstanceIdChanged, onChanged);
|
||||
});
|
||||
|
||||
private static void Open(IRenderedComponent<InstancePicker> cut) =>
|
||||
cut.Find("[data-test='t-toggle']").Click();
|
||||
|
||||
private static void ClickRow(IRenderedComponent<InstancePicker> cut, string text) =>
|
||||
cut.FindAll("[data-test='t-row']").First(r => r.TextContent.Trim() == text).Click();
|
||||
|
||||
private static string InputValue(IRenderedComponent<InstancePicker> cut) =>
|
||||
cut.Find("[data-test='t-input']").GetAttribute("value") ?? string.Empty;
|
||||
|
||||
[Fact]
|
||||
public void Closed_ShowsNothingButTheField()
|
||||
{
|
||||
var cut = RenderPicker();
|
||||
|
||||
Assert.Empty(cut.FindAll("[data-test='t-panel']"));
|
||||
|
||||
var input = cut.Find("[data-test='t-input']");
|
||||
Assert.Equal("combobox", input.GetAttribute("role"));
|
||||
Assert.Equal("false", input.GetAttribute("aria-expanded"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Toggle_OpensPanel_WithAreasCollapsed()
|
||||
{
|
||||
var cut = RenderPicker();
|
||||
|
||||
Open(cut);
|
||||
|
||||
Assert.Single(cut.FindAll("[data-test='t-panel']"));
|
||||
Assert.Equal("true", cut.Find("[data-test='t-input']").GetAttribute("aria-expanded"));
|
||||
|
||||
var rows = cut.FindAll("[data-test='t-row']").Select(r => r.TextContent.Trim()).ToArray();
|
||||
Assert.Equal(new[] { "Line1", "Zulu" }, rows);
|
||||
|
||||
// P1 sits under a collapsed area, so its row is not rendered at all.
|
||||
Assert.Empty(cut.FindAll("[data-instance-id='7']"));
|
||||
|
||||
// Area rows must not carry a data-instance-id at all (Blazor drops a null attribute).
|
||||
var areaRow = cut.FindAll("[data-test='t-row']").First(r => r.TextContent.Trim() == "Line1");
|
||||
Assert.False(areaRow.HasAttribute("data-instance-id"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClickingAnAreaLabel_ExpandsIt()
|
||||
{
|
||||
var cut = RenderPicker();
|
||||
Open(cut);
|
||||
|
||||
ClickRow(cut, "Line1");
|
||||
Assert.Contains(cut.FindAll("[data-test='t-row']"), r => r.TextContent.Trim() == "Cell A");
|
||||
Assert.Empty(cut.FindAll("[data-instance-id='7']"));
|
||||
|
||||
ClickRow(cut, "Cell A");
|
||||
Assert.Single(cut.FindAll("[data-instance-id='7']"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClickingAnInstance_Selects_Closes_AndRaisesTheCallback()
|
||||
{
|
||||
int? picked = null;
|
||||
var cut = RenderPicker(onChanged: id => picked = id);
|
||||
|
||||
Open(cut);
|
||||
ClickRow(cut, "Line1");
|
||||
ClickRow(cut, "Cell A");
|
||||
cut.Find("[data-instance-id='7']").Click();
|
||||
|
||||
Assert.Equal(7, picked);
|
||||
Assert.Empty(cut.FindAll("[data-test='t-panel']"));
|
||||
Assert.Equal("P1", InputValue(cut));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Disabled_NeverOpens()
|
||||
{
|
||||
var cut = RenderPicker(disabled: true);
|
||||
|
||||
Assert.True(cut.Find("[data-test='t-input']").HasAttribute("disabled"));
|
||||
Assert.True(cut.Find("[data-test='t-toggle']").HasAttribute("disabled"));
|
||||
|
||||
Open(cut);
|
||||
|
||||
Assert.Empty(cut.FindAll("[data-test='t-panel']"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Backdrop_ClickClosesThePanel_WithoutChangingSelection()
|
||||
{
|
||||
int? picked = null;
|
||||
var cut = RenderPicker(onChanged: id => picked = id);
|
||||
|
||||
Open(cut);
|
||||
cut.Find("[data-test='t-backdrop']").Click();
|
||||
|
||||
Assert.Empty(cut.FindAll("[data-test='t-panel']"));
|
||||
Assert.Null(picked);
|
||||
Assert.Equal(string.Empty, InputValue(cut));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParentDrivenSelection_UpdatesTheFieldText()
|
||||
{
|
||||
var cut = RenderPicker();
|
||||
|
||||
cut.Render(ps => ps.Add(p => p.SelectedInstanceId, 8));
|
||||
Assert.Equal("Zulu", InputValue(cut));
|
||||
|
||||
cut.Render(ps => ps.Add(p => p.SelectedInstanceId, 0));
|
||||
Assert.Equal(string.Empty, InputValue(cut));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SiteChange_NewInstancesList_ClearsAStaleSelectionText()
|
||||
{
|
||||
var cut = RenderPicker(selectedInstanceId: 8);
|
||||
Assert.Equal("Zulu", InputValue(cut));
|
||||
|
||||
Open(cut);
|
||||
|
||||
// A different site: neither the areas nor the previously selected instance survive.
|
||||
cut.Render(ps =>
|
||||
{
|
||||
ps.Add(p => p.Areas, new List<Area>());
|
||||
ps.Add(p => p.Instances, new List<Instance> { new("Other") { Id = 99, SiteId = 2 } });
|
||||
});
|
||||
|
||||
Assert.Equal(string.Empty, InputValue(cut));
|
||||
Assert.Empty(cut.FindAll("[data-test='t-panel']"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ItemLabel_IsUsedForRowsAndField()
|
||||
{
|
||||
var cut = RenderPicker(itemLabel: i => i.UniqueName + " (x)");
|
||||
|
||||
Open(cut);
|
||||
|
||||
var rows = cut.FindAll("[data-test='t-row']").Select(r => r.TextContent.Trim()).ToArray();
|
||||
Assert.Equal(new[] { "Line1", "Zulu (x)" }, rows);
|
||||
|
||||
ClickRow(cut, "Line1");
|
||||
ClickRow(cut, "Cell A");
|
||||
cut.Find("[data-instance-id='7']").Click();
|
||||
|
||||
Assert.Equal("P1 (x)", InputValue(cut));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user