diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Cluster/CliRunner.Helpers.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Cluster/CliRunner.Helpers.cs index 16db7dbe..bbe1892b 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Cluster/CliRunner.Helpers.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Cluster/CliRunner.Helpers.cs @@ -100,6 +100,34 @@ public static partial class CliRunner await RunAsync([.. args]); } + /// + /// Adds an alarm to a template via template alarm add (using the typed setpoint + /// flags) and returns its new id. Throws on failure. + /// + public static async Task AddAlarmAsync( + int templateId, string name, string triggerType = "HiLo", int priority = 500, + string? attribute = null, double? hi = null, double? hiHi = null, + double? lo = null, double? loLo = null) + { + var inv = System.Globalization.CultureInfo.InvariantCulture; + var args = new List + { + "template", "alarm", "add", + "--template-id", templateId.ToString(inv), + "--name", name, + "--trigger-type", triggerType, + "--priority", priority.ToString(inv), + }; + if (attribute is not null) { args.Add("--attribute"); args.Add(attribute); } + if (hi.HasValue) { args.Add("--hi"); args.Add(hi.Value.ToString(inv)); } + if (hiHi.HasValue) { args.Add("--hihi"); args.Add(hiHi.Value.ToString(inv)); } + if (lo.HasValue) { args.Add("--lo"); args.Add(lo.Value.ToString(inv)); } + if (loLo.HasValue) { args.Add("--lolo"); args.Add(loLo.Value.ToString(inv)); } + + using var doc = await RunJsonAsync([.. args]); + return RequireId(doc, "template alarm add"); + } + /// /// Creates an area under a site via site area create and returns its /// new id. @@ -558,6 +586,18 @@ public static partial class CliRunner } } + /// Best-effort delete of an instance alarm override (teardown). Never throws. + public static async Task DeleteInstanceAlarmOverrideAsync(int instanceId, string alarmCanonicalName) + { + var inv = System.Globalization.CultureInfo.InvariantCulture; + try + { + await RunAsync("instance", "alarm-override", "delete", + "--instance-id", instanceId.ToString(inv), "--alarm", alarmCanonicalName); + } + catch { /* best-effort teardown — never mask the test's own failure. */ } + } + /// /// Exports a Transport bundle scoped to a single template via /// bundle export. diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Cluster/CliRunnerHelpersTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Cluster/CliRunnerHelpersTests.cs index 76793453..0fe2c7b6 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Cluster/CliRunnerHelpersTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Cluster/CliRunnerHelpersTests.cs @@ -188,4 +188,23 @@ public class CliRunnerHelpersTests } finally { await CliRunner.DeleteRoleMappingAsync(id); } } + + /// + /// Exercises the typed HiLo setpoint flags end-to-end: a template alarm added via + /// with --hi/--hihi returns a + /// positive id, confirming the server accepted the serialized trigger-config JSON. + /// + [SkippableFact] + public async Task AddAlarmWithTypedFlags_RoundTrips() + { + Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); + var id = await CliRunner.CreateTemplateAsync(CliRunner.UniqueName("tmpl")); + try + { + await CliRunner.AddAttributeAsync(id, "Value", "Double"); + var alarmId = await CliRunner.AddAlarmAsync(id, "HiHi", "HiLo", 500, attribute: "Value", hi: 80, hiHi: 95); + Assert.True(alarmId > 0); // server accepted the serialized trigger-config JSON + } + finally { await CliRunner.DeleteTemplateAsync(id); } + } }