refactor(adminui): harden SetFullName (reject blank ref) + cover alarm-flag re-pick

Code-review nits: SetFullName now throws on a blank reference (was silently
persisting FullName:null → silent deploy-time bind failure), and a new test
covers the alarm-typed re-pick combo (SeedDefaultAlarm over an already-edited
alarm leaves it intact).
This commit is contained in:
Joseph Doherty
2026-06-19 02:08:43 -04:00
parent da57c307a7
commit e047af0553
2 changed files with 28 additions and 0 deletions
@@ -54,6 +54,9 @@ public static class TagConfigJson
/// </summary>
public static string SetFullName(string? json, string fullName)
{
// A blank reference is never a valid Galaxy bind — surface it loudly rather than persisting
// a poisoned "FullName": null/"" that would silently fail to bind at deploy time.
ArgumentException.ThrowIfNullOrWhiteSpace(fullName);
var o = ParseOrNew(json);
o["FullName"] = JsonValue.Create(fullName);
return Serialize(o);
@@ -75,6 +75,31 @@ public sealed class GalaxyAddressRepickMergeTests
merged.ShouldEndWith("}");
}
[Fact]
public void Repick_with_alarm_flag_does_not_overwrite_existing_alarm_object()
{
// Mirrors the handler's alarm-typed re-pick: SeedDefaultAlarm(SetFullName(existing, addr)).
// The operator authored an alarm, then re-picks an alarm-typed Galaxy attribute — the
// SeedDefaultAlarm no-op guard must leave the edited alarm intact, not re-seed a default.
const string current =
"""{"FullName":"Pump_001.OldAttr","alarm":{"alarmType":"LimitAlarm","severity":250,"historizeToAveva":false}}""";
var merged = NativeAlarmModel.SeedDefaultAlarm(TagConfigJson.SetFullName(current, "Pump_001.NewAttr"));
ReadFullName(merged).ShouldBe("Pump_001.NewAttr");
var alarm = NativeAlarmModel.FromJson(merged);
alarm.IsAlarm.ShouldBeTrue();
alarm.AlarmType.ShouldBe("LimitAlarm");
alarm.Severity.ShouldBe(250);
alarm.HistorizeToAveva.ShouldBe(false);
}
[Fact]
public void SetFullName_rejects_a_blank_reference()
{
Should.Throw<ArgumentException>(() => TagConfigJson.SetFullName("""{"FullName":"x"}""", " "));
}
// Mirror of TagModal.ReadFullName — extracts FullName from a Galaxy TagConfig blob.
private static string ReadFullName(string json)
{