Files
adas-core/adas-core.Test/Customizations/HPAZ/CalculatedObservationsTest.cs
T

991 lines
38 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using adas_core.Application.Customizations.HPAZ;
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.Pumps;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using Moq;
using Options = Microsoft.Extensions.Options.Options;
namespace adas_core.Test.Customizations.HPAZ;
/// <summary>
/// Provides a NUnit test fixture that hosts unit tests verifying the behavior of calculated observations.
/// </summary>
/// <remarks>
/// The class is marked with the <see cref="TestFixtureAttribute"/> attribute to group test methods that validate calculated observation logic.
/// </remarks>
/// <!-- aidoc:v1 sig=ce3e368 -->
[TestFixture]
public class CalculatedObservationsTest
{
/// <summary>
/// Initializes mocked dependencies and configures the dependency injection container required to instantiate the <see cref="CalculatedObservations"/> service under test.
/// </summary>
/// <!-- aidoc:v1 sig=dee8bf2 body=d74ae8f -->
[SetUp]
public void Setup()
{
_alarmServiceMock = new Mock<IAlarmService>();
var alarmServiceLazy = new Lazy<IAlarmService>(() => _alarmServiceMock.Object);
_patientServiceMock = new Mock<IPatientService>();
_lightBeaconServiceMock = new Mock<ILightBeaconService>();
var balizaServiceLazy = new Lazy<ILightBeaconService>(() => _lightBeaconServiceMock.Object);
_recordingServiceMock = new Mock<IRecordingService>();
var recordingServiceLazy = new Lazy<IRecordingService>(() => _recordingServiceMock.Object);
_relayServiceMock = new Mock<IRelayService>();
var relayServiceLazy = new Lazy<IRelayService>(() => _relayServiceMock.Object);
_treatmentServiceMock = new Mock<ITreatmentService>();
var treatmentServiceLazy = new Lazy<ITreatmentService>(() => _treatmentServiceMock.Object);
_medicineServiceMock = new Mock<IMedicineService>();
var medicineServiceLazy = new Lazy<IMedicineService>(() => _medicineServiceMock.Object);
_configObservationServiceMock = new Mock<IConfigObservationService>();
_observationServiceMock = new Mock<IObservationService>();
var observationServiceLazy = new Lazy<IObservationService>(() => _observationServiceMock.Object);
_logger = new Mock<ILogger<CalculatedObservations>>();
_optionsApiSettings = Options.Create(_apiSettings);
_optionsApiSettings.Value.IgnoreCalcObservationsOlderInMinutesThan = 5;
_optionsRecordingSettings = Options.Create(_recordingSettings);
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton(_patientServiceMock.Object);
serviceCollection.AddSingleton(balizaServiceLazy);
serviceCollection.AddSingleton(recordingServiceLazy);
serviceCollection.AddSingleton(relayServiceLazy);
serviceCollection.AddSingleton(treatmentServiceLazy);
serviceCollection.AddSingleton(medicineServiceLazy);
serviceCollection.AddSingleton(_configObservationServiceMock.Object);
serviceCollection.AddSingleton(observationServiceLazy);
serviceCollection.AddSingleton(_optionsApiSettings);
serviceCollection.AddSingleton(_optionsRecordingSettings);
serviceCollection.AddSingleton(_logger.Object);
serviceCollection.AddSingleton(alarmServiceLazy);
var serviceProvider = serviceCollection.BuildServiceProvider();
_calculatedObservations = new CalculatedObservations(serviceProvider);
}
private CalculatedObservations _calculatedObservations;
private Mock<IPatientService> _patientServiceMock;
private Mock<ILightBeaconService> _lightBeaconServiceMock;
private Mock<IRecordingService> _recordingServiceMock;
private Mock<IRelayService> _relayServiceMock;
private Mock<ITreatmentService> _treatmentServiceMock;
private Mock<IMedicineService> _medicineServiceMock;
private Mock<IConfigObservationService> _configObservationServiceMock;
private Mock<IObservationService> _observationServiceMock;
private Mock<IAlarmService> _alarmServiceMock;
private Mock<ILogger<CalculatedObservations>> _logger;
private readonly ApiSettings _apiSettings = new()
{
VolumetricAirOcclusionAlarm = ["Occlusion", "Upstream Occlusion"]
};
private IOptions<ApiSettings> _optionsApiSettings;
private readonly RecordingSettings _recordingSettings = new();
private IOptions<RecordingSettings> _optionsRecordingSettings;
private readonly List<string> _pressBloodArteryMean = ["TAm"];
private static readonly DateTime Now = DateTime.Now;
private static readonly ObjectId PatientId = ObjectId.GenerateNewId();
/// <summary>
/// Verifies that a PatientObservation with the ventilation mode "PRVC" is mapped to a calculated observation with the value "VCRP".
/// </summary>
/// <!-- aidoc:v1 sig=eb9f8ec body=e44fb52 -->
[Test]
public async Task Calculate_Ventilation_Mode_PRVC_Returns_VCRP()
{
var patientId = ObjectId.GenerateNewId();
var observation = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Value = "PRVC",
Name = "Resp_Mode"
};
var result = await _calculatedObservations.Map(observation, false);
Assert.That(result, Is.Not.Null);
Assert.That(result!.Value, Is.EqualTo("VCRP"));
}
/// <summary>
/// Verifies that the calculated observations mapping translates the ventilation mode value "FLUJ.ALTO" (High Flow) into the respiratory support code "OAF".
/// Ensures that a patient observation with the name "Resp_Mode" and value "FLUJ.ALTO" produces a non-null mapped result with the expected output value.
/// </summary>
/// <!-- aidoc:v1 sig=76d5e48 body=d17dc11 -->
[Test]
public async Task Calculate_Ventilation_Mode_FLUJ_ALTO_Returns_OAF()
{
var patientId = ObjectId.GenerateNewId();
var observation = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Value = "FLUJ.ALTO",
Name = "Resp_Mode"
};
var result = await _calculatedObservations.Map(observation, false);
Assert.That(result, Is.Not.Null);
Assert.That(result!.Value, Is.EqualTo("OAF"));
}
/// <summary>
/// Verifies that when a patient observation's respiratory mode is neither "PRVC" nor "FLUJ_ALTO" (for example, "VNI PC"), the calculated observation is not mapped to "VCRP" or "OAF".
/// </summary>
/// <!-- aidoc:v1 sig=44eb476 body=279d733 -->
[Test]
public async Task Calculate_Ventilation_Mode_Not_PRVC_Not_FLUJ_ALTO_Returns_Other()
{
var patientId = ObjectId.GenerateNewId();
var observation = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Value = "VNI PC",
Name = "Resp_Mode"
};
var result = await _calculatedObservations.Map(observation, false);
Assert.That(result, Is.Not.Null);
using (Assert.EnterMultipleScope())
{
Assert.That(result!.Value, Is.Not.EqualTo("VCRP"));
Assert.That(result.Value, Is.Not.EqualTo("OAF"));
}
}
/// <summary>
/// Verifies that the calculated observations mapping does not produce a Sattc_FiO2 observation
/// when the Sattc value is 98, ensuring the calculation is suppressed for this specific input case.
/// </summary>
/// <!-- aidoc:v1 sig=c417ee7 body=b77cd07 -->
[Test]
public async Task CalculateSF_Sattc_98_Returns_Not_Sattc_FiO2()
{
var patientId = ObjectId.GenerateNewId();
var observation = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "Sattc",
Value = 98
};
var obsLast = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "FiO2",
Value = 34
};
var value = 96.0 / 34.0;
value = Math.Round(value, 4);
var obsCalculate = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "Sattc_FiO2",
CodingSystem = "ADAS",
Value = value
};
_observationServiceMock
.Setup(l => l.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
.ReturnsAsync([obsLast]);
await _calculatedObservations.Map(observation, false);
_observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Name == obsCalculate.Name &&
Math.Abs(double.Parse(arg.Value.ToString()!) - double.Parse(obsCalculate.Value.ToString()!)) <= 0 &&
arg.PatientId == patientId
&& arg.CodingSystem == obsCalculate.CodingSystem
), true, true), Times.Never);
}
/// <summary>
/// Verifies that when an FiO2 observation is processed, the Oxygenation Index is calculated and inserted
/// using the related P_VAM and PaO2_Tidal observations retrieved for the same patient.
/// </summary>
/// <!-- aidoc:v1 sig=3315812 body=f686108 -->
[Test]
public async Task CalculateOxygenationIndex_FiO2_Returns_Oxygenation_Index()
{
var patientId = ObjectId.GenerateNewId();
var obsFio2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "FiO2",
Value = 34
};
var obsPVam = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "P_VAM",
Value = 6
};
var obsPaO2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "PaO2_Tidal",
Value = 234
};
const int value = 6 * 34 * 100 / 234;
var obsCalculate = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "Oxygenation_Index",
CodingSystem = "ADAS",
Value = value
};
_observationServiceMock
.Setup(l => l.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
.ReturnsAsync([obsPVam, obsPaO2]);
await _calculatedObservations.Map(obsFio2, false);
_observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Name == obsCalculate.Name && arg.Value.ToString() == obsCalculate.Value.ToString() &&
arg.PatientId == patientId
&& arg.CodingSystem == obsCalculate.CodingSystem
), true, true));
}
/// <summary>
/// Verifies that mapping a <c>P_VAM</c> patient observation produces a derived <c>Oxygenation_Index</c> observation
/// (computed as <c>P_VAM × FiO2 × 100 / PaO2</c>) that is inserted through the observation service for the same patient.
/// </summary>
/// <returns>A task that completes when the expected <c>Oxygenation_Index</c> observation has been inserted via the mocked observation service.</returns>
/// <!-- aidoc:v1 sig=da07bc9 body=502f5d7 -->
[Test]
public async Task CalculateOxygenationIndex_P_VAM_Returns_Oxygenation_Index()
{
var patientId = ObjectId.GenerateNewId();
var obsFiO2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "FiO2",
Value = 34
};
var obsPVam = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "P_VAM",
Value = 6
};
var obsPaO2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "PaO2_Tidal",
Value = 234
};
var value = 6 * 34 * 100 / 234;
var obsCalculate = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "Oxygenation_Index",
CodingSystem = "ADAS",
Value = value
};
_observationServiceMock
.Setup(l => l.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
.ReturnsAsync([obsFiO2, obsPaO2]);
await _calculatedObservations.Map(obsPVam, false);
_observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Name == obsCalculate.Name && arg.Value.ToString() == obsCalculate.Value.ToString() &&
arg.PatientId == patientId
&& arg.CodingSystem == obsCalculate.CodingSystem
), true, true));
}
/// <summary>
/// Verifies that when a PaO2_Tidal observation is mapped, the calculated Oxygenation_Index is derived using the formula P_VAM * FiO2 * 100 / PaO2_Tidal and persisted as an ADAS-coded observation for the same patient.
/// </summary>
/// <!-- aidoc:v1 sig=d5e69ac body=9ff274d -->
[Test]
public async Task CalculateOxygenationIndex_PaO2_Tidal_Returns_Oxygenation_Index()
{
var patientId = ObjectId.GenerateNewId();
var obsFiO2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "FiO2",
Value = 34
};
var obsPVam = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "P_VAM",
Value = 6
};
var obsPaO2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "PaO2_Tidal",
Value = 234
};
var value = 6 * 34 * 100 / 234;
var obsCalculate = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "Oxygenation_Index",
CodingSystem = "ADAS",
Value = value
};
_observationServiceMock
.Setup(l => l.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
.ReturnsAsync([obsFiO2, obsPVam]);
await _calculatedObservations.Map(obsPaO2, false);
_observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Name == obsCalculate.Name && arg.Value.ToString() == obsCalculate.Value.ToString() &&
arg.PatientId == patientId
&& arg.CodingSystem == obsCalculate.CodingSystem
), true, true));
}
/// <summary>
/// Verifies that the oxygenation index is not calculated and persisted when the required FiO2 observation
/// is missing from the patient's most recent observations, even when a PaO2_Tidal observation is provided.
/// Ensures that the mapping logic does not insert a new Oxygenation_Index observation in this scenario.
/// </summary>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The doc states FiO2 is missing from recent observations, but the code mocks FindLastObservations to return FiO2 (it is present); PaO2_Tidal is the observation missing from the recent observations." -->
[Test]
public async Task CalculateOxygenationIndex_PaO2_Tidal_Not_Returns_Oxygenation_Index()
{
var patientId = ObjectId.GenerateNewId();
var obsFiO2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "FiO2",
Value = 34
};
var obsPaO2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "PaO2_Tidal",
Value = 234
};
var obsCalculate = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "Oxygenation_Index",
CodingSystem = "ADAS"
};
_observationServiceMock
.Setup(l => l.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
.ReturnsAsync([obsFiO2]);
await _calculatedObservations.Map(obsPaO2, false);
_observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Name == obsCalculate.Name && arg.PatientId == patientId
&& arg.CodingSystem == obsCalculate.CodingSystem
), true, true), Times.Never);
}
/// <summary>
/// Verifies that the Oxygenation_Index is not calculated or persisted when the PaO2_Tidal observation value is zero.
/// Ensures that the mapping logic skips downstream calculation and InsertObservation is never invoked in this edge case.
/// </summary>
/// <!-- aidoc:v1 sig=b4705b3 body=72f7967 -->
[Test]
public async Task CalculateOxygenationIndex_PaO2_Tidal_0_Not_Returns_Oxygenation_Index()
{
var patientId = ObjectId.GenerateNewId();
var obsFiO2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "FiO2",
Value = 34
};
var obsPVam = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "P_VAM",
Value = 6
};
var obsPaO2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "PaO2_Tidal",
Value = 0
};
const int value = 6 * 34 * 100 / 234;
var obsCalculate = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "Oxygenation_Index",
CodingSystem = "ADAS",
Value = value
};
_observationServiceMock
.Setup(l => l.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
.ReturnsAsync([obsFiO2, obsPVam]);
await _calculatedObservations.Map(obsPaO2, false);
_observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Name == obsCalculate.Name && arg.PatientId == patientId
&& arg.CodingSystem == obsCalculate.CodingSystem
), true, true), Times.Never);
}
/// <summary>
/// Verifies that the mapping process correctly computes the PaO2/FiO2 ratio when a PaO2 observation is provided,
/// by dividing the PaO2 value by the most recent FiO2 observation for the patient and inserting the result as a new
/// PatientObservation with the ADAS coding system.
/// </summary>
/// <!-- aidoc:v1 sig=087da9c body=91ce4a0 -->
[Test]
public async Task CalculatePF_PaO2_Returns_PaO2_FiO2()
{
var patientId = ObjectId.GenerateNewId();
var observation = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "PaO2_Tidal",
Value = 234
};
var obsLast = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "FiO2",
Value = 34
};
var value = 234.0 / 34.0;
value = Math.Round(value, 4);
var obsCalculate = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "PaO2_FiO2",
CodingSystem = "ADAS",
Value = value
};
_observationServiceMock
.Setup(l => l.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
.ReturnsAsync([obsLast]);
await _calculatedObservations.Map(observation, false);
_observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Name == obsCalculate.Name && Equals(TryparseDouble(arg.Value), TryparseDouble(obsCalculate.Value)) &&
arg.PatientId == patientId
&& arg.CodingSystem == obsCalculate.CodingSystem
), true, true));
}
/// <summary>
/// Verifies that the calculated observation mapping produces a PaO2/FiO2 ratio observation
/// when an FiO2 observation is processed, by inserting a new patient observation with the
/// expected ratio value and coding system.
/// </summary>
/// <!-- aidoc:v1 sig=83f8636 body=46adcbd -->
[Test]
public async Task CalculatePF_FiO2_Returns_PaO2_FiO2()
{
var patientId = ObjectId.GenerateNewId();
var observation = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "FiO2",
Value = 34
};
var obsLast = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "PaO2_Tidal",
Value = 234
};
var value = 234.0 / 34.0;
value = Math.Round(value, 4);
var obsCalculate = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "PaO2_FiO2",
CodingSystem = "ADAS",
Value = value
};
_observationServiceMock
.Setup(l => l.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
.ReturnsAsync([obsLast]);
await _calculatedObservations.Map(observation, false);
_observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Name == obsCalculate.Name && Equals(TryparseDouble(arg.Value), TryparseDouble(obsCalculate.Value)) &&
arg.PatientId == patientId
&& arg.CodingSystem == obsCalculate.CodingSystem
), true, true));
}
/// <summary>
/// Verifies that the PF ratio calculation does not produce a PaO2/FiO2 observation when the FiO2 value is zero.
/// Ensures that no calculated observation is inserted for the patient under this condition.
/// </summary>
/// <!-- aidoc:v1 sig=74e2fba body=e97f55c -->
[Test]
public async Task CalculatePF_FiO2_0_Not_Returns_PaO2_FiO2()
{
var patientId = ObjectId.GenerateNewId();
var observation = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "PaO2_Tidal",
Value = 98
};
var obsLast = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "FiO2",
Value = 0
};
var obsCalculate = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "Sattc_FiO2",
CodingSystem = "ADAS"
};
_observationServiceMock
.Setup(l => l.FindLastObservations(It.IsAny<ObjectId>(), It.IsAny<int>(), It.IsAny<List<string>>()))
.ReturnsAsync([obsLast]);
await _calculatedObservations.Map(observation, false);
_observationServiceMock.Verify(o => o.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Name == obsCalculate.Name && arg.PatientId == patientId
&& arg.CodingSystem == obsCalculate.CodingSystem
), true, true), Times.Never);
}
/// <summary>
/// Verifies that when patient observations include a low SpO2 (Sattc) value of 50 and a low FC value of 50, the calculated observations processing triggers a BlueCode alarm by inserting the observation and sending the alarm.
/// </summary>
/// <!-- aidoc:v1 sig=cb9af03 body=d68c56c -->
[Test]
public async Task
SendAlarm_BlueCode_FC_SpO2_Alarm_True_Returns_SendAlarm_BlueCode()
{
var patientId = ObjectId.GenerateNewId();
var now = DateTime.Now;
var obsSattc = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "Sattc",
Value = 50,
Time = now
};
var obsFc = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Value = "50",
Name = "FC",
Time = now
};
var listObservation = new List<PatientObservation?>
{
obsSattc, obsFc
};
await _calculatedObservations.CalculateBlueCodeList(listObservation);
_observationServiceMock.Verify(o => o.InsertObservation(It.IsAny<PatientObservation>(), true, true),
Times.Once);
_alarmServiceMock.Verify(
a => a.SendAlarm(It.IsAny<PatientObservation>(), "BlueCode", AlarmEnum.Name.Blue, AlarmEnum.Severity.None,
AlarmEnum.Type.Auto), Times.Once);
}
/// <summary>
/// Verifies that when a BlueCode alarm condition is triggered by FC and TAm observations, the calculated blue code list is generated, the observation is inserted, and the blue code alarm is sent with the expected severity and type.
/// </summary>
/// <returns>A task that completes when the blue code alarm verification has been executed.</returns>
/// <!-- aidoc:v1 sig=8d996ea body=861269c -->
[Test]
public async Task
SendAlarm_BlueCode_FC_TAm_Alarm_True_Returns_SendAlarm_BlueCode()
{
var patientId = ObjectId.GenerateNewId();
var now = DateTime.Now;
var obsFc = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Value = "50",
Name = "FC",
Time = now
};
var obsTAm1 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "TAm",
Value = 100,
Time = now.AddSeconds(-5)
};
var obsTAm2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "TAm",
Value = 50,
Time = now
};
var listObservation = new List<PatientObservation?>
{
obsFc, obsTAm2
};
var listTAmObs = new List<PatientObservation>
{
obsTAm1
};
_observationServiceMock.Setup(l => l.FindLastObservations(patientId, 1, _pressBloodArteryMean))
.ReturnsAsync(listTAmObs);
await _calculatedObservations.CalculateBlueCodeList(listObservation);
_observationServiceMock.Verify(o => o.InsertObservation(It.IsAny<PatientObservation>(), true, true),
Times.Once);
_alarmServiceMock.Verify(
a => a.SendAlarm(It.IsAny<PatientObservation>(), "BlueCode", AlarmEnum.Name.Blue, AlarmEnum.Severity.None,
AlarmEnum.Type.Auto), Times.Once);
}
/// <summary>
/// Verifies that a BlueCode alarm is not triggered when the heart rate (FC) is at 50 and the mean arterial pressure (TAm) values do not meet the BlueCode criteria.
/// </summary>
/// <!-- aidoc:v1 sig=593d4af body=9dce27f -->
[Test]
public async Task SendAlarm_BlueCode_FC_TAm_Alarm_False()
{
var patientId = ObjectId.GenerateNewId();
var now = DateTime.Now;
var obsFc = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Value = "50",
Name = "FC",
Time = now
};
var obsTAm1 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "TAm",
Value = 100,
Time = now.AddSeconds(-5)
};
var obsTAm2 = new PatientObservation
{
Id = ObjectId.GenerateNewId(),
PatientId = patientId,
Name = "TAm",
Value = 80,
Time = now
};
var listObservation = new List<PatientObservation?>
{
obsFc, obsTAm2
};
var listTAmObs = new List<PatientObservation>
{
obsTAm1
};
_observationServiceMock.Setup(l => l.FindLastObservations(patientId, 1, _pressBloodArteryMean))
.ReturnsAsync(listTAmObs);
await _calculatedObservations.CalculateBlueCodeList(listObservation);
_observationServiceMock.Verify(o => o.InsertObservation(It.IsAny<PatientObservation>(), true, true),
Times.Never);
_alarmServiceMock.Verify(
a => a.SendAlarm(It.IsAny<PatientObservation>(), "BlueCode", AlarmEnum.Name.Blue, AlarmEnum.Severity.None,
AlarmEnum.Type.Auto), Times.Never);
}
/// <summary>
/// Attempts to parse the string representation of the specified object as a <see cref="double"/>.
/// Returns <see langword="null"/> when the value cannot be parsed as a valid double.
/// </summary>
/// <param name="value">The object whose string representation will be converted to a double.</param>
/// <returns>The parsed <see cref="double"/> value if the conversion succeeds; otherwise, <see langword="null"/>.</returns>
/// <!-- aidoc:v1 sig=a1cea6b body=2180954 -->
private static double? TryparseDouble(object value)
{
return double.TryParse(value.ToString(), out var valueParsed) ? valueParsed : null;
}
/// <summary>
/// Verifies that mapping a <see cref="PumpObservation"/> with a null drug name and <see cref="PumpEnum.AlarmType.Occlusion"/> results in an inserted position name formatted as "Rack 1 Bomba 2".
/// </summary>
/// <!-- aidoc:v1 sig=23bca88 body=2889a88 -->
[Test]
public async Task Map_PumpObservation_DrugName_Null_AlarmType_Occlusion_Return_Insert_Pump_Insert_PositionName()
{
var pumpObservation = new PumpObservation
{
Code = "Tile-6",
Time = Now,
Name = "g-1-pump-Tile-6",
Number = 2,
Total = 7,
TotalAux = 0,
Status = PumpEnum.Status.Alarm,
PumpMode = PumpEnum.Mode.Unknown,
InfusingStatus = PumpEnum.InfusingStatus.Unknown,
Pressure = new CommonPumpTypes.PumpValue(),
//drugName = "Nutrición Parenteral",
Concentration = new CommonPumpTypes.PumpValue(),
DrugAmount = new CommonPumpTypes.PumpValue(),
DiluentVolume = new CommonPumpTypes.PumpValue(),
DoseRate = new CommonPumpTypes.PumpValue(),
Rate = new CommonPumpTypes.PumpValue(),
VolumeInfused = new CommonPumpTypes.PumpValue
{
Value = 0.00001
},
VolumeRemaining = new CommonPumpTypes.PumpValue
{
Value = 0.00001
},
TimeRemaining = new CommonPumpTypes.PumpValue
{
Value = 1441,
Units = "min"
},
PatientWeight = new CommonPumpTypes.PumpValue(),
AlarmType = PumpEnum.AlarmType.Occlusion,
AlarmMode = PumpEnum.AlarmMode.Hight,
GatewayNumber = 1,
IsAux = false,
IsInfusing = false,
Expires = 100
};
await _calculatedObservations.Map(pumpObservation);
_observationServiceMock.Verify(d => d.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Value.ToString() == "Rack 1 Bomba 2"), true, true));
}
/// <summary>
/// Verifies that mapping a <see cref="PumpObservation"/> with a null drug name, <see cref="PumpEnum.AlarmType.Occlusion"/> alarm, and <see cref="PumpObservation.IsAux"/> set to true produces an insertion of the main pump observation and an auxiliary observation with a position name formatted as "Rack Aux {GatewayNumber} Bomba {Number}".
/// </summary>
/// <!-- aidoc:v1 sig=6ae491c body=5178203 -->
[Test]
public async Task
Map_PumpObservation_DrugName_Null_AlarmType_Occlusion_Return_Insert_Pump_Insert_Aux_PositionName()
{
var pumpObservation = new PumpObservation
{
Code = "Tile-6",
Time = Now,
Name = "g-1-pump-Tile-6",
Number = 2,
Total = 7,
TotalAux = 0,
Status = PumpEnum.Status.Alarm,
PumpMode = PumpEnum.Mode.Unknown,
InfusingStatus = PumpEnum.InfusingStatus.Unknown,
Pressure = new CommonPumpTypes.PumpValue(),
//drugName = "Nutrición Parenteral",
Concentration = new CommonPumpTypes.PumpValue(),
DrugAmount = new CommonPumpTypes.PumpValue(),
DiluentVolume = new CommonPumpTypes.PumpValue(),
DoseRate = new CommonPumpTypes.PumpValue(),
Rate = new CommonPumpTypes.PumpValue(),
VolumeInfused = new CommonPumpTypes.PumpValue
{
Value = 0.00001
},
VolumeRemaining = new CommonPumpTypes.PumpValue
{
Value = 0.00001
},
TimeRemaining = new CommonPumpTypes.PumpValue
{
Value = 1441,
Units = "min"
},
PatientWeight = new CommonPumpTypes.PumpValue(),
AlarmType = PumpEnum.AlarmType.Occlusion,
AlarmMode = PumpEnum.AlarmMode.Hight,
GatewayNumber = 1,
IsAux = true,
IsInfusing = false,
Expires = 100
};
await _calculatedObservations.Map(pumpObservation);
_observationServiceMock.Verify(d => d.InsertObservation(It.Is<PatientObservation>(arg =>
arg.Value.ToString() == "Rack Aux 1 Bomba 2"), true, true));
}
/// <summary>
/// Verifies that a <see cref="PatientObservation"/> representing a pump volumetric air occlusion alarm is correctly mapped by the calculated observations mapper, returning a non-null result with a matching name.
/// </summary>
/// <!-- aidoc:v1 sig=6fdcb6b body=3319cdd -->
[Test]
public async Task Map_PatientObservation_Alarm_Pump_Retur_obs()
{
PatientObservation patientObservation = new()
{
CodingSystem = "ADAS_ALARM",
Code = "Pump_VolumetricAirOclusion",
Name = "Alarm_Pump_VolumetricAirOclusion",
Value = "Rack 1 Bomba 1",
PatientId = PatientId,
Time = Now
};
var result = await _calculatedObservations.Map(patientObservation, false);
Assert.That(result, Is.Not.Null);
Assert.That(result!.Name, Is.EqualTo(patientObservation.Name));
}
}