using adas_core.Application.Customizations.H12O.UCIN; using adas_core.Application.Services.Interfaces; using adas_core.Domain.Enums; using adas_core.Domain.Models; using adas_core.Domain.Models.AppSettings; 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.H12O.UCIN; /// /// Represents a test fixture that contains unit tests for calculated observations, executing with an order priority of 2 relative to other test fixtures. /// /// /// This fixture is annotated with to mark it as a container of NUnit test methods, and with to control its execution sequence within the test suite. /// /// [TestFixture] [Order(2)] public class CalculatedObservationsTest { /// /// Initializes the test fixture for by creating mocked instances of /// , , , /// , and , configuring /// settings for medication bolus, transcutaneous, regional brain saturation, /// electroencephalogram, respiratory, high-frequency ventilation, invasive ventilation, non-invasive /// ventilation, one-lung isolation, and ECMO codes, and registering all dependencies in a /// so that a fully wired instance /// is produced for each test. /// /// [SetUp] public void Setup() { _observationServiceMock = new Mock(); _configOservationServiceMock = new Mock(); _medicineServiceMock = new Mock(); _treatmentServiceMock = new Mock(); _logger = new Mock>(); _optionsApiSettings = Options.Create(_apiSettings); _optionsApiSettings.Value.MedicationBolus = ["18851000140100", "21011000140105"]; _optionsApiSettings.Value.IntravenousLinesCode = ["10546003"]; _optionsApiSettings.Value.Transcutaneous = ["151756", "151760"]; _optionsApiSettings.Value.RegionalBrainSaturation = ["194908", "194909"]; _optionsApiSettings.Value.Electroencephalogram = ["42803009"]; _optionsApiSettings.Value.Respiratory = ["361110005", "84481000140102"]; _optionsApiSettings.Value.HighFrequencyVentilation = ["PC-HFO"]; _optionsApiSettings.Value.InvasiveVentilation = [ "A/C (S.I.P.P.V. )", "A/C (S.I.P.P.V.) + V.G.", "PRVC", "PC-SIMV", "SIMV-PRVC", "PC-AC", "SIMV", "SIMV-PC", "S.I.M.V.", "PC-CMV", "SIPPV", "PC" ]; _optionsApiSettings.Value.NonInvasiveVentilation = ["DUOPAP", "NCPAP"]; _optionsApiSettings.Value.Oni = ["84481000140102", "416362002"]; _optionsApiSettings.Value.Ecmo = ["705923009"]; var serviceCollection = new ServiceCollection(); //serviceCollection.AddSingleton(_observationServiceMock.Object); serviceCollection.AddSingleton(new Lazy(() => _observationServiceMock.Object)); serviceCollection.AddSingleton( new Lazy(() => _configOservationServiceMock.Object)); serviceCollection.AddSingleton(_medicineServiceMock.Object); serviceCollection.AddSingleton(new Lazy(() => _treatmentServiceMock.Object)); serviceCollection.AddSingleton(_optionsApiSettings); serviceCollection.AddSingleton(_logger.Object); var serviceProvider = serviceCollection.BuildServiceProvider(); _calculatedObservations = new CalculatedObservations(serviceProvider); } private CalculatedObservations _calculatedObservations; private Mock _medicineServiceMock; private Mock _observationServiceMock; private Mock _configOservationServiceMock; private Mock _treatmentServiceMock; private Mock> _logger; private readonly ApiSettings _apiSettings = new() { ConfigObservation = new ConfigObservationSettings { IgnoreUnknownObservation = false } }; private IOptions _optionsApiSettings; /// /// Verifies that processing a new that contains a medicine—matched by code to a known with an assigned —for the first time for a patient (no prior observations and no active treatments) results in a named Medication with value 1 associated to the treatment's . /// /// [Test] public async Task Calculate_First_Medicine_Observation_With_Type_Should_Return_1() { //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1 var patientId = ObjectId.GenerateNewId(); var treatment = new PatientTreatment { Id = ObjectId.GenerateNewId(), PatientId = patientId, OrderControl = OrderControlType.Nw, PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, RequestedGiveCodes = [new Code { Identifier = "12345" }], OrderStatus = "A", OrderTime = DateTime.Now, Notes = [], Routes = [] }; var medicine = new Medicine { Codes = ["12345"], Group = [MedicineEnum.Group.DoubleSignature.ToString()], Type = [MedicineEnum.Types.MuscleRelaxant.ToString()], Name = "cisataracurio" }; _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List { "12345" })) .ReturnsAsync([medicine]); _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny(), true, true)); _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId)) .ReturnsAsync(new List().AsEnumerable()); _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny>())) .ReturnsAsync(new List().AsEnumerable()); await _calculatedObservations.Map(treatment); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Medication" && (int)arg.Value == 1 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that mapping a new containing a medicine, when no prior /// observations or active treatments exist for the patient, results in the insertion of a /// named "Medication" with value 0 for the patient. /// /// [Test] public async Task Calculate_First_Medicine_Observation_With_Out_Type_Should_Return_1() { //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1 var patientId = ObjectId.GenerateNewId(); var treatment = new PatientTreatment { Id = ObjectId.GenerateNewId(), PatientId = patientId, OrderControl = OrderControlType.Nw, PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, RequestedGiveCodes = [new Code { Identifier = "12345" }], OrderStatus = "A", OrderTime = DateTime.Now, Notes = [], Routes = [] }; var medicine = new Medicine { Codes = ["12345"], Group = [MedicineEnum.Group.DoubleSignature.ToString()], Name = "cisataracurio" }; _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List { "12345" })) .ReturnsAsync([medicine]); _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny(), true, true)); _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId)) .ReturnsAsync(new List().AsEnumerable()); _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny>())) .ReturnsAsync(new List().AsEnumerable()); await _calculatedObservations.Map(treatment); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Medication" && (int)arg.Value == 0 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that when a new with an OrderControl of is mapped for the first time and contains a medicine code, a with name Medication and value 1 is inserted for the patient. /// /// [Test] public async Task Calculate__Medicine_Observation_New_Type_Should_Sum_1() { //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1 var patientId = ObjectId.GenerateNewId(); var treatment = new PatientTreatment { Id = ObjectId.GenerateNewId(), PatientId = patientId, OrderControl = OrderControlType.Nw, PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, RequestedGiveCodes = [new Code { Identifier = "12345" }], OrderStatus = "A", OrderTime = DateTime.Now, Notes = [], Routes = [] }; var medicine = new Medicine { Codes = ["12345"], Group = [MedicineEnum.Group.DoubleSignature.ToString()], Name = "cisataracurio", Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()] }; _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId)) .ReturnsAsync(new List().AsEnumerable()); _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List { "12345" })) .ReturnsAsync([medicine]); _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny>())) .ReturnsAsync(new List().AsEnumerable()); _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny(), true, true)); _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.Map(treatment); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Medication" && (int)arg.Value == 1 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that when a new is mapped and a prior of name "Medication" with value 0 already exists for the patient, the calculated observations service inserts a new observation with value 1 (the sum of the existing value 0 plus the new contribution). /// /// [Test] public async Task Calculate__Medicine_Observation_Type_Already_Exists_Should_Sum_0() { //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1 var patientId = ObjectId.GenerateNewId(); var treatment = new PatientTreatment { Id = ObjectId.GenerateNewId(), PatientId = patientId, OrderControl = OrderControlType.Nw, PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, RequestedGiveCodes = [new Code { Identifier = "12345" }], OrderStatus = "A", OrderTime = DateTime.Now, Notes = [], Routes = [] }; var medicine = new Medicine { Codes = ["12345"], Group = [MedicineEnum.Group.DoubleSignature.ToString()], Name = "cisataracurio", Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()] }; var activeMedicines = new List { new() { Codes = ["12345"], Group = [MedicineEnum.Group.DoubleSignature.ToString()], Name = "Biotin", Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()] } }; _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId)) .ReturnsAsync(new List().AsEnumerable()); _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List { "12345" })) .ReturnsAsync([medicine]); _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny>())) .ReturnsAsync(activeMedicines.AsEnumerable()); _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny(), true, true)); _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([ new PatientObservation { PatientId = patientId, Value = 0, Name = "Medication" } ]); await _calculatedObservations.Map(treatment); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Medication" && (int)arg.Value == 1 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that when a medicine observation of type already exists for the patient, /// subtracts the existing value and inserts a new observation with a resulting value of 0. /// /// A representing the asynchronous unit test execution. /// [Test] public async Task Calculate__Medicine_Observation_DC_Type_Already_Exists_Should_Subtract_0() { var patientId = ObjectId.GenerateNewId(); var treatment = new PatientTreatment { Id = ObjectId.GenerateNewId(), PatientId = patientId, OrderControl = OrderControlType.Dc, PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, RequestedGiveCodes = [new Code { Identifier = "12345" }], OrderStatus = "A", OrderTime = DateTime.Now, Notes = [], Routes = [] }; var medicine = new Medicine { Codes = ["12345"], Group = [MedicineEnum.Group.DoubleSignature.ToString()], Name = "cisataracurio", Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()] }; var activeMedicines = new List { new() { Codes = ["12345"], Group = [MedicineEnum.Group.DoubleSignature.ToString()], Name = "cisataracurio", Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()] } }; _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId)) .ReturnsAsync(new List().AsEnumerable()); _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List { "12345" })) .ReturnsAsync([medicine]); _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny>())) .ReturnsAsync(activeMedicines.AsEnumerable()); _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny(), true, true)); _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([ new PatientObservation(patientId, 1, "Medication") ]); await _calculatedObservations.Map(treatment); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "ERMedication" && (int)arg.Value == 0 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that when a treatment is processed and the patient has two active medicines, a Medication observation is inserted with the last observation value decremented by one (2 - 1 = 1). /// /// [Test] public async Task Calculate__Medicine_Observation_DC_OF_TYPE_WITH_TWO_MEDICINES_Should_Subtract_0() { //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1 var patientId = ObjectId.GenerateNewId(); var treatment = new PatientTreatment { Id = ObjectId.GenerateNewId(), PatientId = patientId, OrderControl = OrderControlType.Dc, PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, RequestedGiveCodes = [new Code { Identifier = "12345" }], OrderStatus = "A", OrderTime = DateTime.Now, Notes = [], Routes = [] }; var medicine = new Medicine { Codes = ["12345"], Group = [MedicineEnum.Group.DoubleSignature.ToString()], Name = "cisataracurio", Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()] }; var activeMedicines = new List { new() { Codes = ["12345"], Name = "cisataracurio", Group = [MedicineEnum.Group.DoubleSignature.ToString()], Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()] }, new() { Codes = ["12345"], Name = "Lipoic acid", Group = [MedicineEnum.Group.DoubleSignature.ToString()], Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()] } }; _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId)) .ReturnsAsync(new List().AsEnumerable()); _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List { "12345" })) .ReturnsAsync([medicine]); _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny>())) .ReturnsAsync(activeMedicines.AsEnumerable()); _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny(), true, false)); _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([ new PatientObservation { PatientId = patientId, Value = 2, Name = "Medication" } ]); //_observationServiceMock.Setup(o => o.InsertObservation(It.Is(arg => // (arg.Name == "ERMedication" && (int)arg.Value == 1) // && arg.PatientId == patientId //), true, true)); await _calculatedObservations.Map(treatment); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Medication" && (int)arg.Value == 1 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that mapping a new containing a medicine without a defined type results in the insertion of a named "Medication" with a value of 1 for the associated patient. /// /// [Test] public async Task Calculate_Medicine_Observation_New_Medicine_Without_Type_Should_Insert_Medication_1_point() { //Entra un tratamiento por primera vez con una medicina, se crea una observación medication con valor 1 var patientId = ObjectId.GenerateNewId(); var treatment = new PatientTreatment { Id = ObjectId.GenerateNewId(), PatientId = patientId, OrderControl = OrderControlType.Nw, PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, RequestedGiveCodes = [new Code { Identifier = "12345" }], OrderStatus = "A", OrderTime = DateTime.Now, Notes = [], Routes = [] }; var medicine = new Medicine { Codes = ["12345"], Name = "Betaine" }; var activeMedicines = new List { new() { Codes = ["12345"], Name = "cisataracurio", Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()] }, new() { Codes = ["12345"], Name = "Lipoic acid", Type = [MedicineEnum.Types.AdrenalineNoradrenaline.ToString()] } }; var expectedMedication = new PatientObservation { PatientId = patientId, Value = 0, Name = "Medication" }; _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId)) .ReturnsAsync(new List().AsEnumerable()); _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List { "12345" })) .ReturnsAsync([medicine]); _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny>())) .ReturnsAsync(activeMedicines.AsEnumerable()); _observationServiceMock.Setup(o => o.InsertObservation(It.IsAny(), true, true)); _observationServiceMock.Setup(o => o.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([expectedMedication]); await _calculatedObservations.Map(treatment); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Medication" && (int)arg.Value == 1 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that . inserts a new /// observation with a score of 5 when processing the first /// intravenous arterial observation for a patient, given that no previous observations exist. /// /// [Test] public async Task Calculate_First_Intravenous_Arterial_Observation_Should_Return_5() { var patientId = ObjectId.GenerateNewId(); var obs = new PatientObservation { PatientId = patientId, Value = new PatientIntravenousLinesValue { Action = "Insert", Duration = "7", InsertTime = DateTime.Now, Location = "Rodilla", Type = "Catéter arterial" }, Name = "IntravenousLinesObs" }; _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId)) .ReturnsAsync([]); await _calculatedObservations.Map(obs, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "IntravenousLines" && (int)arg.Value == 5 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that when a previous for the same patient and location has already been removed, the intravenous calculation performed by produces a result of 0. /// /// [Test] public async Task Calculate_Intravenous_Obs_Already_Exist_Removed_Should_Return_0() { var patientId = ObjectId.GenerateNewId(); var now = DateTime.Now; var obs = new PatientObservation { PatientId = patientId, Value = new PatientIntravenousLinesValue { Action = "Insert", Duration = "7", InsertTime = now, Location = "Rodilla", Type = "Catéter arterial", RemoveTime = DateTime.Now.AddDays(1) }, Name = "IntravenousLinesObs" }; _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId)) .ReturnsAsync([]); _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([ new PatientObservation { PatientId = patientId, Value = new PatientIntravenousLinesValue { Action = "Insert", Duration = "7", InsertTime = now, Type = "Catéter arterial", Location = "Rodilla" }, Name = "IntravenousLinesObs" } ]); await _calculatedObservations.Map(obs, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "IntravenousLines" && (int)arg.Value == 0 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that mapping a with an whose type and location match the last stored observation for the same patient does not trigger an insertion of a calculated "IntravenousLines" observation. /// /// [Test] public async Task Calculate_Intravenous_two_observations_of_same_type_and_same_location_should_return_null() { var patientId = ObjectId.GenerateNewId(); var now = DateTime.Now; var obs = new PatientObservation { PatientId = patientId, Name = "IntravenousLinesObs", Value = new PatientIntravenousLinesValue { Action = "Insertado", Duration = "7", InsertTime = now, Location = "Rodilla", Type = "Catéter arterial" } }; _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId)) .ReturnsAsync([ new PatientObservation { PatientId = patientId, Value = new PatientIntravenousLinesValue { Action = "Insertado", Duration = "7", InsertTime = now, Type = "Catéter arterial", Location = "Rodilla" }, Name = "IntravenousLinesObs" } ]); await _calculatedObservations.Map(obs, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "IntravenousLines" && (int)arg.Value == 5 && arg.PatientId == patientId ), true, true), Times.Never); } /// /// Verifies that when a new PatientObservation of type "IntravenousLinesObs" is processed alongside a previous observation of the same type for the same patient, the calculator produces a derived PatientObservation named "IntravenousLines" with a value of 10. /// /// [Test] public async Task Calculate_Intravenous_two_observations_of_same_type_should_return_10() { var patientId = ObjectId.GenerateNewId(); var now = DateTime.Now; var obs = new PatientObservation { PatientId = patientId, Name = "IntravenousLinesObs", Value = new PatientIntravenousLinesValue { Action = "Insertado", Duration = "7", InsertTime = now, Location = "Rodilla", Type = "Catéter arterial" } }; _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId)) .ReturnsAsync([ new PatientObservation { PatientId = patientId, Name = "IntravenousLinesObs", Value = new PatientIntravenousLinesValue { Action = "Insertado", Duration = "7", InsertTime = now, Type = "Catéter arterial", Location = "Codo" } } ]); _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.Map(obs, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "IntravenousLines" && (int)arg.Value == 10 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that the method limits the calculated sum of observations to a maximum value of ten when the total exceeds that threshold. /// /// [Test] public async Task Calculate_Intravenous_sum_more_than_10_should_limit_to_ten() { var patientId = ObjectId.GenerateNewId(); var now = DateTime.Now; var obs = new PatientObservation { PatientId = patientId, Value = new PatientIntravenousLinesValue { Action = "Insertado", Duration = "7", InsertTime = now, Location = "Rodilla Izd.", Type = "Catéter arterial" }, Name = "IntravenousLinesObs" }; var patientObservations = new List { new() { PatientId = patientId, Name = "IntravenousLinesObs", Value = new PatientIntravenousLinesValue { Action = "Insertado", Duration = "7", InsertTime = now, Type = "Catéter arterial", Location = "Rodilla Der." } }, new() { PatientId = patientId, Name = "IntravenousLinesObs", Value = new PatientIntravenousLinesValue { Action = "Insertado", Duration = "7", InsertTime = now, Type = "Catéter PICC", Location = "Brazo" } } }; _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId)) .ReturnsAsync(patientObservations); _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.Map(obs, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "IntravenousLines" && (int)arg.Value == 10 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that mapping a new with a "Catéter línea media" type, when two prior intravenous lines exist (one "Catéter EPICUTÁNEO PERIFÉRICO" and one "Catéter Venoso PERIFÉRICO"), inserts an named "IntravenousLines" with a summed value of 5 for the given . /// /// [Test] public async Task Calculate_Intravenous_sum_one_middle_line_and_two_Peripheral_should_return_5() { var patientId = ObjectId.GenerateNewId(); var now = DateTime.Now; var obs = new PatientObservation { PatientId = patientId, Value = new PatientIntravenousLinesValue { Action = "Insertado", Duration = "7", InsertTime = now, Location = "Rodilla Izd.", Type = "Catéter línea media" }, Name = "IntravenousLinesObs" }; _observationServiceMock.Setup(t => t.FindLastIntravenousLinesObservationByLocation(patientId)) .ReturnsAsync([ new PatientObservation { PatientId = patientId, Name = "IntravenousLinesObs", Value = new PatientIntravenousLinesValue { Action = "Insertado", Duration = "7", InsertTime = now, Type = "Catéter EPICUTÁNEO PERIFÉRICO", Location = "Rodilla Der." } }, new PatientObservation { PatientId = patientId, Name = "IntravenousLinesObs", Value = new PatientIntravenousLinesValue { Action = "Insertado", Duration = "7", InsertTime = now, Type = "Catéter Venoso PERIFÉRICO", Location = "Brazo" } } ]); _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.Map(obs, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "IntravenousLines" && (int)arg.Value == 5 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that . produces a monitor observation with value 3 for a treatment containing the EEG code 42803009, based on the most recent transcutaneous and regional brain saturation observations retrieved for the patient. /// /// [Test] public async Task Calculate_Monitor_Transcuatenous_Regional_Brain_Saturation_and_enter_EEG_should_return_3() { var patientId = ObjectId.GenerateNewId(); var treatment = new PatientTreatment { Id = ObjectId.GenerateNewId(), PatientId = patientId, OrderControl = OrderControlType.Nw, PlacerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, FillerOrder = new Entity { EntityIdentifier = "100", NamespaceId = "CareVue" }, RequestedGiveCodes = [new Code { Identifier = "42803009" }], OrderStatus = "NW", OrderTime = DateTime.Now, Notes = [], Routes = [] }; _treatmentServiceMock.Setup(t => t.GetActiveTreatmentsByPatient(patientId)) .ReturnsAsync(new List().AsEnumerable()); _medicineServiceMock.Setup(m => m.GetByCodeOrNote(new List { "42803009" })) .ReturnsAsync([]); _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([ new PatientObservation { PatientId = patientId, Code = "151756", Name = "Transcutaneous", Time = DateTime.Now }, new PatientObservation { PatientId = patientId, Code = "151760", Name = "Transcutaneous", Time = DateTime.Now }, new PatientObservation { PatientId = patientId, Code = "194908", Name = "RegionalBrainSaturation", Time = DateTime.Now }, new PatientObservation { PatientId = patientId, Code = "194909", Name = "RegionalBrainSaturation", Time = DateTime.Now } ]); await _calculatedObservations.Map(treatment); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Monitor" && (int)arg.Value == 3 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that mapping a ventilation with value OXIDO NITRICO 800 PPM MOL for a patient with no prior observations produces a derived named "Respiratory" with an integer value of 10. /// /// [Test] public async Task Calculate_Respiratory_INO_should_return_10() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Value = "OXIDO NITRICO 800 PPM MOL", Code = "84481000140102", Name = "Tipo de ventilación", CodingSystem = "SNM" }; _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.Map(observation, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Respiratory" && (int)arg.Value == 10 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that calculates a respiratory value of 5 when the patient observation /// represents a "V.A.F.O." (ventilación de alta frecuencia oscilatoria) entry coded as 361110005 in the SNM coding system, /// using an empty list returned by . /// /// A that completes when the assertions have been executed. /// [Test] public async Task Calculate_Respiratory_VAFO_should_return_5() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Value = "V.A.F.O.", Code = "361110005", Name = "Tipo de ventilación", CodingSystem = "SNM" }; _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.Map(observation, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Respiratory" && (int)arg.Value == 5 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that mapping a with value "V.M.C." (ventilation type, SNOMED code "361110005") produces a calculated respiratory observation with value 3 for the same , when no previous observations are returned by the observation service. /// /// [Test] public async Task Calculate_Respiratory_VMC_should_return_3() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Value = "V.M.C.", Code = "361110005", Name = "Tipo de ventilación", CodingSystem = "SNM" }; _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.Map(observation, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Respiratory" && (int)arg.Value == 3 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that mapping a with the ventilation type V.N.I. Ciclada (Non-Invasive Mechanical Ventilation) results in the insertion of a calculated respiratory observation with an integer value of 2 for the same patient. /// /// [Test] public async Task Calculate_Respiratory_VMNI_should_return_2() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Value = "V.N.I. Ciclada", Code = "361110005", Name = "Tipo de ventilación", CodingSystem = "SNM" }; _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.Map(observation, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Respiratory" && (int)arg.Value == 2 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that when a with name "Tipo de ventilación" and value "Bajo Flujo" is mapped, a calculated respiratory observation is inserted with value 1 for the associated patient. /// /// [Test] public async Task Calculate_Respiratory_Nassal_Canulas_Bajo_Flujo_should_return_2() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Value = "Bajo Flujo", Code = "361110005", Name = "Tipo de ventilación", CodingSystem = "SNM" }; _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.Map(observation, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Respiratory" && (int)arg.Value == 1 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that returns a respiratory value of 1 when the patient observation indicates an "Alto Flujo" (high flow nasal cannula) ventilation type, identified by "361110005" in the SNM coding system. /// /// [Test] public async Task Calculate_Respiratory_Nassal_Canulas_Alto_Flujo_should_return_1() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Value = "Alto Flujo", Code = "361110005", Name = "Tipo de ventilación", CodingSystem = "SNM" }; _observationServiceMock.Setup(t => t.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.Map(observation, false); _observationServiceMock.Verify(o => o.InsertObservation(It.Is(arg => arg.Name == "Respiratory" && (int)arg.Value == 1 && arg.PatientId == patientId ), true, false)); } /// /// Verifies that mapping a with the name "Resp_Mode" and the value "PC-AC" /// produces a calculated observation for "Resp_Type" using the "ADAS" coding system with the /// value. /// /// [Test] public async Task Calculate_Ventilation_Mode_Returns_INVASIVE() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Value = "PC-AC", Name = "Resp_Mode" }; await _calculatedObservations.Map(observation, false); _observationServiceMock.Verify(o => o.InsertIfChanged("Resp_Type", It.Is(arg => arg.Name == "Resp_Type" && arg.CodingSystem == "ADAS" && arg.Value.ToString() == RespirationType.Invasive.ToString() ), true, true)); } /// /// Verifies that mapping a with the name Resp_Mode and value DUOPAP triggers an insert of a new observation named Resp_Type using the value. /// /// [Test] public async Task Calculate_Ventilation_Mode_Returns_NON_INVASIVE() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Value = "DUOPAP", Name = "Resp_Mode" }; await _calculatedObservations.Map(observation, false); _observationServiceMock.Verify(o => o.InsertIfChanged("Resp_Type", It.Is(arg => arg.Name == "Resp_Type" && arg.CodingSystem == "ADAS" && arg.Value.ToString() == RespirationType.NonInvasive.ToString() ), true, true)); } /// /// Verifies that mapping a with the Resp_Mode name and the PC-HFO value produces a calculated observation named Resp_Type using the ADAS coding system whose value resolves to . /// /// [Test] public async Task Calculate_Ventilation_Mode_Returns_HIGH_FREQUENCY() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Value = "PC-HFO", Name = "Resp_Mode" }; await _calculatedObservations.Map(observation, false); _observationServiceMock.Verify(o => o.InsertIfChanged("Resp_Type", It.Is(arg => arg.Name == "Resp_Type" && arg.CodingSystem == "ADAS" && arg.Value.ToString() == RespirationType.HighFrequencyVentilation.ToString() ), true, true)); } /// /// Verifies that when a with "Resp_Mode" and "VENTAPNEA" is mapped, the calculated observation for "Resp_Type" is produced with using the "ADAS" coding system. /// /// A representing the asynchronous test execution. /// [Test] public async Task Calculate_Ventilation_Mode_Returns_NONE() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Value = "VENTAPNEA", Name = "Resp_Mode" }; await _calculatedObservations.Map(observation, false); _observationServiceMock.Verify(o => o.InsertIfChanged("Resp_Type", It.Is(arg => arg.Name == "Resp_Type" && arg.CodingSystem == "ADAS" && arg.Value.ToString() == RespirationType.None.ToString() ), true, true)); } /// /// Verifies that CalculateOxygenationIndex retrieves the latest AirPressure_Mean, FiO2, and PaO2 /// values for the patient via FindLastObservations and inserts a new /// named "Oxygenation_Index" with the correctly computed value of 1250. /// /// [Test] public async Task CalculateOxygenationIndex_ShouldInsertCorrectObservation() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { PatientId = patientId, Name = "FiO2", Value = 50 }; var observations = new List { new() { Name = "AirPressure_Mean", Value = 20, PatientId = patientId }, new() { Name = "FiO2", Value = 50, PatientId = patientId }, new() { Name = "PaO2", Value = 80, PatientId = patientId } }; _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync(observations); await _calculatedObservations.CalculateOxygenationIndex(observation); _observationServiceMock.Verify(s => s.InsertObservation( It.Is(o => o.Name == "Oxygenation_Index" && o.PatientId == patientId && (int)o.Value == 1250), It.IsAny(), It.IsAny())); } /// /// Verifies that inserts a new /// with the name Respiratory for the patient when the most recent /// retrieved observation matches the expected respiratory mode (Resp_Mode), and returns the /// original . /// /// [Test] public async Task CalculateAsistResp_ShouldUpdateObservation_WhenConditionsMet() { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { PatientId = patientId, Name = "ONi", Value = "valor", Time = DateTime.Now, Code = "codigo" }; var lastAsistResp = new PatientObservation { PatientId = patientId, Name = "Resp_Mode", Value = "valor", Time = DateTime.Now.AddMinutes(-10) }; _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([lastAsistResp]); var result = await _calculatedObservations.CalculateAsistResp(observation); _observationServiceMock.Verify(s => s.InsertObservation( It.Is(o => o.Name == "Respiratory" && o.PatientId == patientId), It.IsAny(), It.IsAny())); Assert.That(result, Is.EqualTo(observation)); } // [TestCase("valorHFV", RespirationType.HIGH_FREQUENCY_VENTILATION)] // [TestCase("valorInvasive", RespirationType.INVASIVE)] // [TestCase("valorNonInvasive", RespirationType.NON_INVASIVE)] // [TestCase("valorNone", RespirationType.NONE)] /// /// Verifies that maps the supplied input value to the expected and persists it as a Resp_Type observation via . /// Handles the localized input cases valorHFV (mapped to PC-HFO), valorInvasive (mapped to PRVC), and valorNonInvasive (mapped to DUOPAP); any other value falls back to . /// /// The raw Resp_Mode input value from the observation; when it does not match a known ventilation label, it is replaced by . /// The expected to be inserted as Resp_Type after the calculation runs. /// public async Task CalculateVentilationMode_ShouldInsertCorrectRespType(string value, RespirationType expectedRespType) { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { PatientId = patientId, Name = "Resp_Mode", Time = DateTime.Now, Value = value switch { "valorHFV" => "PC-HFO", "valorInvasive" => "PRVC", "valorNonInvasive" => "DUOPAP", _ => expectedRespType } }; await _calculatedObservations.CalculateVentilationMode(observation); _observationServiceMock.Verify(s => s.InsertIfChanged( "Resp_Type", It.Is(o => o.PatientId == patientId && o.Name == "Resp_Type" && o.Value.ToString() == expectedRespType.ToString()), It.IsAny(), It.IsAny())); } // [TestCase("TAm", 10, 12, ObservationStatus.Ok)] // [TestCase("Age_Gestational", 1, 2, ObservationStatus.Alert)] // [TestCase("Age_Gestational", 1, 12, ObservationStatus.Ok)] // [TestCase("Age_Gestational_Fixed", 5, 10, ObservationStatus.Ok)] /// /// Verifies that the CalculateTAmAlert method updates the status of a TAm observation /// to the expected when the observation name is "TAm", and inserts a new /// TAm observation when the name is "Age_Gestational" or "Age_Gestational_Fixed". /// /// The name of the observation under test, expected to be "TAm", "Age_Gestational", or "Age_Gestational_Fixed". /// The numeric TAm value assigned to the observation and related grouped observations. /// The numeric gestational age value used in the related grouped observations. /// The expected used to assert the resulting observation status. /// public async Task CalculateTAmAlert_ShouldUpdateStatusCorrectly(string observationName, int tamValue, int gestationalAge, StatusEnum.Type expectedType) { var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { PatientId = patientId, Name = observationName, Value = tamValue, Time = DateTime.Now, Status = expectedType }; List groupedObservations = []; switch (observationName) { case "TAm": groupedObservations = [ new PatientObservation { Name = "Age_Gestational", Value = gestationalAge, PatientId = patientId, Time = DateTime.Now.AddMinutes(-10), Status = expectedType }, new PatientObservation { Name = "Age_Gestational_Fixed", Value = gestationalAge, PatientId = patientId, Time = DateTime.Now.AddMinutes(-10), Status = expectedType } ]; break; case "Age_Gestational": case "Age_Gestational_Fixed": groupedObservations = [ new PatientObservation { Name = "Age_Gestational", Value = gestationalAge, PatientId = patientId, Time = DateTime.Now.AddMinutes(-10), Status = expectedType }, new PatientObservation { Name = "TAm", Value = tamValue, PatientId = patientId, Time = DateTime.Now.AddMinutes(-10), Status = expectedType } ]; break; } _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync(groupedObservations); await _calculatedObservations.CalculateTAmAlert(observation); if (observation.Name == "TAm") Assert.That(observation.Status, Is.EqualTo(expectedType)); else _observationServiceMock.Verify(s => s.InsertObservation( It.Is(o => o.PatientId == patientId && o.Name == "TAm"), It.IsAny(), It.IsAny())); } /// /// Verifies that the ParseWeight method correctly converts the units to "gr" and scales the value (multiplying by 1000) when given a valid with a numeric . /// /// [Test] public async Task ParseWeight_WhenValidObservation_ShouldConvertUnitsAndValue() { var obs = new PatientObservation { Value = 1.23 }; var result = await _calculatedObservations.ParseWeight(obs) as PatientObservation; Assert.That(result, Is.Not.Null); Action assertions = () => { Assert.That(result!.Units, Is.EqualTo("gr")); Assert.That(result.Value, Is.EqualTo(1230)); }; Assert.Multiple(assertions); } /// /// Verifies that ParseWeight handles non-numeric gracefully by returning the original unchanged. /// /// [Test] public async Task ParseWeight_WhenValueIsNotNumeric_ShouldHandleGracefullyAndReturnOriginal() { var obs = new PatientObservation { Value = "string" }; var result = await _calculatedObservations.ParseWeight(obs); Assert.That(result, Is.EqualTo(obs)); } /// /// Verifies that the ParseWeight method returns the original unchanged when the observation cannot be converted to a PatientObservation, exercising the fallback behavior for invalid input types. /// /// [Test] public async Task ParseWeight_WhenInvalidObservation_ShouldReturnOriginal() { var obs = new BasePatientObservation(); // No es PatientObservation, por lo que no se puede convertir var result = await _calculatedObservations.ParseWeight(obs); Assert.That(result, Is.EqualTo(obs)); } /// /// Verifies that when the patient temperature and the latest incubator temperature observation are both recent, CalculateTempGradient triggers an InsertObservation call exactly once to persist the computed Temp_Gradient value (incubator minus patient temperature). /// /// [Test] public async Task CalculateTempGradient_WhenTempPatientAndTempIncubatorAreRecent_ShouldCalculateGradient() { var now = DateTime.UtcNow; var patientId = ObjectId.GenerateNewId(); var tempPatientObs = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Name = "Temp_Patient", Time = now, Value = 36.5 }; var tempIncubatorObs = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Name = "Temp_Incubator", Time = now.AddMinutes(-10), // 10 minutos antes Value = 37.0 }; var tempGradientObs = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Name = "Temp_Gradient", Time = now.AddSeconds(1), Value = 37.0 }; _observationServiceMock.Setup(s => s.FindAnyWithSameDate(patientId, now, "Temp_Gradient")) .ReturnsAsync([tempGradientObs]); _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([tempIncubatorObs]); _observationServiceMock.Setup(s => s.InsertObservation( It.IsAny(), It.IsAny(), It.IsAny() )).Callback((obs, _, _) => { Action assertions = () => { Assert.That(obs.Name, Is.EqualTo("Temp_Gradient")); Assert.That(Math.Abs((double)obs.Value - (37.0 - 36.5)), Is.LessThan(0.001)); }; }); await _calculatedObservations.CalculateTempGradient(tempPatientObs); _observationServiceMock.Verify(s => s.InsertObservation( It.IsAny(), It.IsAny(), It.IsAny() ), Times.Once()); } /// /// Verifies that the temperature gradient calculation does not persist a new /// when the lookup for the complementary temperature reading returns no observations. /// /// [Test] public async Task CalculateTempGradient_WhenOneTemperatureIsMissing_ShouldNotCalculateGradient() { var patientId = ObjectId.GenerateNewId(); var tempPatientObs = new PatientObservation { PatientId = patientId, Name = "Temp_Patient", Time = DateTime.UtcNow, Value = 36.5 }; // Configuramos el mock para que no devuelva ninguna observación para Temp_Incubator _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.CalculateTempGradient(tempPatientObs); _observationServiceMock.Verify(s => s.InsertObservation( It.IsAny(), It.IsAny(), It.IsAny() ), Times.Never()); // Verificamos que InsertObservation no se llama } /// /// Verifies that the intravenous line observation calculation maps to "IntravenousLines", preserves , and ensures is not earlier than the current time when no prior intravenous lines observation exists. /// /// [Test] public async Task CalculateIntravenousLineObservation_ShouldCalculateObservationAndAdjustTimeIfNecessary() { var patientId = ObjectId.GenerateNewId(); var currentTime = DateTime.UtcNow; var obs = new PatientObservation { PatientId = patientId, Name = "IntravenousLine", Value = new PatientIntravenousLinesValue(), Time = currentTime }; _observationServiceMock.Setup(s => s.FindLastIntravenousLinesObservationByLocation(patientId)) .ReturnsAsync([]); PatientObservation? insertedObservation = null; _observationServiceMock.Setup(s => s.InsertObservation(It.IsAny(), It.IsAny(), It.IsAny())) .Callback((ob, _, _) => insertedObservation = ob) .Returns(Task.CompletedTask); _observationServiceMock.Setup(s => s.FindLastObservations(It.IsAny(), 1, It.IsAny>())) .ReturnsAsync([]); await _calculatedObservations.CalculateIntravenousLineObservation(obs); Assert.That(insertedObservation, Is.Not.Null); Action assertions = () => { Assert.That(insertedObservation!.PatientId, Is.EqualTo(patientId)); Assert.That(insertedObservation.Name, Is.EqualTo("IntravenousLines")); Assert.That(insertedObservation.Time, Is.GreaterThanOrEqualTo(currentTime)); // Verificar que la hora no sea anterior a la hora actual }; } /// /// Verifies that correctly calculates and inserts a "Monitor" when the patient has a valid existing observation matching the configured regional brain saturation code or an active treatment. /// /// [Test] public async Task CalculateMonitor_WithValidObservationOrTreatment_ShouldCalculateAndInsertObservation() { var patientId = ObjectId.GenerateNewId(); var monitorObservation = new PatientObservation { PatientId = patientId }; var activeObservation = new PatientObservation { Code = _optionsApiSettings.Value.RegionalBrainSaturation?.FirstOrDefault(), PatientId = patientId }; var activeTreatment = new PatientTreatment { PatientId = patientId }; _observationServiceMock.Setup(s => s.FindLastObservations(It.IsAny(), It.IsAny(), It.IsAny>())) .ReturnsAsync([activeObservation]); _treatmentServiceMock.Setup(s => s.GetActiveTreatmentsByPatient(It.IsAny())) .ReturnsAsync(new List { activeTreatment }); _observationServiceMock.Setup(s => s.InsertObservation(It.IsAny(), true, true)) .Returns(Task.CompletedTask) .Verifiable(); await _calculatedObservations.CalculateMonitor(monitorObservation); _observationServiceMock.Verify(s => s.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "Monitor" && o.CodingSystem == "ADAS" && o.Min != null && Math.Abs(o.Min.Value - 0) < 0.01 && o.Max != null && Math.Abs(o.Max.Value - 3) < 0.01 ), It.IsAny(), It.IsAny()), Times.Once()); } /// /// Verifies that CalculateMonitor calculates and inserts a new Monitor observation for the patient when invoked with a , provided an active treatment exists and a matching non-expired is returned by FindLastObservations. /// /// [Test] public async Task CalculateMonitor_WithPatientTreatment_ShouldCalculateAndInsertObservation() { // Arrange var patientId = ObjectId.GenerateNewId(); var monitorTreatment = new PatientTreatment { PatientId = patientId }; var activeTreatment = new PatientTreatment { PatientId = patientId }; var patientObservation = new PatientObservation { Code = _optionsApiSettings.Value.Transcutaneous?.First(), PatientId = patientId, Expired = false }; // Simular respuestas de los servicios _treatmentServiceMock.Setup(s => s.GetActiveTreatmentsByPatient(It.IsAny())) .ReturnsAsync(new List { activeTreatment }); _observationServiceMock.Setup(s => s.InsertObservation(It.IsAny(), true, true)) .Returns(Task.CompletedTask) .Verifiable(); _observationServiceMock.Setup(s => s.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([patientObservation]); // Act await _calculatedObservations.CalculateMonitor(monitorTreatment); // Assert _observationServiceMock.Verify(s => s.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "Monitor" && o.CodingSystem == "ADAS" && o.Min != null && Math.Abs(o.Min.Value - 0) < 0.01 && o.Max != null && Math.Abs(o.Max.Value - 3) < 0.01 ), It.IsAny(), It.IsAny()), Times.Once()); } /// /// Verifies that does not invoke /// when the supplied /// contains incomplete data (only /// is populated), and the prior observations returned by are empty. /// /// [Test] public async Task CalculateMonitor_WithIncompleteData_ShouldNotInsertObservation() { // Arrange var patientId = ObjectId.GenerateNewId(); var incompleteObservation = new PatientObservation { PatientId = patientId // Proporcionar datos incompletos o irrelevantes }; // Simular respuestas de los servicios _observationServiceMock.Setup(s => s.FindLastObservations(It.IsAny(), It.IsAny(), It.IsAny>())) .ReturnsAsync([]); _observationServiceMock.Setup(s => s.InsertObservation(It.IsAny(), true, true)) .Returns(Task.CompletedTask) .Verifiable(); // Act await _calculatedObservations.CalculateMonitor(incompleteObservation); // Assert _observationServiceMock.Verify( s => s.InsertObservation(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never()); } /// /// Verifies that the surgery expiration check does not insert the when its flag is set to false, ensuring that only expired observations trigger an insertion. /// /// [Test] public async Task CheckSurgeryExpired_WhenNotExpired_DoesNotInsertObservation() { var obs = new PatientObservation { Expired = false }; await _calculatedObservations.CheckSurgeryExpired(obs); _observationServiceMock.Verify(s => s.InsertObservation(It.IsAny(), true, false), Times.Never); } /// /// Tests that when a has expired, inserts a new named "Surgery" with value 0, range 0 to 5, coding system "ADAS", timestamp offset by one second from the original observation, and matching patient identifier and expiry duration. /// /// [Test] public async Task CheckSurgeryExpired_WhenExpired_InsertsCorrectObservation() { var initialTime = DateTime.Now; var obs = new PatientObservation { Expired = true, PatientId = ObjectId.GenerateNewId(), Time = initialTime, Expires = 30 }; await _calculatedObservations.CheckSurgeryExpired(obs); _observationServiceMock.Verify(s => s.InsertObservation(It.Is(o => o.PatientId == obs.PatientId && o.Name == "Surgery" && o.Min != null && Math.Abs(o.Min.Value - 0) < 0.01 && o.Max != null && Math.Abs(o.Max.Value - 5) < 0.01 && o.CodingSystem == "ADAS" && o.Time == initialTime.AddSeconds(1) && o.Value.Equals(0) && // Asegúrate de que la comparación de 'o.Value' sea apropiada para su tipo o.Expires == 30 ), true, false), Times.Once); } /// /// Verifies that inserts a new complexity observation when processing a patient observation in a non-ECMO treatment context, ensuring the active treatments and recent observations are retrieved and the resulting complexity value is persisted. /// /// [Test] public async Task CalculateComplexity_NewObservation_NoECMO_AddsComplexity() { var patientId = ObjectId.GenerateNewId(); var patientTreatment = new PatientTreatment { Id = patientId }; var patientObservation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Name = "Weight_Current", Value = 10 }; var complelxity = new PatientObservation { Id = patientId, Value = 1 }; // Mock de datos de tratamiento activo var activeTreatments = new List { patientTreatment }; _treatmentServiceMock.Setup(m => m.GetActiveTreatmentsByPatient(It.IsAny())) .ReturnsAsync(activeTreatments); // Mock de datos de observación var observations = new List { patientObservation }; _observationServiceMock.Setup(m => m.FindLastObservations(It.IsAny(), 1, It.IsAny>())) .ReturnsAsync(observations); var complexityObservations = new List { complelxity }; _observationServiceMock.Setup(m => m.FindLastObservations(It.IsAny(), 1, It.IsAny>())) .ReturnsAsync(complexityObservations); var obs = patientObservation as BasePatientObservation; var result = await _calculatedObservations.CalculateComplexity(obs); // Verifica que el valor de complejidad calculado sea el esperado Assert.That(result.Name, Is.EqualTo("Weight_Current")); // Verifica que se hayan llamado los métodos esperados en los servicios mockeados _treatmentServiceMock.Verify(m => m.GetActiveTreatmentsByPatient(It.IsAny()), Times.Once); _observationServiceMock.Verify(m => m.FindLastObservations(It.IsAny(), 1, It.IsAny>()), Times.Exactly(3)); _observationServiceMock.Verify(s => s.InsertObservation(It.Is(o => o.PatientId == obs.PatientId && o.Name == "Complexity" && o.CodingSystem == "ADAS" && Equals(o.Value, 7) ), true, false), Times.Once); } /// /// Verifies that when an expired is passed to the complexity calculation, /// no new complexity record is inserted into the database, ensuring that expired observations are excluded /// from contributing to the patient's calculated complexity value. /// /// [Test] public async Task CalculateComplexity_ExpiredObservation_DoesNotAddToComplexity() { // Configuración inicial var patientId = ObjectId.GenerateNewId(); var expiredPatientObservation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Name = "Weight_Current", Value = 10, Expired = true // Observación expirada }; var observations = new List { expiredPatientObservation }; _observationServiceMock.Setup(m => m.FindLastObservations(It.IsAny(), 1, It.IsAny>())) .ReturnsAsync(observations); var obs = expiredPatientObservation as BasePatientObservation; var result = await _calculatedObservations.CalculateComplexity(obs); // Verificaciones Assert.That(result.Name, Is.EqualTo("Weight_Current")); _observationServiceMock.Verify(s => s.InsertObservation(It.Is(o => o.PatientId == obs.PatientId && o.Name == "Complexity" && Equals(o.Value, 0) // Valor de complejidad no debe cambiar ), true, true), Times.Never); // No se debe llamar InsertObservation } /// /// Verifies that when an active treatment includes ECMO, /// preserves the original value and records a derived Complexity observation labeled /// "1 ECMO" for the patient. /// /// [Test] public async Task CalculateComplexity_ECMOActive_AdjustsComplexity() { var code = new Code { Identifier = "705923009" }; // Configuración inicial var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Name = "ECMO", Value = 10 }; var lastObservation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Name = "Surgery", Value = 1 }; var patientTreatment = new PatientTreatment { Id = patientId }; patientTreatment.RequestedGiveCodes.Add(code); // Mock de datos de tratamiento activo var activeTreatments = new List { patientTreatment }; _treatmentServiceMock.Setup(m => m.GetActiveTreatmentsByPatient(It.IsAny())) .ReturnsAsync(activeTreatments); var observations = new List { lastObservation }; _observationServiceMock.Setup(m => m.FindLastObservations(It.IsAny(), 1, It.IsAny>())) .ReturnsAsync(observations); BasePatientObservation obs = observation; var result = await _calculatedObservations.CalculateComplexity(obs); // Verificaciones Assert.That(result.Name, Is.EqualTo("ECMO")); _observationServiceMock.Verify(s => s.InsertObservation(It.Is(o => o.PatientId == obs.PatientId && o.Name == "ECMO" && Equals(o.Value, 10) // Valor de complejidad no debe cambiar ), true, true), Times.Once); _observationServiceMock.Verify(s => s.InsertObservation(It.Is(o => o.PatientId == obs.PatientId && o.Name == "Complexity" && Equals(o.Value, "1 ECMO") ), true, false), Times.Once); } /// /// Verifies that increments the by one second beyond the existing observation when the lookup returns a sharing the same timestamp, patient, and observation name as the supplied instance. /// /// [Test] public async Task CheckObsExistsAndIncrementTime_SameHourObservation_IncrementsTime() { // Configuración inicial var patientId = ObjectId.GenerateNewId(); var initialTime = DateTime.UtcNow; var sameHourObservation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Time = initialTime, Name = "TestObservation" }; var existingObservation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Time = initialTime, // Misma hora que sameHourObservation Name = "TestObservation" }; // Mock del servicio de observación para que retorne una observación existente en la misma hora _observationServiceMock.Setup(m => m.FindLastBeforeDate(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(existingObservation); var obs = sameHourObservation as BasePatientObservation; var result = await _calculatedObservations.CheckObsExistsAndIncrementTime(obs); // Verificaciones var resultObs = result as PatientObservation; Assert.That(resultObs, Is.Not.Null); Assert.That(resultObs!.Time, Is.GreaterThan(initialTime)); // Verifica que el tiempo ha sido incrementado Assert.That(resultObs.Time, Is.EqualTo(existingObservation.Time.AddSeconds(1))); // Verifica que el tiempo se incrementó en 1 segundo } /// /// Verifies that increments the of the supplied by one second and assigns a new when another observation with the same time and already exists for the same . /// /// [Test] public async Task CheckObsWithSameTimeExistsAndIncrementTime_WhenObservationWithSameTimeExists_IncrementsTime() { // Configuración inicial var patientId = ObjectId.GenerateNewId(); var observationTime = DateTime.UtcNow; const string observationName = "TestObservation"; var newObservation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Time = observationTime, Name = observationName }; var existingObservation = new PatientObservation { Id = ObjectId.GenerateNewId(), PatientId = patientId, Time = observationTime, // Misma hora y nombre que newObservation Name = observationName }; // Mock del servicio de observación para que retorne una observación existente con el mismo tiempo y nombre _observationServiceMock.Setup(m => m.FindAnyWithSameDate(patientId, observationTime, observationName)) .ReturnsAsync([existingObservation]); BasePatientObservation obs = newObservation; var result = await _calculatedObservations.CheckObsWithSameTimeExistsAndIncrementTime(obs); // Verificaciones var resultObs = result as PatientObservation; Assert.That(resultObs, Is.Not.Null); using (Assert.EnterMultipleScope()) { { Assert.That(resultObs!.Time, Is.EqualTo(observationTime.AddSeconds(1))); // Verifica que el tiempo se haya incrementado en 1 segundo Assert.That(existingObservation.Id, Is.Not.EqualTo(resultObs.Id)); // Verifica que el Id sea diferente al de la observación existente } ; } } /// /// Verifies that correctly processes a treatment whose notes contain a parental nutrition formulation (comment "NPT" with comment type "formularybaseformulation"), looking up the associated by code, retrieving active treatments and the last medication observation for the patient, and inserting a new with "Medication", "ADAS" and 1. /// /// [Test] public async Task CheckTreatmentMedicines_ProcessesTreatmentCorrectly_WithParentalNutritionMedicine() { var patientId = ObjectId.GenerateNewId(); var code = new Code { Identifier = "705923009" }; var medicationObs = new PatientObservation { PatientId = patientId, Value = 2 }; // Configuración inicial var treatment = new PatientTreatment { PatientId = patientId, Notes = [ new Note { Comment = "NPT", CommentType = "formularybaseformulation" } ], RequestedGiveCodes = [code], RequestedGiveTreatment = "Medicación" }; var medicine = new Medicine { Codes = [code.Identifier] }; var lastMedicationObs = new List { medicationObs }; var expectedMedicines = new List { medicine }; var activeTreatments = new List { treatment }; // Mock de medicineService para que devuelva medicinas esperadas _medicineServiceMock.Setup(m => m.GetByCodeOrNote(It.IsAny>())) .ReturnsAsync(expectedMedicines); _medicineServiceMock.Setup(m => m.GetMedicinesOfTreatments(It.IsAny>())) .ReturnsAsync(expectedMedicines); _treatmentServiceMock.Setup(m => m.GetActiveTreatmentsByPatient(It.IsAny())) .ReturnsAsync(activeTreatments); _observationServiceMock .Setup(m => m.FindLastObservations(It.IsAny(), 1, new List { "Medication" })) .ReturnsAsync(lastMedicationObs); _observationServiceMock.Setup(s => s.FindLastObservations(It.IsAny(), 1, It.IsAny>())) .ReturnsAsync([]); // Otras configuraciones de mock según sea necesario // Llamada al método bajo prueba await _calculatedObservations.CheckTreatmentMedicines(treatment); // Verificaciones // Verifica que las llamadas a los servicios mockeados son como se esperan // Verifica que la lógica de procesamiento de medicamentos es correcta // Puedes usar Assert o Verify de Moq según corresponda // ... _observationServiceMock.Verify(s => s.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "Medication" && o.CodingSystem == "ADAS" && Equals(o.Value, 1) ), true, false), Times.Once); } }