using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.AdminUI.Uns; namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Uns; /// /// Verifies returns Tag leaf nodes /// followed by VirtualTag leaf nodes, in Name order, with the correct keys and display names. /// [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)); } /// /// Tags come first, ordered by Name, then VirtualTags; keys follow the tag:/vtag: scheme /// and the Tag display name embeds the DataType. /// [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(); } /// An equipment with no tags or virtual tags returns an empty list. [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(); } }