diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/AlarmsViewModelTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/AlarmsViewModelTests.cs
index 503ab5b3..73ac6e10 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/AlarmsViewModelTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/AlarmsViewModelTests.cs
@@ -342,6 +342,47 @@ public class AlarmsViewModelTests
message.ShouldContain("Confirm failed");
}
+ /// Verifies that confirming an alarm without a ConditionNodeId is rejected without a service call.
+ [Fact]
+ public async Task ConfirmAlarm_MissingConditionNodeId_Fails_NoServiceCall()
+ {
+ _vm.IsConnected = true;
+ var alarm = BuildAlarm(conditionNodeId: null);
+
+ var (ok, _) = await _vm.ConfirmAlarmAsync(alarm, "note");
+
+ ok.ShouldBeFalse();
+ _service.ConfirmCallCount.ShouldBe(0);
+ }
+
+ /// Verifies that a transport exception from ShelveAlarmAsync is caught and surfaced as an error message.
+ [Fact]
+ public async Task ShelveAlarm_ServiceThrows_ReturnsError()
+ {
+ _vm.IsConnected = true;
+ _service.ShelveException = new InvalidOperationException("transport error");
+ var alarm = BuildAlarm();
+
+ var (ok, message) = await _vm.ShelveAlarmAsync(alarm, ShelveKind.OneShot, 0);
+
+ ok.ShouldBeFalse();
+ message.ShouldContain("Error");
+ }
+
+ /// Verifies that a transport exception from ConfirmAlarmAsync is caught and surfaced as an error message.
+ [Fact]
+ public async Task ConfirmAlarm_ServiceThrows_ReturnsError()
+ {
+ _vm.IsConnected = true;
+ _service.ConfirmException = new InvalidOperationException("transport error");
+ var alarm = BuildAlarm();
+
+ var (ok, message) = await _vm.ConfirmAlarmAsync(alarm, "note");
+
+ ok.ShouldBeFalse();
+ message.ShouldContain("Error");
+ }
+
// --- CanShelve / CanConfirm predicates ---
/// Verifies CanShelve is true when a ConditionNodeId is present.