From fcc73ccd2df88a45a6a1dfcc9ab69a048265c4fe Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 11 Jun 2026 21:12:52 -0400 Subject: [PATCH] fix(adminui): null Source for alias rows without a FullName (review nits) --- .../Uns/IUnsTreeService.cs | 4 ++- .../Uns/UnsTreeService.cs | 3 +- .../Uns/UnsTreeServiceAliasTagTests.cs | 34 +++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/IUnsTreeService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/IUnsTreeService.cs index 2b4d5dfb..8209ceb6 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/IUnsTreeService.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/IUnsTreeService.cs @@ -345,7 +345,9 @@ public interface IUnsTreeService Task> LoadTagDriversForEquipmentAsync(string equipmentId, CancellationToken ct = default); /// Galaxy gateway driver instances (DriverType "GalaxyMxGateway") in the equipment's - /// cluster, for the alias address picker. Tuple = (DriverInstanceId, Display, DriverConfig). + /// cluster, for the alias address picker. Tuple = (DriverInstanceId, Display, DriverConfig). + /// Display is intentionally "{DriverInstanceId} — {Name}" (no DriverType suffix) + /// because every returned driver is a Galaxy gateway — do not add the type suffix. Task> LoadGalaxyGatewaysForEquipmentAsync(string equipmentId, CancellationToken ct = default); diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs index df0d76cd..62d82b50 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs @@ -111,7 +111,8 @@ public sealed class UnsTreeService(IDbContextFactory dbF return rows.Select(r => { var isAlias = r.DriverType == "GalaxyMxGateway"; - var source = isAlias ? $"galaxy:{ExtractTagConfigFullName(r.TagConfig)}" : null; + var fullName = isAlias ? ExtractTagConfigFullName(r.TagConfig) : null; + var source = fullName is not null ? $"galaxy:{fullName}" : null; return new EquipmentTagRow(r.TagId, r.Name, r.DriverInstanceId, r.DataType, r.AccessLevel, isAlias, source); }).ToList(); } diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceAliasTagTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceAliasTagTests.cs index c18333b8..fc32d4ab 100644 --- a/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceAliasTagTests.cs +++ b/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceAliasTagTests.cs @@ -173,6 +173,40 @@ public sealed class UnsTreeServiceAliasTagTests normal.IsAlias.ShouldBeFalse(); normal.Source.ShouldBeNull(); } + + /// + /// A GalaxyMxGateway-bound tag whose TagConfig carries no FullName (e.g. "{}") is + /// still an alias (IsAlias = true) but has a null Source — the display should not + /// show the literal "galaxy:" string. + /// + [Fact] + public async Task LoadTagsForEquipment_alias_with_no_FullName_has_null_Source() + { + var dbName = SeedCluster(); + + using (var db = UnsTreeTestDb.CreateNamed(dbName)) + { + db.Tags.Add(new Tag + { + TagId = "TAG-ALIAS-NONAME", + DriverInstanceId = GatewayDriverId, + EquipmentId = EquipmentId, + Name = "unconfigured-alias", + DataType = "Float", + AccessLevel = TagAccessLevel.Read, + TagConfig = "{}", + }); + db.SaveChanges(); + } + + var service = new UnsTreeService(UnsTreeTestDb.Factory(dbName)); + + var rows = await service.LoadTagsForEquipmentAsync(EquipmentId); + + var alias = rows.ShouldHaveSingleItem(r => r.TagId == "TAG-ALIAS-NONAME"); + alias.IsAlias.ShouldBeTrue(); + alias.Source.ShouldBeNull(); + } } /// Small Shouldly-style helper for "exactly one match" assertions used by these tests.