diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Topology.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Topology.razor index 6a0fb025..326a80eb 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Topology.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Topology.razor @@ -892,13 +892,20 @@ } // Compact summary of a connection's deployment-relevant fields for the diff - // table's Before/After cells: protocol, primary endpoint config, and the - // failover retry count. Mirrors the fields ConnectionsEqual compares. + // table's Before/After cells. Surfaces all four fields ConnectionsEqual + // compares — protocol, primary endpoint config, failover retry count, and + // the backup endpoint — so a backup-only change doesn't show identical + // Before/After cells. The backup segment is omitted when there is no backup. private static string FormatConnection( ZB.MOM.WW.ScadaBridge.Commons.Types.Flattening.ConnectionConfig c) { var endpoint = string.IsNullOrWhiteSpace(c.ConfigurationJson) ? "—" : c.ConfigurationJson; - return $"{c.Protocol} · {endpoint} · failover ×{c.FailoverRetryCount}"; + var summary = $"{c.Protocol} · {endpoint} · failover ×{c.FailoverRetryCount}"; + if (!string.IsNullOrWhiteSpace(c.BackupConfigurationJson)) + { + summary += $" · backup {c.BackupConfigurationJson}"; + } + return summary; } // Renders one change section (a heading plus a Bootstrap change-table) for a diff --git a/tests/ZB.MOM.WW.ScadaBridge.TemplateEngine.Tests/Flattening/DiffServiceTests.cs b/tests/ZB.MOM.WW.ScadaBridge.TemplateEngine.Tests/Flattening/DiffServiceTests.cs index e405a109..fb5fa89f 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.TemplateEngine.Tests/Flattening/DiffServiceTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.TemplateEngine.Tests/Flattening/DiffServiceTests.cs @@ -286,6 +286,36 @@ public class DiffServiceTests Assert.Equal("OpcUa", diff[0].NewValue!.Protocol); } + [Fact] + public void ComputeConnectionsDiff_NullOldConfig_AllReportedAsAdded() + { + // First deploy: there is no prior flattened config at all (null), so + // every connection in the new config is Added. Exercises the public + // method's null-oldConfig tolerance explicitly (the ComputeDiff path + // covers it end-to-end, but the isolated API contract is asserted here). + var newConfig = new FlattenedConfiguration + { + InstanceUniqueName = "Instance1", + Connections = new Dictionary + { + ["plc1"] = new ConnectionConfig + { + Protocol = "OpcUa", + ConfigurationJson = "{\"endpoint\":\"opc.tcp://host\"}", + FailoverRetryCount = 3, + } + } + }; + + var diff = _sut.ComputeConnectionsDiff(null, newConfig); + + Assert.Single(diff); + Assert.Equal("plc1", diff[0].CanonicalName); + Assert.Equal(DiffChangeType.Added, diff[0].ChangeType); + Assert.Null(diff[0].OldValue); + Assert.Equal("OpcUa", diff[0].NewValue!.Protocol); + } + [Fact] public void ComputeConnectionsDiff_BindingCleared_ReportedAsRemoved() {