using System.Security.Claims;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.MongoModels;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;
using Moq;
using Options = Microsoft.Extensions.Options.Options;
namespace adas_core.Test.Services;
///
/// Contains unit tests for verifying the behavior and functionality of the class.
///
public class AlarmServiceTest
{
private readonly Mock _alarmRepositoryMock;
private readonly AlarmService _alarmService;
private readonly ApiSettings _apiSettings = new()
{
ConfigObservation = new ConfigObservationSettings
{
IgnoreUnknownObservation = false
},
IntravenousLinesCode = ["10546003"],
AllergiesCode = ["473011001"],
DrainageCode = ["56868008"],
IsolationCode = ["302147001"],
PositionCode = ["386053000"]
};
private readonly Mock _calculatedObservationsServiceMock;
private readonly Mock _configObservationServiceMock;
private readonly Mock _observationServiceMock;
private readonly Mock _patientServiceMock;
private readonly RecordingSettings _recordingSettings = new();
private readonly Mock _unitServiceMock;
public AlarmServiceTest()
{
var optionsApiSettings = Options.Create(_apiSettings);
Options.Create(_recordingSettings);
_observationServiceMock = new Mock();
var observationServiceMockLazy = new Lazy(() => _observationServiceMock.Object);
_patientServiceMock = new Mock();
_configObservationServiceMock = new Mock();
_unitServiceMock = new Mock();
var pocServiceMock = new Mock();
var beaconServiceMock = new Mock();
var beaconServiceMockLazy = new Lazy(() => beaconServiceMock.Object);
var relayServiceMock = new Mock();
var relayServiceMockLazy = new Lazy(() => relayServiceMock.Object);
var recordingServiceMock = new Mock();
var recordingServiceMockLazy = new Lazy(() => recordingServiceMock.Object);
var clientMessageServiceMock = new Mock();
var subscribersServiceMock = new Mock();
var httpContextAccessorMock = new Mock();
var auditServiceMock = new Mock();
_calculatedObservationsServiceMock = new Mock();
var calculatedObservationsServiceLazy =
new Lazy(() => _calculatedObservationsServiceMock.Object);
var logger = new Mock>();
_alarmRepositoryMock = new Mock();
var userClaims = new ClaimsPrincipal(new ClaimsIdentity([
new Claim(ClaimTypes.Name, "TestUser")
], "mock"));
var httpContextMock = new DefaultHttpContext
{
User = userClaims
};
httpContextAccessorMock.Setup(accessor => accessor.HttpContext)
.Returns(httpContextMock);
_alarmService = new AlarmService(
_alarmRepositoryMock.Object,
logger.Object,
_patientServiceMock.Object,
_configObservationServiceMock.Object,
observationServiceMockLazy,
clientMessageServiceMock.Object,
subscribersServiceMock.Object,
calculatedObservationsServiceLazy,
beaconServiceMockLazy,
recordingServiceMockLazy,
relayServiceMockLazy,
optionsApiSettings,
_unitServiceMock.Object,
pocServiceMock.Object,
httpContextAccessorMock.Object,
auditServiceMock.Object,
false // Disable the timer for testing
);
}
///
/// Verifies that when an ORU_R40 type request is processed without any alarms, the patient is located but the observation is not persisted.
///
[Test]
public async Task SaveRequest_Oru_R40_Type_Without_Alarms_Dont_Insert()
{
// Arrange
var apiRequest = new ApiRequest
{
Type = "ORU_R40",
PatientNumber = "12345",
Observation = new PatientObservation { Value = "Test" },
Alarms = [],
Location = new PatientLocation { Bed = "Bed1", Room = "Bed1", UnitName = "Unit1" }
};
var unit = new Unit { Configuration = new UnitConfiguration { AutoAdt = true } };
var patient = new Patient { Id = ObjectId.GenerateNewId(), Bed = "Bed1" };
_unitServiceMock.Setup(u => u.FindByUnitNameOrPocName(It.IsAny(), It.IsAny()))
.ReturnsAsync(unit);
_patientServiceMock.Setup(p => p.FindPatientByApiRequest(apiRequest)).ReturnsAsync(patient);
_observationServiceMock.Setup(o => o.SaveRequestAsync(It.IsAny())).Returns(Task.CompletedTask);
// Act
await _alarmService.SaveRequest(apiRequest);
// Assert
_patientServiceMock.Verify(p => p.FindPatientByApiRequest(apiRequest), Times.Once);
_observationServiceMock.Verify(o => o.SaveRequestAsync(It.IsAny()), Times.Never);
}
///
/// Verifies that inserts the provided alarm observations into the alarm repository.
///
[Test]
public async Task ProcessAlarmObservations_Should_Insert_Alarm_Observations()
{
// Arrange
var patient = new Patient { Id = ObjectId.GenerateNewId(), Bed = "Bed1" };
var alarmObservations = new List
{
new() { Value = "Alarm1", Time = DateTime.UtcNow}
};
var observations = new List
{
new() { Value = "Alarm1", Time = DateTime.MinValue}
};
_configObservationServiceMock.Setup(o => o.Map(It.IsAny(), It.IsAny()))
.ReturnsAsync((PatientObservationAlarm obs, bool _) => obs); // Correct setup
_calculatedObservationsServiceMock.Setup(o => o.Map(It.IsAny(), It.IsAny()))
.ReturnsAsync((PatientObservationAlarm obs, bool _) => obs); // Correct setup
// Act
await _alarmService.ProcessAlarmObservations(alarmObservations, observations, patient, DateTime.UtcNow);
// Assert
_alarmRepositoryMock.Verify(a => a.InsertOneAsync(It.IsAny()), Times.Once);
}
///
/// Verifies that when checking observation alarms for a patient observation with an "Event_PEEP_Low" configuration
/// (coding system "ADAS_EVENT", description "EVT_LO and EVT_EXTR_LO"), the alarm service does not insert a new observation,
/// as indicated by the verification that InsertObservation is never invoked.
///
[Test]
public async Task CheckObservationAlarm_Alarm_EventPEEP_PEEP_bajo_create_Event()
{
var obs = new PatientObservation();
var configs = new ConfigObservation
{
Id = ObjectId.GenerateNewId(),
Name = "Event_PEEP_Low",
CodingSystem = "ADAS_EVENT",
Description = "EVT_LO and EVT_EXTR_LO"
};
_configObservationServiceMock.Setup(c => c.Get(It.IsAny(), false))
.ReturnsAsync(configs);
await _alarmService.CheckObservationAlarm(obs);
_observationServiceMock.Verify(o => o.InsertObservation(obs, true, true), Times.Never);
}
///
/// Verifies that processes a patient observation
/// matching a configured rule (name "EVT_LO" with required value "PEEP") by inserting a new
/// observation with the original value preserved (e.g., "PEEP High") while the alarm
/// configuration handles the red beacon signaling.
///
[Test]
public async Task CheckObservationAlarm_Should_Launch_Red_Alarm_And_Set_BeaconColor_Red()
{
var alarmConfig = new AlarmConfig
{
Enabled = true,
Priority = 10,
Beacon = new AlarmItem
{
Enabled = true,
BeaconColor = AlarmEnum.BeaconColor.Red, // Using the enum value
EndAfter = 60 // Assuming the alarm should end after 60 seconds
}
};
var configs = new ConfigObservation
{
Id = ObjectId.GenerateNewId(),
Name = "Event_PEEP_Low",
CodingSystem = "ADAS_EVENT",
Description = "logs an event. No generate an alarm.",
Alarm = alarmConfig,
RequiredValue = "PEEP"
};
var obsConfig = new ConfigObservation
{
Id = ObjectId.GenerateNewId(),
Name = "EVT_LO",
CheckObservations = true,
CreateObservation = [configs]
};
var patId = ObjectId.GenerateNewId();
// Arrange
var obs = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
Name = "EVT_LO",
PatientId = patId,
Value = "PEEP High",
Time = DateTime.UtcNow,
CheckObservations = true,
CreateObservation = [configs]
};
_configObservationServiceMock.Setup(c => c.Get(It.IsAny(), false))
.ReturnsAsync(obsConfig);
// Act
await _alarmService.CheckObservationAlarm(obs);
_observationServiceMock.Verify(
o => o.InsertObservation(
It.Is(ob => ob.Value.ToString() == "PEEP High"), true, true),
Times.Once);
}
}