Files
lmxopcua/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceLazyTests.cs
T
Joseph Doherty b33cf1c80d feat(uns): lazy per-equipment tag + virtual-tag load
Add LoadEquipmentChildrenAsync to IUnsTreeService and UnsTreeService; returns
Tag nodes (ordered by Name) then VirtualTag nodes (ordered by Name) as leaf
nodes with ChildCount=0, HasLazyChildren=false, keys tag:{id}/vtag:{id}.
2026-06-08 12:29:52 -04:00

83 lines
3.0 KiB
C#

using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.AdminUI.Uns;
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Uns;
/// <summary>
/// Verifies <see cref="UnsTreeService.LoadEquipmentChildrenAsync"/> returns Tag leaf nodes
/// followed by VirtualTag leaf nodes, in Name order, with the correct keys and display names.
/// </summary>
[Trait("Category", "Unit")]
public sealed class UnsTreeServiceLazyTests
{
private static UnsTreeService SeededService()
{
var dbName = $"uns-lazy-{Guid.NewGuid():N}";
UnsTreeTestDb.SeedNamed(dbName);
return new UnsTreeService(UnsTreeTestDb.Factory(dbName));
}
/// <summary>
/// Tags come first, ordered by Name, then VirtualTags; keys follow the tag:/vtag: scheme
/// and the Tag display name embeds the DataType.
/// </summary>
[Fact]
public async Task LoadEquipmentChildren_returns_tags_then_vtags()
{
var service = SeededService();
var children = await service.LoadEquipmentChildrenAsync(UnsTreeTestDb.SeededEquipmentId);
// Seed has 2 tags (speed=Float, running=Boolean) + 1 vtag (computed).
// Tags are ordered by Name: "running" < "speed".
children.Count.ShouldBe(3);
var running = children[0];
running.Kind.ShouldBe(UnsNodeKind.Tag);
running.Key.ShouldBe("tag:TAG-2");
running.EntityId.ShouldBe("TAG-2");
running.ClusterId.ShouldBeNull();
running.DisplayName.ShouldContain("running");
running.DisplayName.ShouldContain("Boolean");
running.ChildCount.ShouldBe(0);
running.HasLazyChildren.ShouldBeFalse();
running.Children.ShouldBeEmpty();
var speed = children[1];
speed.Kind.ShouldBe(UnsNodeKind.Tag);
speed.Key.ShouldBe("tag:TAG-1");
speed.EntityId.ShouldBe("TAG-1");
speed.DisplayName.ShouldContain("speed");
speed.DisplayName.ShouldContain("Float");
var vtag = children[2];
vtag.Kind.ShouldBe(UnsNodeKind.VirtualTag);
vtag.Key.ShouldBe("vtag:VTAG-1");
vtag.EntityId.ShouldBe("VTAG-1");
vtag.ClusterId.ShouldBeNull();
vtag.DisplayName.ShouldContain("computed");
vtag.DisplayName.ShouldContain("VirtualTag");
vtag.ChildCount.ShouldBe(0);
vtag.HasLazyChildren.ShouldBeFalse();
vtag.Children.ShouldBeEmpty();
}
/// <summary>An equipment with no tags or virtual tags returns an empty list.</summary>
[Fact]
public async Task LoadEquipmentChildren_empty_for_equipment_with_none()
{
// Use a fresh named store and add an equipment with no tags/vtags.
var dbName = $"uns-lazy-empty-{Guid.NewGuid():N}";
UnsTreeTestDb.SeedNamed(dbName);
// The orphan equipment id is not in the seeded fixture, so just use a novel id.
const string emptyEquipmentId = "EQ-NO-TAGS";
var service = new UnsTreeService(UnsTreeTestDb.Factory(dbName));
var children = await service.LoadEquipmentChildrenAsync(emptyEquipmentId);
children.ShouldBeEmpty();
}
}